Refactor/state machine (#470)

* initial additions

* Move current_blind to game vars

* tmp

* tmp

* tmp

* tmp

* tmp

* tmp

* tmp

* Compile but is broken

* temp fix for token location

* tmp

* Working, lets clean up

* remove todo

* Remove odd reroll blind variable

* fix skipping blind screen

* fix reroll

* remove magic for blind token locations

* clang format

* Cleanup button highlight in blind menu

* some cleanup

* Add layout file for global UI rects

* remove dead code

* Clang format

* clang format it up

* Move reset top left funct to gfx utils

* make note of soon-to-be removed vars

* Cleanup gamevars declaration

* Cleanup layout file

* Apply suggestions from code review

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* Add include for stdbool.h in common_ui.h

* Cleanup rect declaration

* Start moving state machine stuff to new file

* quick tmp

* oops, add new files

* working call list

* fixed pointer stuff

* working as per norm

* working replacement

* move defines to static const

* fix compile issue

* Add some missing "void"s

* Working new substates

* add statemachine to blind select

* Fix game restart statemachine leak

* clang-format

* Clang format

* Rework shop exit logic

* Use new state machine in shop

* Remove substates entirely

* Remove debug stuff

* Clang format

* document state machine better

* update list tests

* clang-format

* Update for PR

* Claaaaang format

* another clang-format

* Remove extra state in round_end

* cleanup docs for removals in lists

* clang-format... again

* update doxygen format

* Clang format

* Update list docs

* Update lists tests

* Fix bad conflict resolution

---------

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
Rickey
2026-05-22 18:06:13 -07:00
committed by GitHub
co-authored by Copilot Autofix powered by AI
parent 2329c4c681
commit 92cb9f9883
11 changed files with 428 additions and 165 deletions
+36 -29
View File
@@ -11,17 +11,19 @@
#include "layout.h"
#include "soundbank.h"
#include "sprite.h"
#include "state_machine.h"
#include "timer.h"
#include "util.h"
#include <maxmod.h>
#define BLIND_SELECT_BTN_PID 15
#define TM_DISP_BLIND_PANEL_FINISH 7
#define TM_DISP_BLIND_PANEL_START 1
#define BLIND_SKIP_BTN_PID 5
#define BLIND_SKIP_BTN_SELECTED_BORDER_PID 10
#define BLIND_SELECT_BTN_SELECTED_BORDER_PID 18
static const u32 BLIND_SELECT_BTN_PID = 15;
static const u32 BLIND_SKIP_BTN_PID = 5;
static const u32 BLIND_SKIP_BTN_SELECTED_BORDER_PID = 10;
static const u32 BLIND_SELECT_BTN_SELECTED_BORDER_PID = 18;
static const u32 TM_DISP_BLIND_PANEL_FINISH = 7;
static const u32 TM_DISP_BLIND_PANEL_START = 1;
static int timer;
@@ -29,6 +31,7 @@ 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 void game_blind_select_exit(void);
static Rect game_blind_select_get_req_score_rect(enum BlindTokens blind);
static void game_blind_select_print_blinds_reqs_and_rewards(void);
static enum BlindType get_blind_type_from_token(enum BlindTokens blind);
@@ -40,15 +43,22 @@ enum BlindSelectState
BLIND_SELECT,
BLIND_SELECTED_ANIM_SEQ,
DISPLAY_BLIND_PANEL,
BLIND_SELECT_MAX
BLIND_SELECT_EXIT,
BLIND_SELECT_MAX,
};
// TODO: this will be refactored into common state machine
static const SubStateActionFn blind_select_state_actions[] = {
game_blind_select_start_anim_seq,
game_blind_select_handle_input,
game_blind_select_selected_anim_seq,
game_blind_select_display_blind_panel
static StateInfo state_info[] = {
STATE_INFO_UPDATE_FN_ONLY(game_blind_select_start_anim_seq),
STATE_INFO_UPDATE_FN_ONLY(game_blind_select_handle_input),
STATE_INFO_UPDATE_FN_ONLY(game_blind_select_selected_anim_seq),
STATE_INFO_UPDATE_FN_ONLY(game_blind_select_display_blind_panel),
STATE_INFO_UPDATE_FN_ONLY(game_blind_select_exit),
};
static StateMachine blind_select_sm = {
.state_infos = &state_info[0],
.num_infos = BLIND_SELECT_MAX,
};
// clang-format off
@@ -74,8 +84,6 @@ static const u32 SKIP_ROW = 1;
static int selection_x = 0;
static int selection_y = 0;
static enum BlindSelectState substate;
static Sprite* blind_select_tokens[NUM_BLINDS_PER_ANTE] = {NULL};
static void game_blind_select_start_anim_seq()
@@ -95,7 +103,7 @@ static void game_blind_select_start_anim_seq()
if (timer == TM_END_ANIM_SEQ)
{
game_blind_select_print_blinds_reqs_and_rewards();
substate = BLIND_SELECT;
state_machine_change_state(&blind_select_sm, BLIND_SELECT);
timer = TM_ZERO; // Reset the timer
}
}
@@ -191,7 +199,7 @@ static void game_blind_select_handle_input()
{
case BLIND_ROW:
play_sfx(SFX_BUTTON, MM_BASE_PITCH_RATE, BUTTON_SFX_VOLUME);
substate = BLIND_SELECTED_ANIM_SEQ;
state_machine_change_state(&blind_select_sm, BLIND_SELECTED_ANIM_SEQ);
timer = TM_ZERO;
++g_game_vars.round;
display_round();
@@ -258,8 +266,8 @@ static void game_blind_select_selected_anim_seq()
obj_hide(blind_select_tokens[i]->obj);
}
substate = DISPLAY_BLIND_PANEL; // Reset the state
timer = TM_ZERO; // Reset the timer
timer = TM_ZERO;
state_machine_change_state(&blind_select_sm, DISPLAY_BLIND_PANEL);
}
}
@@ -267,7 +275,7 @@ static void game_blind_select_display_blind_panel()
{
if (timer >= TM_DISP_BLIND_PANEL_FINISH)
{
substate = BLIND_SELECT_MAX;
state_machine_change_state(&blind_select_sm, BLIND_SELECT_EXIT);
return;
}
@@ -302,6 +310,12 @@ static void game_blind_select_display_blind_panel()
}
}
static void game_blind_select_exit(void)
{
reset_background();
game_change_state(GAME_STATE_PLAYING);
}
static Rect game_blind_select_get_req_score_rect(enum BlindTokens blind)
{
Rect blind_req_score_rect = SINGLE_BLIND_SEL_REQ_SCORE_RECT;
@@ -441,7 +455,8 @@ static void blind_tokens_init()
void game_blind_select_on_init(void)
{
timer = TM_ZERO;
substate = START_ANIM_SEQ;
state_machine_register(&blind_select_sm);
state_machine_change_state(&blind_select_sm, START_ANIM_SEQ);
selection_x = 0;
selection_y = 0;
@@ -461,14 +476,6 @@ void game_blind_select_on_init(void)
void game_blind_select_on_update(void)
{
timer++;
if (substate == BLIND_SELECT_MAX)
{
reset_background();
game_change_state(GAME_STATE_PLAYING);
return;
}
blind_select_state_actions[substate]();
}
void game_blind_select_on_exit(void)
@@ -483,7 +490,7 @@ void game_blind_select_on_exit(void)
reset_background();
selection_y = 0;
g_game_vars.timer = TM_ZERO;
state_machine_remove(&blind_select_sm);
}
void game_blind_select_change_background(void)
+31 -30
View File
@@ -5,6 +5,7 @@
#include "game.h"
#include "game_variables.h"
#include "layout.h"
#include "state_machine.h"
#include "timer.h"
#include "util.h"
@@ -19,7 +20,7 @@ enum GameRoundEndStates
DISPLAY_REWARDS,
DISPLAY_CASHOUT,
DISMISS_ROUND_END_PANEL,
ROUND_END_EXIT
ROUND_END_STATES_MAX
};
static const u32 TM_RESET_STATIC_VARS = 30;
@@ -46,7 +47,6 @@ static const Rect ROUND_END_MENU_RECT = {9, 7, 24, 20
static const BG_POINT CASHOUT_SRC_3X3_RECT_POS = {5, 29};
// clang-format on
static int substate;
static int blind_reward = 0;
static int hand_reward = 0;
static int interest_reward = 0;
@@ -67,16 +67,21 @@ static void game_round_end_dismiss_round_end_panel(void);
static void game_round_end_extend_black_panel_down(int black_panel_bottom);
static const SubStateActionFn round_end_state_actions[] = {
game_round_end_start,
game_round_end_start_expand_popup,
game_round_end_display_finished_blind,
game_round_end_display_score_min,
game_round_end_update_blind_reward,
game_round_end_panel_exit,
game_round_end_display_rewards,
game_round_end_display_cashout,
game_round_end_dismiss_round_end_panel
static StateInfo state_info[] = {
STATE_INFO_UPDATE_FN_ONLY(game_round_end_start),
STATE_INFO_UPDATE_FN_ONLY(game_round_end_start_expand_popup),
STATE_INFO_UPDATE_FN_ONLY(game_round_end_display_finished_blind),
STATE_INFO_UPDATE_FN_ONLY(game_round_end_display_score_min),
STATE_INFO_UPDATE_FN_ONLY(game_round_end_update_blind_reward),
STATE_INFO_UPDATE_FN_ONLY(game_round_end_panel_exit),
STATE_INFO_UPDATE_FN_ONLY(game_round_end_display_rewards),
STATE_INFO_UPDATE_FN_ONLY(game_round_end_display_cashout),
STATE_INFO_UPDATE_FN_ONLY(game_round_end_dismiss_round_end_panel),
};
static StateMachine round_end_sm = {
.state_infos = &state_info[0],
.num_infos = ROUND_END_STATES_MAX,
};
static int calculate_interest_reward(void)
@@ -93,8 +98,8 @@ static void game_round_end_start(void)
if (g_game_vars.timer == TM_RESET_STATIC_VARS)
{
change_background(BG_ROUND_END, false); // Change the background to the round end background
substate = START_EXPAND_POPUP; // Change the state to the next one
g_game_vars.timer = TM_ZERO; // Reset the timer
state_machine_change_state(&round_end_sm, START_EXPAND_POPUP);
g_game_vars.timer = TM_ZERO; // Reset the timer
blind_reward = blind_get_reward(g_game_vars.current_blind);
hand_reward = g_game_vars.hands;
interest_reward = calculate_interest_reward();
@@ -109,7 +114,7 @@ static void game_round_end_start_expand_popup(void)
if (g_game_vars.timer == TM_END_POP_MENU_ANIM)
{
substate = DISPLAY_FINISHED_BLIND;
state_machine_change_state(&round_end_sm, DISPLAY_FINISHED_BLIND);
g_game_vars.timer = TM_ZERO;
}
}
@@ -151,7 +156,7 @@ static void game_round_end_display_finished_blind(void)
if (g_game_vars.timer >= TM_END_DISPLAY_FIN_BLIND)
{
substate = DISPLAY_SCORE_MIN;
state_machine_change_state(&round_end_sm, DISPLAY_SCORE_MIN);
g_game_vars.timer = TM_ZERO;
}
}
@@ -172,7 +177,7 @@ static void game_round_end_display_score_min(void)
if (g_game_vars.timer >= TM_END_DISPLAY_SCORE_MIN)
{
substate = UPDATE_BLIND_REWARD;
state_machine_change_state(&round_end_sm, UPDATE_BLIND_REWARD);
g_game_vars.timer = TM_ZERO;
}
}
@@ -208,7 +213,7 @@ static void game_round_end_update_blind_reward(void)
tte_erase_rect_wrapper(BLIND_REQ_TEXT_RECT);
obj_hide(g_game_vars.playing_blind_token->obj);
affine_background_load_palette(affine_background_gfxPal);
substate = BLIND_PANEL_EXIT;
state_machine_change_state(&round_end_sm, BLIND_PANEL_EXIT);
g_game_vars.timer = TM_ZERO;
}
}
@@ -236,7 +241,7 @@ static void game_round_end_panel_exit(void)
else if (g_game_vars.timer > FRAMES(20))
{
memset16(&pal_bg_mem[REWARD_PANEL_BORDER_PID], 0x1483, 1);
substate = DISPLAY_REWARDS;
state_machine_change_state(&round_end_sm, DISPLAY_REWARDS);
g_game_vars.timer = TM_ZERO;
}
}
@@ -342,7 +347,7 @@ static void game_round_end_display_rewards(void)
if (hand_reward <= 0 && interest_to_count <= 0)
{
g_game_vars.timer = TM_ZERO;
substate = DISPLAY_CASHOUT;
state_machine_change_state(&round_end_sm, DISPLAY_CASHOUT);
}
else if (g_game_vars.timer == TM_START_ROUND_END_REWARDS_ANIM)
{
@@ -406,7 +411,7 @@ static void game_round_end_display_cashout()
{
game_round_end_cashout();
substate = DISMISS_ROUND_END_PANEL; // Go to the next state
state_machine_change_state(&round_end_sm, DISMISS_ROUND_END_PANEL);
g_game_vars.timer = TM_ZERO;
obj_hide(g_game_vars.round_end_blind_token->obj); // Hide the blind token object
@@ -423,7 +428,7 @@ static void game_round_end_dismiss_round_end_panel(void)
if (g_game_vars.timer >= TM_DISMISS_ROUND_END_TM)
{
g_game_vars.timer = TM_ZERO;
substate = ROUND_END_EXIT;
game_change_state(GAME_STATE_SHOP);
}
}
@@ -446,19 +451,14 @@ void game_round_end_change_background(void)
void game_round_end_on_init(void)
{
substate = ROUND_END_START;
g_game_vars.timer = 0;
state_machine_register(&round_end_sm);
state_machine_change_state(&round_end_sm, ROUND_END_START);
}
void game_round_end_on_update(void)
{
if (substate == ROUND_END_EXIT)
{
game_change_state(GAME_STATE_SHOP);
return;
}
round_end_state_actions[substate]();
// Substate logic only
}
void game_round_end_on_exit(void)
@@ -470,5 +470,6 @@ void game_round_end_on_exit(void)
interest_reward = 0;
sprite_destroy(&g_game_vars.playing_blind_token);
sprite_destroy(&g_game_vars.round_end_blind_token);
state_machine_remove(&round_end_sm);
// TODO: Reuse sprites for blind selection?
}
+24 -26
View File
@@ -20,6 +20,7 @@
#include "random.h"
#include "save.h"
#include "soundbank.h"
#include "state_machine.h"
#include "timer.h"
#include "util.h"
@@ -62,8 +63,6 @@ static const Rect SHOP_REROLL_RECT = { 88, 96, UNDEFINED, UNDEFINED };
static const BG_POINT SHOP_JOKER_SPRITES_INIT_POS = {120, 160};
// clang-format on
// Shop Substates
enum GameShopStates
{
GAME_SHOP_INTRO,
@@ -72,14 +71,19 @@ enum GameShopStates
GAME_SHOP_MAX
};
static void game_shop_intro();
static void game_shop_process_user_input();
static void game_shop_outro();
static void game_shop_intro(void);
static void game_shop_process_user_input(void);
static void game_shop_outro(void);
static const SubStateActionFn shop_state_actions[] = {
game_shop_intro,
game_shop_process_user_input,
game_shop_outro
static StateInfo shop_state_actions[] = {
STATE_INFO_UPDATE_FN_ONLY(game_shop_intro),
STATE_INFO_UPDATE_FN_ONLY(game_shop_process_user_input),
STATE_INFO_UPDATE_FN_ONLY(game_shop_outro),
};
static StateMachine shop_sm = {
.state_infos = &shop_state_actions[0],
.num_infos = GAME_SHOP_MAX,
};
// Shop SelectionGrid
@@ -132,7 +136,6 @@ static Button reroll_button = {
// Shop internal variables
static int timer;
static enum GameShopStates substate;
static int reroll_cost = REROLL_BASE_COST;
@@ -165,7 +168,9 @@ void game_shop_on_init(void)
game_shop_change_background();
timer = TM_ZERO;
substate = GAME_SHOP_INTRO;
state_machine_register(&shop_sm);
state_machine_change_state(&shop_sm, GAME_SHOP_INTRO);
// The selection grid is initialized outside of bounds and moved
// to trigger the selection change so the initial selection is visible
@@ -245,7 +250,7 @@ static void game_shop_create_items(void)
List* shop_jokers_list = get_shop_jokers_list();
list_clear(shop_jokers_list);
*shop_jokers_list = list_create();
*shop_jokers_list = list_init();
for (int i = 0; i < MAX_SHOP_JOKERS; i++)
{
@@ -326,7 +331,7 @@ static void game_shop_intro()
if (timer == TM_END_GAME_SHOP_INTRO)
{
substate = GAME_SHOP_ACTIVE;
state_machine_change_state(&shop_sm, GAME_SHOP_ACTIVE);
timer = TM_ZERO; // Reset the timer
// print initial reroll cost only when the panel is in place
@@ -515,7 +520,7 @@ static inline void game_shop_reroll(int* reroll_cost)
}
list_clear(shop_jokers_list);
*shop_jokers_list = list_create();
*shop_jokers_list = list_init();
game_shop_create_items();
@@ -559,7 +564,7 @@ static void shop_reroll_row_on_key_transit(SelectionGrid* selection_grid, Select
static void next_round_on_pressed(void)
{
// Go to next blind selection game state
substate = GAME_SHOP_EXIT; // Go to the outro sequence state
state_machine_change_state(&shop_sm, GAME_SHOP_EXIT);
timer = TM_ZERO;
reroll_cost = REROLL_BASE_COST;
@@ -624,8 +629,7 @@ static void game_shop_outro()
if (timer >= MENU_POP_OUT_ANIM_FRAMES)
{
substate = GAME_SHOP_MAX; // Go to the next state
timer = TM_ZERO; // Reset the timer
game_change_state(GAME_STATE_BLIND_SELECT);
}
}
@@ -681,14 +685,6 @@ void game_shop_on_update(void)
{
game_shop_lights_anim_frame();
}
if (substate == GAME_SHOP_MAX)
{
game_change_state(GAME_STATE_BLIND_SELECT);
return;
}
shop_state_actions[substate]();
}
void game_shop_on_exit(void)
@@ -711,5 +707,7 @@ void game_shop_on_exit(void)
increment_blind(BLIND_STATE_DEFEATED); // TODO: Move to game_round_end()?
state_machine_remove(&shop_sm);
save_game();
}
}