From c6d7bd6c8c476f268776af785e94e42e112eb2d1 Mon Sep 17 00:00:00 2001 From: Adolfo Reyna Date: Sat, 31 Jan 2026 22:46:26 -0500 Subject: [PATCH] monopoly Main UI Changes --- emulator/basic1_emulator | Bin 162608 -> 164672 bytes games/monopoly/monopoly_game.cpp | 366 +++++++++++++++++++++++++------ games/monopoly/monopoly_game.h | 15 +- lib/game.h | 4 +- 4 files changed, 321 insertions(+), 64 deletions(-) diff --git a/emulator/basic1_emulator b/emulator/basic1_emulator index 089c710028ac1f17c44ea05551be7aaad2a3a900..b168b168790f2a66ff55ec888b5c14030849666d 100755 GIT binary patch delta 37272 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 D{?|1T diff --git a/games/monopoly/monopoly_game.cpp b/games/monopoly/monopoly_game.cpp index 34e40ac..97a3d43 100644 --- a/games/monopoly/monopoly_game.cpp +++ b/games/monopoly/monopoly_game.cpp @@ -20,6 +20,8 @@ extern "C" { #include "DiceModalGame.h" #include "PropertyModalGame.h" #include "BoardModalGame.h" +#include "ChanceModalGame.h" +#include "CommunityChestModalGame.h" #include "MonopolyBoardRenderer.h" @@ -45,15 +47,53 @@ void MonopolyGame::init() { just_sent_to_jail = false; selected_action = 0; srand(time(NULL)); + shuffle_chance_deck(); + shuffle_community_deck(); if (active_modal) { delete active_modal; active_modal = nullptr; } // TODO: Reset all board state, property ownership, etc. } +void MonopolyGame::shuffle_chance_deck() { + for (int i = 0; i < CHANCE_DECK_SIZE; i++) { + chance_deck[i] = i; + } + for (int i = CHANCE_DECK_SIZE - 1; i > 0; i--) { + int j = rand() % (i + 1); + int temp = chance_deck[i]; + chance_deck[i] = chance_deck[j]; + chance_deck[j] = temp; + } + current_chance_idx = 0; +} + +void MonopolyGame::shuffle_community_deck() { + for (int i = 0; i < COMMUNITY_DECK_SIZE; i++) { + community_deck[i] = i; + } + for (int i = COMMUNITY_DECK_SIZE - 1; i > 0; i--) { + int j = rand() % (i + 1); + int temp = community_deck[i]; + community_deck[i] = community_deck[j]; + community_deck[j] = temp; + } + current_community_idx = 0; +} + // --- Handle input events (minimal: roll, buy, end turn) --- bool MonopolyGame::update(const InputEvent& event) { Player* p = &players[current_player_idx]; bool needs_redraw = false; + // Calculate available actions + int menu_count = 0; + if (!has_rolled) { + menu_count++; // Roll Dice + if (p->is_in_jail) menu_count++; // Pay $50 + } else { + menu_count++; // End Turn + } + menu_count++; // View Board + // If a modal is active, delegate input and check for dismissal if (active_modal) { bool modal_redraw = active_modal->update(event); @@ -63,7 +103,9 @@ bool MonopolyGame::update(const InputEvent& event) { DiceModalGame* dice_modal = (active_modal->get_type() == Game::Type::MONOPOLY_DICE) ? static_cast(active_modal) : nullptr; PropertyModalGame* prop_modal = (active_modal->get_type() == Game::Type::MONOPOLY_PROPERTY) ? static_cast(active_modal) : nullptr; BoardModalGame* board_modal = (active_modal->get_type() == Game::Type::MONOPOLY_BOARD) ? static_cast(active_modal) : nullptr; - + ChanceModalGame* chance_modal = (active_modal->get_type() == Game::Type::MONOPOLY_CHANCE) ? static_cast(active_modal) : nullptr; + CommunityChestModalGame* community_modal = (active_modal->get_type() == Game::Type::MONOPOLY_COMMUNITY_CHEST) ? static_cast(active_modal) : nullptr; + if (dice_modal && dice_modal->is_dismissed()) { delete active_modal; active_modal = nullptr; @@ -88,9 +130,164 @@ bool MonopolyGame::update(const InputEvent& event) { bool can_afford = (p->balance >= MONOPOLY_BOARD[modal_property_index].cost); active_modal = new PropertyModalGame(width, height, renderer, gui, input_manager, &MONOPOLY_BOARD[modal_property_index], is_owned, owner_name, owner_id, can_afford, players, players_count); modal_property_index = -1; + } else if (last_drawn_chance_idx >= 0) { + active_modal = new ChanceModalGame(width, height, renderer, gui, input_manager, &CHANCE_DECK[last_drawn_chance_idx], players, players_count, p->position); + // We'll apply the effect when ChanceModal is dismissed + } else if (last_drawn_community_idx >= 0) { + active_modal = new CommunityChestModalGame(width, height, renderer, gui, input_manager, &COMMUNITY_DECK[last_drawn_community_idx], players, players_count, p->position); + // We'll apply the effect when CommunityChestModal is dismissed } return needs_redraw; - } else if (prop_modal && prop_modal->is_dismissed()) { + } else if (chance_modal && chance_modal->is_dismissed()) { + const ChanceCard* card = &CHANCE_DECK[last_drawn_chance_idx]; + last_drawn_chance_idx = -1; + + // Apply card effects + bool position_changed = false; + int old_pos = p->position; + + switch (card->type) { + case CHANCE_EARN: + p->balance += card->value; + break; + case CHANCE_SPEND: + p->balance -= card->value; + break; + case CHANCE_ADVANCE: { + int target = card->value; + if (target == TARGET_NEAREST_UTILITY) { + target = (p->position + 1) % BOARD_SIZE; + while (MONOPOLY_BOARD[target].type != TILE_UTILITY) { + target = (target + 1) % BOARD_SIZE; + } + force_utility_10x = true; + } else if (target == TARGET_NEAREST_RAILROAD) { + target = (p->position + 1) % BOARD_SIZE; + while (MONOPOLY_BOARD[target].type != TILE_RAILROAD) { + target = (target + 1) % BOARD_SIZE; + } + rent_multiplier = 2; + } + p->position = target; + if (p->position < old_pos) p->balance += 200; + position_changed = true; + break; + } + case CHANCE_BACK: + p->position = (p->position - card->value + BOARD_SIZE) % BOARD_SIZE; + position_changed = true; + break; + case CHANCE_JAIL: + p->position = 10; // Jail + p->is_in_jail = true; + break; + case CHANCE_JAIL_FREE: + p->jail_free_cards++; + break; + case CHANCE_SPEND_EACH_PLAYER: + for (int i = 0; i < players_count; i++) { + if (i != (int)current_player_idx) { + p->balance -= card->value; + players[i].balance += card->value; + } + } + break; + case CHANCE_REPAIRS: + // For now, simplify or implement if houses are tracked + break; + } + + delete active_modal; + active_modal = nullptr; + needs_redraw = true; + + if (position_changed) { + // If we moved, check if we landed on a property + const BoardTile* landed = &MONOPOLY_BOARD[p->position]; + if (landed->type == TILE_PROPERTY || landed->type == TILE_RAILROAD || landed->type == TILE_UTILITY) { + bool is_owned = false; + const char* owner_name = nullptr; + int owner_id = -1; + for (int i = 0; i < players_count; ++i) { + for (int j = 0; j < players[i].property_count; ++j) { + if (players[i].properties_owned[j] == p->position) { + is_owned = true; + owner_name = players[i].name; + owner_id = i; + break; + } + } + } + bool can_afford = (p->balance >= landed->cost); + active_modal = new PropertyModalGame(width, height, renderer, gui, input_manager, landed, is_owned, owner_name, owner_id, can_afford, players, players_count); + } + } + return needs_redraw; + } else if (community_modal && community_modal->is_dismissed()) { + const CommunityCard* card = &COMMUNITY_DECK[last_drawn_community_idx]; + last_drawn_community_idx = -1; + + bool position_changed = false; + int old_pos = p->position; + + switch (card->type) { + case COMMUNITY_EARN: + p->balance += card->value; + break; + case COMMUNITY_SPEND: + p->balance -= card->value; + break; + case COMMUNITY_ADVANCE: + p->position = card->value; + if (p->position < old_pos) p->balance += 200; + position_changed = true; + break; + case COMMUNITY_JAIL: + p->position = 10; + p->is_in_jail = true; + break; + case COMMUNITY_JAIL_FREE: + p->jail_free_cards++; + break; + case COMMUNITY_EARN_EACH_PLAYER: + for (int i = 0; i < players_count; i++) { + if (i != (int)current_player_idx) { + p->balance += card->value; + players[i].balance -= card->value; + } + } + break; + case COMMUNITY_REPAIRS: + // p->balance -= (houses * card->value) + (hotels * card->value2); + break; + } + + delete active_modal; + active_modal = nullptr; + needs_redraw = true; + + if (position_changed) { + const BoardTile* landed = &MONOPOLY_BOARD[p->position]; + if (landed->type == TILE_PROPERTY || landed->type == TILE_RAILROAD || landed->type == TILE_UTILITY) { + bool is_owned = false; + const char* owner_name = nullptr; + int owner_id = -1; + for (int i = 0; i < players_count; ++i) { + for (int j = 0; j < players[i].property_count; ++j) { + if (players[i].properties_owned[j] == p->position) { + is_owned = true; + owner_name = players[i].name; + owner_id = i; + break; + } + } + } + bool can_afford = (p->balance >= landed->cost); + active_modal = new PropertyModalGame(width, height, renderer, gui, input_manager, landed, is_owned, owner_name, owner_id, can_afford, players, players_count); + } + } + return needs_redraw; + } else if (prop_modal && prop_modal->is_dismissed()) { if (prop_modal->wants_to_buy()) { const BoardTile* tile = &MONOPOLY_BOARD[p->position]; if (p->balance >= tile->cost) { @@ -137,15 +334,25 @@ bool MonopolyGame::update(const InputEvent& event) { } } } - rent = (utility_count == 2) ? (total_dice * 10) : (total_dice * 4); + if (force_utility_10x) { + rent = total_dice * 10; + } else { + rent = (utility_count == 2) ? (total_dice * 10) : (total_dice * 4); + } } + rent *= rent_multiplier; + int o_id = prop_modal->get_owner_id(); if (o_id != -1 && (int)current_player_idx != o_id) { p->balance -= rent; players[o_id].balance += rent; } } + // Reset multipliers + rent_multiplier = 1; + force_utility_10x = false; + delete active_modal; active_modal = nullptr; needs_redraw = true; @@ -158,54 +365,90 @@ bool MonopolyGame::update(const InputEvent& event) { } switch (event.type) { - case INPUT_BUTTON_0: // Cycle options - selected_action = (selected_action + 1) % ACTION_COUNT; + case INPUT_BUTTON_0: + selected_action = (selected_action + 1) % menu_count; needs_redraw = true; break; - case INPUT_BUTTON_1: // Select option - switch (selected_action) { - case 0: // Context Action - if (!has_rolled) { - // Roll Dice - if (!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; - // Store dice values and show dice modal - last_dice1 = dice1; - last_dice2 = dice2; - if (active_modal) delete active_modal; - active_modal = new DiceModalGame(width, height, renderer, gui, input_manager, dice1, dice2, &MONOPOLY_BOARD[old_pos], &MONOPOLY_BOARD[p->position], players, players_count); - // 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) { - modal_property_index = p->position; - } - } + case INPUT_BUTTON_1: + if (p->is_in_jail && !has_rolled && selected_action == 1) { + p->balance -= 50; + p->is_in_jail = false; + p->jail_turns = 0; + selected_action = 0; + needs_redraw = true; + return true; + } + if (active_modal) delete active_modal; + if (selected_action == (menu_count - 1)) { + active_modal = new BoardModalGame(width, height, renderer, gui, input_manager, players, players_count); + needs_redraw = true; + } else if (!has_rolled) { +roll_dice_logic: + int d1 = (rand() % 6) + 1; + int d2 = (rand() % 6) + 1; + bool is_db = (d1 == d2); + int old_pos = p->position; + if (p->is_in_jail) { + if (is_db) { + p->is_in_jail = false; p->jail_turns = 0; } else { - // End Turn - current_player_idx = (current_player_idx + 1) % players_count; - has_rolled = false; - double_rolls = 0; - just_sent_to_jail = false; - selected_action = 0; // Reset selection for next player - needs_redraw = true; + p->jail_turns++; + if (p->jail_turns >= 3) { + p->balance -= 50; p->is_in_jail = false; p->jail_turns = 0; + } else { + has_rolled = true; + last_dice1 = d1; last_dice2 = d2; + active_modal = new DiceModalGame(width, height, renderer, gui, input_manager, d1, d2, &MONOPOLY_BOARD[old_pos], &MONOPOLY_BOARD[old_pos], players, players_count); + needs_redraw = true; + return true; + } } - break; - case 1: // View Board - if (active_modal) delete active_modal; - active_modal = new BoardModalGame(width, height, renderer, gui, input_manager, players, players_count); - needs_redraw = true; - break; + } else if (is_db) { + double_rolls++; + if (double_rolls >= 3) { + p->position = 10; p->is_in_jail = true; p->jail_turns = 0; + has_rolled = true; double_rolls = 0; + last_dice1 = d1; last_dice2 = d2; + active_modal = new DiceModalGame(width, height, renderer, gui, input_manager, d1, d2, &MONOPOLY_BOARD[old_pos], &MONOPOLY_BOARD[10], players, players_count); + needs_redraw = true; + return true; + } + } else { + double_rolls = 0; + } + + int total = d1 + d2; + p->position = (p->position + total) % BOARD_SIZE; + if (p->position < old_pos) p->balance += 200; + has_rolled = !is_db; + last_dice1 = d1; last_dice2 = d2; + active_modal = new DiceModalGame(width, height, renderer, gui, input_manager, d1, d2, &MONOPOLY_BOARD[old_pos], &MONOPOLY_BOARD[p->position], players, players_count); + + const BoardTile* lnd = &MONOPOLY_BOARD[p->position]; + if (lnd->type == TILE_GO_TO_JAIL) { + p->position = 10; p->is_in_jail = true; p->jail_turns = 0; + has_rolled = true; double_rolls = 0; + } else if (lnd->type == TILE_PROPERTY || lnd->type == TILE_RAILROAD || lnd->type == TILE_UTILITY) { + modal_property_index = p->position; + } else if (lnd->type == TILE_CHANCE) { + last_drawn_chance_idx = chance_deck[current_chance_idx]; + current_chance_idx = (current_chance_idx + 1) % CHANCE_DECK_SIZE; + if (current_chance_idx == 0) shuffle_chance_deck(); + } else if (lnd->type == TILE_COMMUNITY_CHEST) { + last_drawn_community_idx = community_deck[current_community_idx]; + current_community_idx = (current_community_idx + 1) % COMMUNITY_DECK_SIZE; + if (current_community_idx == 0) shuffle_community_deck(); + } else if (lnd->type == TILE_TAX) { + p->balance -= lnd->cost; + } + needs_redraw = true; + } else { + current_player_idx = (current_player_idx + 1) % players_count; + has_rolled = false; double_rolls = 0; just_sent_to_jail = false; selected_action = 0; + needs_redraw = true; } break; - default: - break; + default: break; } return needs_redraw; } @@ -234,33 +477,34 @@ void MonopolyGame::draw() { // Stats Window in center char buf[128]; - renderer->draw_string_scaled(ix + 5, iy + 5, "Monopoly", 2); + renderer->draw_string_scaled(ix + 70, iy + 180, "Monopoly", 3); - int content_y = iy + 25; + int content_y = iy + 0; snprintf(buf, sizeof(buf), "%s", p->name); - renderer->draw_string_scaled(ix + 5, content_y, buf, 2); - content_y += 20; + renderer->draw_string_scaled(ix + 5, content_y, buf, 3); + content_y += 40; snprintf(buf, sizeof(buf), "BAL: $%d", p->balance); - renderer->draw_string_scaled(ix + 5, content_y, buf, 1); - content_y += 12; + renderer->draw_string_scaled(ix + 5, content_y, buf, 2); + content_y += 20; snprintf(buf, sizeof(buf), "POS: %s", tile->name); - renderer->draw_string_scaled(ix + 5, content_y, buf, 1); - content_y += 15; - + renderer->draw_string_scaled(ix + 5, content_y, buf, 2); + content_y += 20; // Draw action menu - const char* actions[ACTION_COUNT]; + const char* actions[3]; + int menu_count = 0; if (!has_rolled) { - actions[0] = "Roll Dice"; + actions[menu_count++] = "Roll Dice"; + if (p->is_in_jail) actions[menu_count++] = "Pay $50"; } else { - actions[0] = "End Turn"; + actions[menu_count++] = "End Turn"; } - actions[1] = "View Board"; + actions[menu_count++] = "View Board"; - for (int i = 0; i < ACTION_COUNT; ++i) { + for (int i = 0; i < menu_count; ++i) { snprintf(buf, sizeof(buf), "%s%s", (i == selected_action) ? "> " : " ", actions[i]); - renderer->draw_string_scaled(ix + 5, content_y, buf, 1); - content_y += 12; + renderer->draw_string_scaled(ix + 5, content_y, buf, 2); + content_y += 20; } } diff --git a/games/monopoly/monopoly_game.h b/games/monopoly/monopoly_game.h index 0b87773..fe58a6e 100644 --- a/games/monopoly/monopoly_game.h +++ b/games/monopoly/monopoly_game.h @@ -37,14 +37,25 @@ private: bool just_sent_to_jail; // UI selection state - int selected_action; // 0: Context action (Roll or End Turn), 1: View Board - static constexpr int ACTION_COUNT = 2; + int selected_action; // 0: Context action, 1: Pay $50 (Jail), 2: View Board + int current_action_count = 2; // Modal games Game* active_modal = nullptr; int last_dice1 = 0; int last_dice2 = 0; int modal_property_index = -1; + int chance_deck[CHANCE_DECK_SIZE]; + int current_chance_idx; + int last_drawn_chance_idx = -1; + int community_deck[COMMUNITY_DECK_SIZE]; + int current_community_idx; + int last_drawn_community_idx = -1; + int rent_multiplier = 1; + bool force_utility_10x = false; + + void shuffle_chance_deck(); + void shuffle_community_deck(); }; #endif // MONOPOLY_GAME_H diff --git a/lib/game.h b/lib/game.h index 27d179c..c17b694 100644 --- a/lib/game.h +++ b/lib/game.h @@ -32,7 +32,9 @@ public: BASE, MONOPOLY_DICE, MONOPOLY_PROPERTY, - MONOPOLY_BOARD + MONOPOLY_BOARD, + MONOPOLY_CHANCE, + MONOPOLY_COMMUNITY_CHEST }; /**