219 lines
8.8 KiB
C++
219 lines
8.8 KiB
C++
// ============================================================================
|
|
// MONOPOLY GAME IMPLEMENTATION (for custom console)
|
|
// ============================================================================
|
|
// Refactored from console version to use Game interface and rendering/input system
|
|
|
|
#include "monopoly_game.h"
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
#include "player.h"
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
|
|
// --- Constructor ---
|
|
MonopolyGame::MonopolyGame(uint16_t width, uint16_t height, LowLevelRenderer* renderer, LowLevelGUI* gui, InputManager* input_manager)
|
|
: Game(width, height, renderer, gui, input_manager) {
|
|
players_count = 2;
|
|
current_player_idx = 0;
|
|
has_rolled = false;
|
|
double_rolls = 0;
|
|
just_sent_to_jail = false;
|
|
}
|
|
|
|
// --- Initialize game state ---
|
|
void MonopolyGame::init() {
|
|
// Hardcoded 2 players for minimal version
|
|
init_player(&players[0], 0, "Elias", "Top Hat");
|
|
init_player(&players[1], 1, "Adolfo", "Racecar");
|
|
players_count = 2;
|
|
current_player_idx = 0;
|
|
has_rolled = false;
|
|
double_rolls = 0;
|
|
just_sent_to_jail = false;
|
|
selected_action = 0;
|
|
// TODO: Reset all board state, property ownership, etc.
|
|
}
|
|
|
|
// --- Handle input events (minimal: roll, buy, end turn) ---
|
|
bool MonopolyGame::update(const InputEvent& event) {
|
|
Player* p = &players[current_player_idx];
|
|
bool needs_redraw = false;
|
|
|
|
// If modal is open, any button closes it
|
|
if (show_property_modal) {
|
|
if (event.type == INPUT_BUTTON_0 || event.type == INPUT_BUTTON_1) {
|
|
show_property_modal = false;
|
|
modal_property_index = -1;
|
|
needs_redraw = true;
|
|
}
|
|
return needs_redraw;
|
|
}
|
|
|
|
switch (event.type) {
|
|
case INPUT_BUTTON_0: // Cycle options
|
|
selected_action = (selected_action + 1) % ACTION_COUNT;
|
|
needs_redraw = true;
|
|
break;
|
|
case INPUT_BUTTON_1: // Select option
|
|
switch (selected_action) {
|
|
case 0: // Roll
|
|
if (!has_rolled && !p->is_in_jail) {
|
|
int dice1 = (rand() % 6) + 1;
|
|
int dice2 = (rand() % 6) + 1;
|
|
int total = dice1 + dice2;
|
|
int old_pos = p->position;
|
|
p->position = (p->position + total) % BOARD_SIZE;
|
|
if (p->position < old_pos) p->balance += 200;
|
|
has_rolled = true;
|
|
needs_redraw = true;
|
|
// Show property modal if landed on property/railroad/utility
|
|
const BoardTile* landed = &MONOPOLY_BOARD[p->position];
|
|
if (landed->type == TILE_PROPERTY || landed->type == TILE_RAILROAD || landed->type == TILE_UTILITY) {
|
|
show_property_modal = true;
|
|
modal_property_index = p->position;
|
|
}
|
|
// TODO: Handle doubles, jail, landing effects
|
|
}
|
|
break;
|
|
case 1: // Buy
|
|
if (has_rolled) {
|
|
const BoardTile* tile = &MONOPOLY_BOARD[p->position];
|
|
if ((tile->type == TILE_PROPERTY || tile->type == TILE_RAILROAD || tile->type == TILE_UTILITY) && p->balance >= tile->cost) {
|
|
bool owned = false;
|
|
for (int i = 0; i < p->property_count; ++i) {
|
|
if (p->properties_owned[i] == p->position) owned = true;
|
|
}
|
|
if (!owned) {
|
|
p->balance -= tile->cost;
|
|
p->properties_owned[p->property_count++] = p->position;
|
|
needs_redraw = true;
|
|
}
|
|
}
|
|
// TODO: Check for ownership by other players
|
|
}
|
|
break;
|
|
case 2: // End Turn
|
|
if (has_rolled) {
|
|
current_player_idx = (current_player_idx + 1) % players_count;
|
|
has_rolled = false;
|
|
double_rolls = 0;
|
|
just_sent_to_jail = false;
|
|
needs_redraw = true;
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return needs_redraw;
|
|
}
|
|
|
|
// --- Draw game state (minimal: player info, current tile, actions) ---
|
|
void MonopolyGame::draw() {
|
|
Player* p = &players[current_player_idx];
|
|
const BoardTile* tile = &MONOPOLY_BOARD[p->position];
|
|
|
|
// Title
|
|
renderer->draw_string_scaled(10, 10, "Monopoly (Minimal)", 2);
|
|
|
|
// --- Player Stats (Right Side) ---
|
|
int stats_x = width - 180;
|
|
int y = 20;
|
|
char buf[128];
|
|
// Name (Big)
|
|
renderer->draw_string_scaled(stats_x, y, p->name, 2);
|
|
y += 40;
|
|
// Money
|
|
snprintf(buf, sizeof(buf), "$%d", p->balance);
|
|
renderer->draw_string_scaled(stats_x, y, buf, 2);
|
|
y += 30;
|
|
// Properties
|
|
int prop_count = 0;
|
|
for (int i = 0; i < p->property_count; ++i) {
|
|
int prop_idx = p->properties_owned[i];
|
|
if (prop_idx >= 0 && MONOPOLY_BOARD[prop_idx].type == TILE_PROPERTY) prop_count++;
|
|
}
|
|
snprintf(buf, sizeof(buf), "Properties: %d", prop_count);
|
|
renderer->draw_string_scaled(stats_x, y, buf, 2);
|
|
y += 30;
|
|
// Monopoly count
|
|
int monopoly_count = 0;
|
|
// For each group, check if player owns all properties in group
|
|
for (int group = 1; group <= 8; ++group) {
|
|
int group_total = 0, group_owned = 0;
|
|
for (int i = 0; i < BOARD_SIZE; ++i) {
|
|
if (MONOPOLY_BOARD[i].type == TILE_PROPERTY && MONOPOLY_BOARD[i].group[0] == group) {
|
|
group_total++;
|
|
for (int j = 0; j < p->property_count; ++j) {
|
|
if (p->properties_owned[j] == i) group_owned++;
|
|
}
|
|
}
|
|
}
|
|
if (group_total > 0 && group_total == group_owned) monopoly_count++;
|
|
}
|
|
snprintf(buf, sizeof(buf), "Monopolies: %d", monopoly_count);
|
|
renderer->draw_string_scaled(stats_x, y, buf, 2);
|
|
|
|
// --- Main Info (Left Side) ---
|
|
snprintf(buf, sizeof(buf), "Player: %s ($%d)", p->name, p->balance);
|
|
renderer->draw_string_scaled(10, 30, buf, 2);
|
|
|
|
snprintf(buf, sizeof(buf), "Location: %s", tile->name);
|
|
renderer->draw_string_scaled(10, 50, buf, 2);
|
|
|
|
// Show property modal window if needed
|
|
if (show_property_modal && modal_property_index >= 0) {
|
|
const BoardTile* mprop = &MONOPOLY_BOARD[modal_property_index];
|
|
int win_w = 320, win_h = 180;
|
|
int win_x = (width - win_w) / 2, win_y = (height - win_h) / 2;
|
|
LowLevelWindow* win = gui->draw_new_window(win_x, win_y, win_w, win_h, "Property Info");
|
|
// gui->current_font = renderer->get_current_font();
|
|
int py = win_y + 30;
|
|
char pbuf[128];
|
|
if (mprop->type == TILE_PROPERTY) {
|
|
snprintf(pbuf, sizeof(pbuf), "%s", mprop->name);
|
|
renderer->draw_string_scaled(win_x + 20, py, pbuf, 2);
|
|
py += 30;
|
|
snprintf(pbuf, sizeof(pbuf), "Color: %s", mprop->color ? mprop->color : "-");
|
|
renderer->draw_string_scaled(win_x + 20, py, pbuf, 2);
|
|
py += 25;
|
|
snprintf(pbuf, sizeof(pbuf), "Cost: $%d", mprop->cost);
|
|
renderer->draw_string_scaled(win_x + 20, py, pbuf, 2);
|
|
py += 25;
|
|
snprintf(pbuf, sizeof(pbuf), "Rent: $%d", mprop->rent[0]);
|
|
renderer->draw_string_scaled(win_x + 20, py, pbuf, 2);
|
|
py += 25;
|
|
snprintf(pbuf, sizeof(pbuf), "House Cost: $%d", mprop->house_cost);
|
|
renderer->draw_string_scaled(win_x + 20, py, pbuf, 2);
|
|
} else if (mprop->type == TILE_RAILROAD || mprop->type == TILE_UTILITY) {
|
|
snprintf(pbuf, sizeof(pbuf), "%s", mprop->name);
|
|
renderer->draw_string_scaled(win_x + 20, py, pbuf, 2);
|
|
py += 30;
|
|
snprintf(pbuf, sizeof(pbuf), "Cost: $%d", mprop->cost);
|
|
renderer->draw_string_scaled(win_x + 20, py, pbuf, 2);
|
|
}
|
|
renderer->draw_string_scaled(win_x + 20, win_y + win_h - 40, "Press any button...", 2);
|
|
return;
|
|
}
|
|
|
|
// Draw action menu (highlight selected)
|
|
const char* actions[ACTION_COUNT] = {"Roll Dice", "Buy Property", "End Turn"};
|
|
for (int i = 0; i < ACTION_COUNT; ++i) {
|
|
int y = height - 80 + i * 20;
|
|
snprintf(buf, sizeof(buf), "%s%s", (i == selected_action) ? "> " : " ", actions[i]);
|
|
renderer->draw_string_scaled(10, y, buf, 2);
|
|
}
|
|
|
|
// renderer->draw_string_scaled(10, height - 20, "BTN0: Next Option BTN1: Select", 2);
|
|
|
|
// TODO: Draw board, all players, property ownership, jail, chance, etc.
|
|
// TODO: Add win/lose/game over conditions
|
|
// TODO: Add touch support, more UI, etc.
|
|
}
|