// BoardModalGame.h #pragma once #include "../../lib/game.h" #include "../../display/low_level_render.h" #include "../../display/low_level_gui.h" #include "input_manager.h" #include "monopoly_board.h" #include "player.h" #include "MonopolyBoardRenderer.h" class BoardModalGame : public Game { bool dismissed; Player* players; int players_count; int observer_idx; public: BoardModalGame(uint16_t width, uint16_t height, LowLevelRenderer* renderer, LowLevelGUI* gui, InputManager* input_manager, Player* p, int count, int current_idx) : Game(width, height, renderer, gui, input_manager), dismissed(false), players(p), players_count(count), observer_idx(current_idx) {} void init() override { dismissed = false; } Type get_type() const override { return Type::MONOPOLY_BOARD; } bool update(const InputEvent& event) override { // Any button dismisses the board view if (event.type == INPUT_BUTTON_0 || event.type == INPUT_BUTTON_1) { dismissed = true; return true; } return false; } void draw() override { renderer->clear_buffer(); MonopolyBoardRenderer::draw_board_perimeter(renderer, width, height, players, players_count, -1, observer_idx); // --- Inner UI --- int cw = width / 7; int ch = height / 7; int ix = cw + 5, iy = ch + 5; int iw = width - 2 * cw - 10, ih = height - 2 * ch - 10; // Window Background (Double Border) renderer->draw_filled_rectangle(ix, iy, iw, ih, false, 0); renderer->draw_rectangle(ix, iy, iw, ih, true, 2); renderer->draw_rectangle(ix + 3, iy + 3, iw - 6, ih - 6, true, 1); // Header Title Bar renderer->draw_filled_rectangle(ix + 4, iy + 4, iw - 8, 30, true, 1); renderer->set_text_color(false); renderer->draw_string_scaled(ix + (iw - 12 * 12) / 2, iy + 10, "BOARD STATUS", 2); renderer->set_text_color(true); // Calculate wealth for all players to find the leader int leader_idx = 0; int max_wealth = -1; int p_wealth[MAX_PLAYERS]; for (int i = 0; i < players_count; ++i) { int total = players[i].balance; for (int j = 0; j < players[i].property_count; ++j) { total += MONOPOLY_BOARD[players[i].properties_owned[j]].cost; } p_wealth[i] = total; if (total > max_wealth) { max_wealth = total; leader_idx = i; } } // --- Current Player Section (Observer) --- Player& curr = players[observer_idx]; char buf[128]; int stats_y = iy + 45; // Name with token snprintf(buf, sizeof(buf), "[%c] %s", (curr.token ? curr.token[0] : 'P'), curr.name); renderer->draw_string_scaled(ix + 12, stats_y, buf, 2); stats_y += 20; // Split Balance and Total Wealth into two lines snprintf(buf, sizeof(buf), "CASH: $%d", curr.balance); renderer->draw_string_scaled(ix + 15, stats_y, buf, 2); stats_y += 20; snprintf(buf, sizeof(buf), "TOTAL: $%d", p_wealth[observer_idx]); renderer->draw_string_scaled(ix + 15, stats_y, buf, 2); stats_y += 25; // Separator Line renderer->draw_line(ix + 10, stats_y, ix + iw - 10, stats_y, true); stats_y += 10; // --- Standings Header --- renderer->draw_string_scaled(ix + 10, stats_y, "STANDINGS:", 1); stats_y += 15; for (int i = 0; i < players_count; ++i) { bool is_leader = (i == leader_idx); bool is_observer = (i == observer_idx); // Format: *[T] Name $Wealth if (is_leader) { snprintf(buf, sizeof(buf), "*%c:%-6s $%d", (players[i].token ? players[i].token[0] : 'P'), players[i].name, p_wealth[i]); } else { snprintf(buf, sizeof(buf), " %c:%-6s $%d", (players[i].token ? players[i].token[0] : 'P'), players[i].name, p_wealth[i]); } if (is_observer) { renderer->draw_filled_rectangle(ix + 8, stats_y - 2, iw - 16, 12, true, 1); renderer->set_text_color(false); } renderer->draw_string_scaled(ix + 12, stats_y, buf, 1); if (is_observer) renderer->set_text_color(true); stats_y += 13; } renderer->draw_string_scaled(ix + (iw - 12 * 6) / 2, iy + ih - 15, "PRESS BUTTON", 1); } public: bool is_dismissed() const { return dismissed; } };