// ============================================================================ // 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 #include // --- 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. }