From db9879b5b52fdd80fd06680acfc3603a0683c782 Mon Sep 17 00:00:00 2001 From: MeirGavish Date: Tue, 6 Jan 2026 11:06:24 +0200 Subject: [PATCH] Added blind score requirement and reward in blind select screen (#282) * Added blind select requirement and rewards printing * Broke game_blind_select_print_blinds_reqs_and_rewards() into separate functions --- source/game.c | 126 +++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 115 insertions(+), 11 deletions(-) diff --git a/source/game.c b/source/game.c index b3ef316..2ee16e3 100644 --- a/source/game.c +++ b/source/game.c @@ -220,6 +220,8 @@ static void game_blind_select_start_anim_seq(void); static void game_blind_select_handle_input(void); static void game_blind_select_selected_anim_seq(void); static void game_blind_select_display_blind_panel(void); +static Rect game_blind_select_get_req_score_rect(enum BlindType blind); +static void game_blind_select_print_blinds_reqs_and_rewards(void); static void game_round_end_start(void); static void game_round_end_start_expand_popup(void); static void game_round_end_display_finished_blind(void); @@ -357,6 +359,8 @@ static const Rect BLIND_REWARD_RECT = {40, 32, 64, 40 }; static const Rect BLIND_REQ_TEXT_RECT = {32, 24, 64, 32 }; static const Rect SHOP_PRICES_TEXT_RECT = {72, 56, 192, 160 }; +static const Rect SINGLE_BLIND_SEL_REQ_SCORE_RECT = {80, 120, 104, 128 }; + // Rects with UNDEFINED are only used in tte_printf, they need to be fully defined // to be used with tte_erase_rect_wrapper() static const Rect HANDS_TEXT_RECT = {16, 104, UNDEFINED, UNDEFINED }; @@ -483,7 +487,7 @@ static int current_blind = BLIND_TYPE_SMALL; // The current state of the blinds, this is used to determine what the game is doing at any given // time -static enum BlindState blinds[BLIND_TYPE_MAX] = { +static enum BlindState blinds_states[BLIND_TYPE_MAX] = { BLIND_STATE_CURRENT, BLIND_STATE_UPCOMING, BLIND_STATE_UPCOMING @@ -656,9 +660,9 @@ void game_init() discards = max_discards; timer = TM_ZERO; current_blind = BLIND_TYPE_SMALL; - blinds[0] = BLIND_STATE_CURRENT; - blinds[1] = BLIND_STATE_UPCOMING; - blinds[2] = BLIND_STATE_UPCOMING; + blinds_states[0] = BLIND_STATE_CURRENT; + blinds_states[1] = BLIND_STATE_UPCOMING; + blinds_states[2] = BLIND_STATE_UPCOMING; ante = STARTING_ANTE; money = STARTING_MONEY; score = STARTING_SCORE; @@ -1381,7 +1385,7 @@ static void change_background(enum BackgroundId id) curr_blind_rect.left += i * rect_width(&SINGLE_BLIND_SELECT_RECT); curr_blind_rect.right += i * rect_width(&SINGLE_BLIND_SELECT_RECT); - if (blinds[i] != BLIND_STATE_CURRENT && + if (blinds_states[i] != BLIND_STATE_CURRENT && (i == BLIND_TYPE_SMALL || i == BLIND_TYPE_BIG)) // Make the skip button gray { BG_POINT skip_blind_btn_pos_dest = { @@ -1397,7 +1401,7 @@ static void change_background(enum BackgroundId id) main_bg_se_copy_rect(skip_blind_btn_rect_src, skip_blind_btn_pos_dest); } - switch (blinds[i]) + switch (blinds_states[i]) { case BLIND_STATE_CURRENT: // Raise the blind panel up a bit { @@ -1778,14 +1782,14 @@ static void increment_blind(enum BlindState increment_reason) if (current_blind >= BLIND_TYPE_MAX) { current_blind = 0; - blinds[0] = BLIND_STATE_CURRENT; // Reset the blinds to the first one - blinds[1] = BLIND_STATE_UPCOMING; // Set the next blind to upcoming - blinds[2] = BLIND_STATE_UPCOMING; // Set the next blind to upcoming + blinds_states[0] = BLIND_STATE_CURRENT; // Reset the blinds to the first one + blinds_states[1] = BLIND_STATE_UPCOMING; // Set the next blind to upcoming + blinds_states[2] = BLIND_STATE_UPCOMING; // Set the next blind to upcoming } else { - blinds[current_blind] = BLIND_STATE_CURRENT; - blinds[current_blind - 1] = increment_reason; + blinds_states[current_blind] = BLIND_STATE_CURRENT; + blinds_states[current_blind - 1] = increment_reason; } } @@ -4362,6 +4366,101 @@ static void game_blind_select_on_update() blind_select_state_actions[substate](); } +static inline void game_blind_select_erase_blind_reqs_and_rewards() +{ + for (enum BlindType curr_blind = 0; curr_blind < BLIND_TYPE_MAX; curr_blind++) + { + Rect blind_req_and_reward_rect = SINGLE_BLIND_SEL_REQ_SCORE_RECT; + + // To account for both raised blind and reward + blind_req_and_reward_rect.top -= TILE_SIZE; + blind_req_and_reward_rect.bottom += TILE_SIZE; + + // To account for overflow + blind_req_and_reward_rect.right += TILE_SIZE; + + blind_req_and_reward_rect.left += + curr_blind * rect_width(&SINGLE_BLIND_SELECT_RECT) * TILE_SIZE; + blind_req_and_reward_rect.right += + curr_blind * rect_width(&SINGLE_BLIND_SELECT_RECT) * TILE_SIZE; + + tte_erase_rect_wrapper(blind_req_and_reward_rect); + } +} + +static Rect game_blind_select_get_req_score_rect(enum BlindType blind) +{ + Rect blind_req_score_rect = SINGLE_BLIND_SEL_REQ_SCORE_RECT; + + blind_req_score_rect.left += blind * rect_width(&SINGLE_BLIND_SELECT_RECT) * TILE_SIZE; + blind_req_score_rect.right += blind * rect_width(&SINGLE_BLIND_SELECT_RECT) * TILE_SIZE; + + if (blinds_states[blind] == BLIND_STATE_CURRENT) + { + // Current blind is raised + blind_req_score_rect.top -= TILE_SIZE; + blind_req_score_rect.bottom -= TILE_SIZE; + } + + return blind_req_score_rect; +} + +static inline void game_blind_select_print_blind_req(enum BlindType blind) +{ + Rect blind_req_score_rect = game_blind_select_get_req_score_rect(blind); + + u32 blind_req = blind_get_requirement(blind, ante); + + char blind_req_str_buff[UINT_MAX_DIGITS + 1]; + truncate_uint_to_suffixed_str( + blind_req, + rect_width(&blind_req_score_rect) / TTE_CHAR_SIZE, + blind_req_str_buff + ); + + update_text_rect_to_right_align_str(&blind_req_score_rect, blind_req_str_buff, OVERFLOW_RIGHT); + + tte_printf( + "#{P:%d,%d; cx:0x%X000}%s", + blind_req_score_rect.left, + blind_req_score_rect.top, + TTE_RED_PB, + blind_req_str_buff + ); +} + +static inline void game_blind_select_print_blind_reward(enum BlindType blind) +{ + int blind_reward = blind_get_reward(blind); + Rect blind_reward_rect = game_blind_select_get_req_score_rect(blind); + + // The reward is right below the score. + blind_reward_rect.top += TILE_SIZE; + blind_reward_rect.bottom += TILE_SIZE; + + char blind_reward_str_buff[UINT_MAX_DIGITS + 2]; // +2 for null terminator and "$" + snprintf(blind_reward_str_buff, sizeof(blind_reward_str_buff), "$%d", blind_reward); + + update_text_rect_to_right_align_str(&blind_reward_rect, blind_reward_str_buff, OVERFLOW_RIGHT); + + tte_printf( + "#{P:%d,%d; cx:0x%X000}%s", + blind_reward_rect.left, + blind_reward_rect.top, + TTE_YELLOW_PB, + blind_reward_str_buff + ); +} + +static void game_blind_select_print_blinds_reqs_and_rewards(void) +{ + for (enum BlindType curr_blind = 0; curr_blind < BLIND_TYPE_MAX; curr_blind++) + { + game_blind_select_print_blind_req(curr_blind); + game_blind_select_print_blind_reward(curr_blind); + } +} + static void game_blind_select_start_anim_seq() { main_bg_se_copy_rect_1_tile_vert(POP_MENU_ANIM_RECT, SCREEN_UP); @@ -4377,6 +4476,7 @@ static void game_blind_select_start_anim_seq() if (timer == TM_END_ANIM_SEQ) { + game_blind_select_print_blinds_reqs_and_rewards(); state_info[game_state].substate = BLIND_SELECT; timer = TM_ZERO; // Reset the timer } @@ -4400,6 +4500,8 @@ static void game_blind_select_handle_input() } else if (key_hit(SELECT_CARD)) { + game_blind_select_erase_blind_reqs_and_rewards(); + if (selection_y == 0) // Blind selected { play_sfx(SFX_BUTTON, MM_BASE_PITCH_RATE, BUTTON_SFX_VOLUME); @@ -4430,6 +4532,8 @@ static void game_blind_select_handle_input() ); } + game_blind_select_print_blinds_reqs_and_rewards(); + timer = TM_ZERO; } }