Files
basic1/games/monopoly/monopoly_game.cpp
Adolfo Reyna fa4c6f00ca monopoly board
2026-01-31 22:00:46 -05:00

216 lines
8.1 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>
#include <stdlib.h>
#include <time.h>
#include "DiceModalGame.h"
#include "PropertyModalGame.h"
#include "BoardModalGame.h"
#include "MonopolyBoardRenderer.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;
srand(time(NULL));
if (active_modal) { delete active_modal; active_modal = nullptr; }
// 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 a modal is active, delegate input and check for dismissal
if (active_modal) {
bool modal_redraw = active_modal->update(event);
if (modal_redraw) needs_redraw = true;
// Check for specific modal types to handle their results
auto dice_modal = dynamic_cast<DiceModalGame*>(active_modal);
auto prop_modal = dynamic_cast<PropertyModalGame*>(active_modal);
auto board_modal = dynamic_cast<BoardModalGame*>(active_modal);
if (dice_modal && dice_modal->is_dismissed()) {
delete active_modal;
active_modal = nullptr;
needs_redraw = true;
} else if (prop_modal && prop_modal->is_dismissed()) {
if (prop_modal->wants_to_buy()) {
const BoardTile* tile = &MONOPOLY_BOARD[p->position];
p->balance -= tile->cost;
p->properties_owned[p->property_count++] = p->position;
}
delete active_modal;
active_modal = nullptr;
needs_redraw = true;
} else if (board_modal && board_modal->is_dismissed()) {
delete active_modal;
active_modal = nullptr;
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: // 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;
}
}
} 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;
}
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;
}
break;
default:
break;
}
// If dice modal was just dismissed and a property modal is queued, show it
if (!active_modal && modal_property_index >= 0) {
// Evaluate ownership and affordability
bool is_owned = false;
const char* owner_name = nullptr;
for (int i = 0; i < players_count; ++i) {
for (int j = 0; j < players[i].property_count; ++j) {
if (players[i].properties_owned[j] == modal_property_index) {
is_owned = true;
owner_name = players[i].name;
break;
}
}
if (is_owned) break;
}
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, can_afford, players, players_count);
modal_property_index = -1;
needs_redraw = true;
}
return needs_redraw;
}
// --- Draw game state (minimal: player info, current tile, actions) ---
void MonopolyGame::draw() {
// If a modal is active, draw it and return
if (active_modal) {
active_modal->draw();
return;
}
renderer->clear_buffer();
// --- Draw Board Perimeter ---
MonopolyBoardRenderer::draw_board_perimeter(renderer, width, height, players, players_count);
// --- Inner Dashboard (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;
Player* p = &players[current_player_idx];
const BoardTile* tile = &MONOPOLY_BOARD[p->position];
// Stats Window in center
char buf[128];
renderer->draw_string_scaled(ix + 5, iy + 5, "Monopoly", 2);
int content_y = iy + 25;
snprintf(buf, sizeof(buf), "TURN: %s", p->name);
renderer->draw_string_scaled(ix + 5, content_y, buf, 1);
content_y += 12;
snprintf(buf, sizeof(buf), "BAL: $%d", p->balance);
renderer->draw_string_scaled(ix + 5, content_y, buf, 1);
content_y += 12;
snprintf(buf, sizeof(buf), "POS: %s", tile->name);
renderer->draw_string_scaled(ix + 5, content_y, buf, 1);
content_y += 15;
// Draw action menu
const char* actions[ACTION_COUNT];
if (!has_rolled) {
actions[0] = "Roll Dice";
} else {
actions[0] = "End Turn";
}
actions[1] = "View Board";
for (int i = 0; i < ACTION_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;
}
}