4#include "affine_background_gfx.h"
6#include "background_main_menu_gfx.h"
34#include "tonc_memdef.h"
42#define STRAIGHT_AND_FLUSH_SIZE_FOUR_FINGERS 4
43#define STRAIGHT_AND_FLUSH_SIZE_DEFAULT 5
47#define STARTING_ROUND 0
48#define STARTING_ANTE 1
49#define STARTING_MONEY 4
50#define STARTING_SCORE 0
52#define EXPIRE_ANIMATION_FRAME_COUNT 3
61int deck_get_size(
void);
62static int deck_get_max_size(
void);
72static const Rect TEMP_SCORE_RECT = {8, 64, 64, 72 };
73static const Rect SCORE_RECT = {24, 48, 64, 56 };
75static const Rect MONEY_TEXT_RECT = {8, 120, 64, 128 };
76static const Rect CHIPS_TEXT_RECT = {8, 80, 32, 88 };
77static const Rect MULT_TEXT_RECT = {40, 80, 64, 88 };
81static const Rect HANDS_TEXT_RECT = {16, 104, UNDEFINED, UNDEFINED };
82static const Rect DISCARDS_TEXT_RECT = {48, 104, UNDEFINED, UNDEFINED };
83static const Rect DECK_SIZE_RECT = {200, 152, 240, 160 };
84static const Rect ROUND_TEXT_RECT = {48, 144, UNDEFINED, UNDEFINED };
85static const Rect ANTE_TEXT_RECT = {8, 144, UNDEFINED, UNDEFINED };
89#define DEF_STATE_INFO(stateEnum, init_fn, update_fn, exit_fn) \
90 {.on_init = init_fn, .on_update = update_fn, .on_exit = exit_fn},
91#include "../include/def_state_info_table.h"
95static StateMachine game_sm = STATE_MACHINE_DEFINE(state_info, GAME_STATE_MAX);
102 .rng_info = {UNDEFINED, {0}},
104 .score = 0, .chips = 0, .mult = 0,
105 .hands = 0, .discards = 0,
106 .money = 0, .hand_size = DEFAULT_HAND_SIZE,
107 .ante = 0, .round = 0,
108 .deck = DECK_TYPE_RED,
109 .nb_played_hands = {0},
111 .best_hand_score = 0,
112 .nb_skipped_rounds = 0,
113 .nb_unused_discards = 0,
115 .current_blind = BLIND_TYPE_SMALL,
116 .next_boss_blind = BLIND_TYPE_BIG,
120 BLIND_STATE_UPCOMING,
124 .playing_blind_token = NULL,
125 .round_end_blind_token = NULL,
127 .game_speed = DEFAULT_GAME_SPEED,
128 .music_volume = DEFAULT_MUSIC_VOLUME,
129 .sound_volume = DEFAULT_SOUND_VOLUME,
133static List s_owned_jokers_list;
134static List s_discarded_items_list;
135static List s_expired_jokers_list;
138static Card* s_deck[MAX_DECK_SIZE] = {NULL};
139static int s_deck_top = -1;
142static int s_shortcut_joker_count = 0;
144static int s_four_fingers_joker_count = 0;
146void deck_push(
Card* card)
148 if (s_deck_top >= MAX_DECK_SIZE - 1)
150 s_deck[++s_deck_top] = card;
157 return s_deck[s_deck_top--];
160void display_ante(
void)
163 "#{P:%d,%d; cx:0x%X000}%ld#{cx:0x%X000}/%d",
185 g_game_vars.timer = TM_ZERO;
186 g_game_vars.score = STARTING_SCORE;
187 g_game_vars.chips = 0;
188 g_game_vars.mult = 0;
189 g_game_vars.hands = MAX_HANDS;
190 g_game_vars.discards = MAX_DISCARDS;
191 g_game_vars.money = STARTING_MONEY;
192 g_game_vars.hand_size = DEFAULT_HAND_SIZE;
193 g_game_vars.ante = STARTING_ANTE;
194 g_game_vars.round = STARTING_ROUND;
195 g_game_vars.deck = DECK_TYPE_RED;
196 for (
int i = 0; i < HAND_TYPE_MAX; i++)
197 g_game_vars.nb_played_hands[i] = 0;
198 g_game_vars.best_hand_score = 0;
199 g_game_vars.nb_skipped_rounds = 0;
200 g_game_vars.nb_unused_discards = 0;
201 g_game_vars.current_blind = BLIND_TYPE_SMALL;
202 g_game_vars.blinds_states[0] = BLIND_STATE_CURRENT;
203 g_game_vars.blinds_states[1] = BLIND_STATE_UPCOMING;
204 g_game_vars.blinds_states[2] = BLIND_STATE_UPCOMING;
212 remove_owned_joker(0);
213 joker_object_destroy(&joker_object);
232 display_score(g_game_vars.score);
244void item_start_discard_animation(
Item* item)
246 item->tx = int2fx(ITEM_DISCARD_TARGET.x);
247 item->ty = int2fx(ITEM_DISCARD_TARGET.y);
251static inline void discarded_items_update_loop(
void)
263 if (item->x == item->tx && item->y == item->ty)
271static inline void held_jokers_update_loop(
void)
273 static const int SPACING_LUT[MAX_JOKERS_HELD_SIZE][MAX_JOKERS_HELD_SIZE] = {
277 {39, 13, -13, -39, 0 },
278 {40, 20, 0, -20, -40}
281 FIXED hand_x = int2fx(HELD_JOKERS_POS.x);
285 int jokers_top =
list_get_len(&s_owned_jokers_list) - 1;
291 joker->tx = hand_x - int2fx(SPACING_LUT[jokers_top][i]);
296bool joker_object_can_acquire(
Item* joker_object)
299 return (
list_get_len(get_jokers_list()) < MAX_JOKERS_HELD_SIZE);
302static inline void expired_jokers_update_loop(
void)
315 if (g_game_vars.timer % FRAMES(EXPIRE_ANIMATION_FRAME_COUNT) == 0)
318 int expired_joker_idx = 0;
321 while ((expired_joker =
list_itr_next(&joker_itr)) && expired_joker != joker_object)
330 remove_owned_joker(expired_joker_idx);
332 joker_object_destroy(&joker_object);
337static inline void jokers_update_loop(
void)
339 held_jokers_update_loop();
340 expired_jokers_update_loop();
349 jokers_update_loop();
350 discarded_items_update_loop();
357void game_change_state(
enum GameState new_game_state)
359 g_game_vars.timer = TM_ZERO;
364enum GameState game_get_state(
void)
366 return game_sm.
state;
369bool is_joker_owned(
int joker_id)
376 if (joker->joker->id == joker_id)
384List* get_jokers_list(
void)
386 return &s_owned_jokers_list;
389List* get_expired_jokers_list(
void)
391 return &s_expired_jokers_list;
394bool is_shortcut_joker_active(
void)
396 return s_shortcut_joker_count > 0;
399int get_straight_and_flush_size(
void)
401 return s_four_fingers_joker_count > 0 ? STRAIGHT_AND_FLUSH_SIZE_FOUR_FINGERS
402 : STRAIGHT_AND_FLUSH_SIZE_DEFAULT;
408 joker_object->ty = int2fx(HELD_JOKERS_POS.y);
413 if (joker_object->joker->id == FOUR_FINGERS_JOKER_ID)
415 s_four_fingers_joker_count++;
418 if (joker_object->joker->id == SHORTCUT_JOKER_ID)
420 s_shortcut_joker_count++;
424void remove_owned_joker(
int owned_joker_idx)
430 if (joker_object->joker->id == FOUR_FINGERS_JOKER_ID)
432 s_four_fingers_joker_count--;
435 if (joker_object->joker->id == SHORTCUT_JOKER_ID)
437 s_shortcut_joker_count--;
445int get_deck_top(
void)
450int get_num_discards_remaining(
void)
452 return g_game_vars.discards;
455int get_num_hands_remaining(
void)
457 return g_game_vars.hands;
462 Rect money_text_rect = MONEY_TEXT_RECT;
465 char money_str_buff[INT_MAX_DIGITS + 2];
466 snprintf(money_str_buff,
sizeof(money_str_buff),
"$%ld", g_game_vars.money);
472 "#{P:%d,%d; cx:0x%X000}%s",
473 money_text_rect.left,
480void display_chips(
void)
482 Rect chips_text_rect = CHIPS_TEXT_RECT;
485 Rect chips_text_overflow_rect = chips_text_rect;
489 char chips_str_buff[UINT_MAX_DIGITS + 1];
499 "#{P:%d,%d; cx:0x%X000;}%s",
500 chips_text_rect.left,
508void display_mult(
void)
510 Rect mult_text_overflow_rect = MULT_TEXT_RECT;
515 char mult_str_buff[UINT_MAX_DIGITS + 1];
523 "#{P:%d,%d; cx:0x%X000;}%s",
533void display_deck_size_max(
void)
539 "#{P:%d,%d; cx:0x%X000}%d/%d",
549bool card_is_face(
Card* card)
553 card->rank == JACK || card->rank == QUEEN || card->rank == KING ||
554 is_joker_owned(PAREIDOLIA_JOKER_ID)
558void display_temp_score(u32 value)
560 char temp_score_str_buff[UINT_MAX_DIGITS + 1];
561 Rect temp_score_rect = TEMP_SCORE_RECT;
571 "#{P:%d,%d; cx:0x%X000}%s",
572 temp_score_rect.left,
579void erase_temp_score(
void)
584void display_score(u32 value)
586 Rect score_rect = SCORE_RECT;
590 char score_str_buff[UINT_MAX_DIGITS + 1];
596 "#{P:%d,%d; cx:0x%X000}%s",
604void display_round(
void)
608 "#{P:%d,%d; cx:0x%X000}%ld",
609 ROUND_TEXT_RECT.left,
616void display_hands(
void)
619 "#{P:%d,%d; cx:0x%X000}%ld",
620 HANDS_TEXT_RECT.left,
627void display_discards(
void)
630 "#{P:%d,%d; cx:0x%X000}%ld",
631 DISCARDS_TEXT_RECT.left,
632 DISCARDS_TEXT_RECT.top,
638int deck_get_size(
void)
640 return s_deck_top + 1;
643static int deck_get_max_size(
void)
649void deck_shuffle(
void)
651 for (
int i = s_deck_top; i > 0; i--)
653 int j =
rng_get_u32(RNG_SEQ_CARD_SHUFFLE) % (i + 1);
654 Card* temp = s_deck[i];
655 s_deck[i] = s_deck[j];
665 g_game_vars.hands = MAX_HANDS;
666 g_game_vars.discards = MAX_DISCARDS;
670 for (
int suit = 0; suit < NUM_SUITS; suit++)
672 for (
int rank = 0; rank < NUM_RANKS; rank++)
674 Card* card = card_new(suit, rank);
682 "#{P:%d,%d; cx:0x%X000}%d/%d",
691 display_score(g_game_vars.score);
702 game_change_state(GAME_STATE_BLIND_SELECT);
Utilities for affine background on GBA.
@ AFFINE_BG_GAME
Display background for game play.
void affine_background_change_background(enum AffineBackgroundID new_bg)
Update the background id.
void affine_background_load_palette(const u16 *src)
Set the background palette.
Utilities for using maxmod to play sound effects.
void init_unbeaten_blinds_lists(void)
Initialize Boss and Showdown Blinds lists to roll from.
Blind select state functions.
Common functions to render UI elements.
Game Over screen state functions.
Game global game variables struct definition.
Graphic utility functions.
void update_text_rect_to_right_align_str(Rect *rect, const char *str, enum OverflowDir overflow_direction)
Changes rect->left so it fits the digits of num exactly when right aligned to rect->right....
void update_text_rect_to_center_str(Rect *rect, const char *str, enum ScreenHorzDir bias_direction)
Updates a rect so a string is centered within it.
#define TTE_CHAR_SIZE
By default TTE characters occupy a single tile.
void tte_erase_rect_wrapper(Rect rect)
A wrapper for tte_erase_rect that would use the rect struct.
INLINE int rect_width(const Rect *rect)
Get the width of a rectangle.
Functions relative to manipulating and analyzing the contents of the Hand, a.k.a. the Cards we hold a...
int get_hand_top(void)
Get the position in hand array of the last card obtained.
void item_dispose(Item **item)
Destroys an item, freeing underlying resources, and manages rollable items sets if needed....
Functions relative to the handling of Jokers.
void joker_set_rollable(int joker_id, bool rollable)
Set whether a Joker is available to be rolled for the shop, packs, etc.
All the functions used specifically to interact with Jokers. This includes browsing,...
Header of shared rects and points needed for ui.
bool list_is_empty(const List *list)
void * list_get_at_idx(List *list, unsigned int idx)
int list_get_len(const List *list)
void list_clear(List *list)
void list_itr_remove_current_node(ListItr *itr)
void * list_itr_next(ListItr *itr)
bool list_remove_at_idx(List *list, unsigned int idx)
void list_push_back(List *list, void *data)
ListItr list_itr_create(List *list)
Main menu state functions.
Common functions to handle RNG manipulation. Using this interface has three goals:
void rng_update(void)
Accumulates CPU cycles for RNG seed generation, call exaclty once per frame.
u32 rng_get_u32(enum RngSequence key)
Get the next "randomly" generated number in the sequence corresponding to the given type.
API relative to the Rounds we play.
int get_discard_top(void)
Get the index of the last discarded card.
void toggle_flaming_score(void)
Checks whether the score that would result from the current Chips and Mult exceeds the current Blind'...
int get_played_top(void)
Get the index of the last played card.
Round end game state functions.
Setup Run menu state functions.
Utils functions to save/load data structures from/to the SRAM.
An implementation for a selection grid that handles directional selection.
Item * shop_get_description_item(void)
Get a pointer to the Card we are currently showing the description of.
void shop_reset(void)
Initialize the shop for a run. Resets all the shop data for the run, needs to be called once per run.
Data structures and functions related to the handling of Skip Tags.
Functions and constants for the splash screen intro.
Sprite system for Gbalatro.
void sprite_object_update_all(void)
Update all SpriteObjects, to be called once per frame in the main update loop.
void sprite_destroy(Sprite **sprite)
Destroy Sprite.
void state_machine_remove(StateMachine *state_machine)
Remove a statemachine's update function.
void state_machine_register(StateMachine *state_machine)
Register a statemachine to run it's update function once per frame.
void state_machine_change_state(StateMachine *state_machine, int new_state)
Calls the current state's on_exit, the new state's on_init, and sets the active update fn.
void state_machine_update(void)
Update registered state machines' update functions.
A central location for all game variables.
A generic interface for all items that can appear in the shop or be in the inventory....
int state
The current state of the state machine, the offset into state_infos.
Utilities relating around number string representation and protected arithmatic helper functions.
#define GBAL_RETURN_IF_NULL(param, ret_val)
Returns ret_val and prints a default error message if param is equal to NULL. Useful for checking arg...
void truncate_uint_to_suffixed_str(uint32_t num, int num_req_chars, char out_str_buff[UINT_MAX_DIGITS+1])
Truncate an unsigned number into a suffixed string representation e.g. 12000 -> "12K" The least signi...