diff --git a/games/monopoly/DiceModalGame.h b/games/monopoly/DiceModalGame.h index ab1f6b4..984a4d7 100644 --- a/games/monopoly/DiceModalGame.h +++ b/games/monopoly/DiceModalGame.h @@ -6,6 +6,8 @@ #include "input_manager.h" #include "MonopolyBoardRenderer.h" #include "ModalButtonHelper.h" +#include +#include class DiceModalGame : public Game { int dice1, dice2; @@ -14,6 +16,13 @@ class DiceModalGame : public Game { int players_count; bool dismissed; + int from_pos; + int correct_destination; + int options[3]; + bool option_visible[3]; + int selected_choice; + bool show_error; + void draw_die(int x, int y, int size, int value) { // Die base renderer->draw_rounded_rectangle(x, y, size, size, 4, true, false); @@ -49,75 +58,139 @@ class DiceModalGame : public Game { public: DiceModalGame(uint16_t width, uint16_t height, LowLevelRenderer* renderer, LowLevelGUI* gui, InputManager* input_manager, int d1, int d2, const BoardTile* from, const BoardTile* to, Player* p, int count) - : Game(width, height, renderer, gui, input_manager), dice1(d1), dice2(d2), from_tile(from), to_tile(to), players(p), players_count(count), dismissed(false) {} + : Game(width, height, renderer, gui, input_manager), dice1(d1), dice2(d2), from_tile(from), to_tile(to), players(p), players_count(count), dismissed(false) { + + // Find from_pos + from_pos = 0; + for(int i=0; i<40; i++) { + if(&MONOPOLY_BOARD[i] == from_tile) { + from_pos = i; + break; + } + } + correct_destination = (from_pos + dice1 + dice2) % BOARD_SIZE; + selected_choice = -1; + show_error = false; + for(int i=0; i<3; i++) option_visible[i] = true; + + // Generate fake options + int fake1 = (from_pos + (rand() % 11 + 2)) % BOARD_SIZE; + if (fake1 == correct_destination) fake1 = (fake1 + 1) % BOARD_SIZE; + + int fake2 = (from_pos + (rand() % 11 + 2)) % BOARD_SIZE; + while (fake2 == correct_destination || fake2 == fake1) { + fake2 = (from_pos + (rand() % 11 + 2)) % BOARD_SIZE; + } + + int rand_pos = rand() % 3; + if (rand_pos == 0) { + options[0] = correct_destination; + options[1] = fake1; + options[2] = fake2; + } else if (rand_pos == 1) { + options[0] = fake1; + options[1] = correct_destination; + options[2] = fake2; + } else { + options[0] = fake1; + options[1] = fake2; + options[2] = correct_destination; + } + } + void init() override { dismissed = false; + selected_choice = -1; + show_error = false; + for(int i=0; i<3; i++) option_visible[i] = true; ModalButtonHelper::set_monopoly_regions(input_manager, width, height); } Type get_type() const override { return Type::MONOPOLY_DICE; } + bool update(const InputEvent& event) override { - // Only B dismisses now, so A can still be used for "change action" (even if it does nothing here) + if (event.type == INPUT_BUTTON_0) { // Select + int start_choice = selected_choice; + do { + selected_choice = (selected_choice + 1) % 3; + } while (!option_visible[selected_choice] && selected_choice != start_choice); + + show_error = false; + return true; + } + if (event.type == INPUT_BUTTON_1) { - dismissed = true; + if (selected_choice == -1 || !option_visible[selected_choice]) return false; + + if (options[selected_choice] == correct_destination) { + dismissed = true; + } else { + option_visible[selected_choice] = false; + show_error = true; + selected_choice = -1; + } return true; } return false; } + void draw() override { renderer->clear_buffer(); - MonopolyBoardRenderer::draw_board_perimeter(renderer, width, height, players, players_count, (to_tile ? -1 /* or some index */ : -1)); // Keep it simple for now or pass relevant pos - // Let's pass the destination position to highlight it during the dice roll - int target_pos = -1; - for(int i=0; i<40; i++) if(&MONOPOLY_BOARD[i] == to_tile) target_pos = i; - MonopolyBoardRenderer::draw_board_perimeter(renderer, width, height, players, players_count, target_pos); + // Draw the restricted board perimeter + MonopolyBoardRenderer::draw_board_perimeter(renderer, width, height, players, players_count, -1, -1, from_pos, (from_pos + 12) % BOARD_SIZE); // --- Inner UI (Center Area) --- int cw = width / 7; int ch = height / 7; - int ix = cw + 2, iy = ch + 2; - int iw = width - 2 * cw - 4, ih = height - 2 * ch - 4; + int ix = cw + 2; + int iy = ch + 2; + int iw = width - 2 * cw - 4; + int ih = height - 2 * ch - 4; // Window background (White box) - renderer->draw_filled_rectangle(ix, iy, iw, ih, false, 0); // Clear central area - renderer->draw_rectangle(ix, iy, iw, ih, true, 1); // 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 - renderer->draw_filled_rectangle(ix + 2, iy + 2, iw - 4, 30, true, 1); + renderer->draw_filled_rectangle(ix + 4, iy + 4, iw - 8, 30, true, 1); renderer->set_text_color(false); - renderer->draw_string_scaled(ix + (iw - (int)strlen("==DICE ROLL==") * 12) / 2, iy + 10, "==DICE ROLL==", 2); + renderer->draw_string_scaled(ix + (iw - (int)strlen("DICE CHALLENGE") * 12) / 2, iy + 10, "DICE CHALLENGE", 2); renderer->set_text_color(true); // Dice - int dice_size = 50; + int dice_size = 40; int dice_y = iy + 45; - draw_die(ix + iw / 2 - dice_size - 10, dice_y, dice_size, dice1); - draw_die(ix + iw / 2 + 10, dice_y, dice_size, dice2); + draw_die(ix + 20, dice_y, dice_size, dice1); + draw_die(ix + 20 + dice_size + 10, dice_y, dice_size, dice2); - // Total - char buf[32]; - snprintf(buf, sizeof(buf), "TOTAL: %d", dice1 + dice2); - renderer->draw_string_scaled(ix + (iw - 100) / 2, dice_y + dice_size + 10, buf, 2); + // --- Prompt --- + int prompt_y = dice_y + dice_size + 10; + renderer->draw_string_scaled(ix + 20, prompt_y, "WHERE WILL YOU LAND?", 1); - // Movement info - int info_y = dice_y + dice_size + 30; - char move_buf[64]; - if (from_tile && to_tile) { - snprintf(move_buf, sizeof(move_buf), "FROM: %s", from_tile->name); - renderer->draw_string_scaled(ix + 10, info_y, move_buf, 2); - info_y += 24; - snprintf(move_buf, sizeof(move_buf), "TO: %s", to_tile->name); - renderer->draw_string_scaled(ix + 10, info_y, move_buf, 2); + // --- Options --- + int opt_y = prompt_y + 20; + for (int i = 0; i < 3; i++) { + if (!option_visible[i]) { + opt_y += 25; + continue; + } + char opt_buf[64]; + snprintf(opt_buf, sizeof(opt_buf), "%s %d: %s", (selected_choice == i ? ">" : " "), i+1, MONOPOLY_BOARD[options[i]].name); + + if (selected_choice == i) renderer->draw_filled_rectangle(ix + 15, opt_y - 2, iw - 30, 22, true, 1); + if (selected_choice == i) renderer->set_text_color(false); + + // Truncate name if too long + if (strlen(opt_buf) > 30) opt_buf[30] = '\0'; + renderer->draw_string_scaled(ix + 20, opt_y, opt_buf, 2); + renderer->set_text_color(true); + opt_y += 25; } - // Button - int btn_w = 120, btn_h = 25; - int btn_x = ix + (iw - btn_w) / 2; - int btn_y = iy + ih - 35; - renderer->draw_filled_rectangle(btn_x, btn_y, btn_w, btn_h, true, 1); - renderer->set_text_color(false); - renderer->draw_string_scaled(btn_x + 5, btn_y + 5, "> CONTINUE", 2); - renderer->set_text_color(true); + if (show_error) { + renderer->draw_string_scaled(ix + (iw - 10 * 12) / 2, iy + ih - 30, "TRY AGAIN!", 2); + } ModalButtonHelper::draw_virtual_buttons(renderer, input_manager); } diff --git a/games/monopoly/MonopolyBoardRenderer.h b/games/monopoly/MonopolyBoardRenderer.h index c8b50c3..b208346 100644 --- a/games/monopoly/MonopolyBoardRenderer.h +++ b/games/monopoly/MonopolyBoardRenderer.h @@ -117,34 +117,43 @@ public: } } - static void draw_board_perimeter(LowLevelRenderer* renderer, int width, int height, Player* players, int players_count, int currentPlayerPos = -1, int observer_idx = -1) { + static void draw_board_perimeter(LowLevelRenderer* renderer, int width, int height, Player* players, int players_count, int currentPlayerPos = -1, int observer_idx = -1, int limit_start = -1, int limit_end = -1) { int cw = width / 7; // Corner width int ch = height / 7; // Corner height int rw = (width - 2 * cw) / 9; // Regular tile width int rh = (height - 2 * ch) / 9; // Regular tile height + auto should_draw = [&](int index) { + if (limit_start == -1 || limit_end == -1) return true; + if (limit_start <= limit_end) { + return index >= limit_start && index <= limit_end; + } else { + return index >= limit_start || index <= limit_end; + } + }; + // --- Bottom Row: 0 to 10 (Right to Left) --- - draw_tile(renderer, width - cw, height - ch, cw, ch, 0, true, players, players_count, 0, currentPlayerPos, observer_idx); // GO + if (should_draw(0)) draw_tile(renderer, width - cw, height - ch, cw, ch, 0, true, players, players_count, 0, currentPlayerPos, observer_idx); // GO for (int i = 1; i < 10; ++i) { - draw_tile(renderer, width - cw - i * rw, height - ch, rw, ch, i, false, players, players_count, 0, currentPlayerPos, observer_idx); + if (should_draw(i)) draw_tile(renderer, width - cw - i * rw, height - ch, rw, ch, i, false, players, players_count, 0, currentPlayerPos, observer_idx); } - draw_tile(renderer, 0, height - ch, cw, ch, 10, true, players, players_count, 1, currentPlayerPos, observer_idx); // JAIL + if (should_draw(10)) draw_tile(renderer, 0, height - ch, cw, ch, 10, true, players, players_count, 1, currentPlayerPos, observer_idx); // JAIL // --- Left Column: 11 to 19 (Bottom to Top) --- for (int i = 11; i < 20; ++i) { - draw_tile(renderer, 0, height - ch - (i - 10) * rh, cw, rh, i, false, players, players_count, 1, currentPlayerPos, observer_idx); + if (should_draw(i)) draw_tile(renderer, 0, height - ch - (i - 10) * rh, cw, rh, i, false, players, players_count, 1, currentPlayerPos, observer_idx); } // --- Top Row: 20 to 30 (Left to Right) --- - draw_tile(renderer, 0, 0, cw, ch, 20, true, players, players_count, 2, currentPlayerPos, observer_idx); // FREE PARKING + if (should_draw(20)) draw_tile(renderer, 0, 0, cw, ch, 20, true, players, players_count, 2, currentPlayerPos, observer_idx); // FREE PARKING for (int i = 21; i < 30; ++i) { - draw_tile(renderer, cw + (i - 21) * rw, 0, rw, ch, i, false, players, players_count, 2, currentPlayerPos, observer_idx); + if (should_draw(i)) draw_tile(renderer, cw + (i - 21) * rw, 0, rw, ch, i, false, players, players_count, 2, currentPlayerPos, observer_idx); } - draw_tile(renderer, width - cw, 0, cw, ch, 30, true, players, players_count, 3, currentPlayerPos, observer_idx); // GO TO JAIL + if (should_draw(30)) draw_tile(renderer, width - cw, 0, cw, ch, 30, true, players, players_count, 3, currentPlayerPos, observer_idx); // GO TO JAIL // --- Right Column: 31 to 39 (Top to Bottom) --- for (int i = 31; i < 40; ++i) { - draw_tile(renderer, width - cw, ch + (i - 31) * rh, cw, rh, i, false, players, players_count, 3, currentPlayerPos, observer_idx); + if (should_draw(i)) draw_tile(renderer, width - cw, ch + (i - 31) * rh, cw, rh, i, false, players, players_count, 3, currentPlayerPos, observer_idx); } } };