GBAlatro
A Demake of Balatro for the GBA
Loading...
Searching...
No Matches
game.c
1#include "game.h"
2
3#include "affine_background.h"
4#include "affine_background_gfx.h"
5#include "audio_utils.h"
6#include "background_main_menu_gfx.h"
7#include "button.h"
8#include "card.h"
9#include "game/blind_select.h"
10#include "game/common_ui.h"
11#include "game/game_over.h"
12#include "game/joker_row.h"
13#include "game/main_menu.h"
14#include "game/options_menu.h"
15#include "game/round.h"
16#include "game/round_end.h"
17#include "game/run_setup.h"
18#include "game/shop.h"
19#include "game_variables.h"
20#include "graphic_utils.h"
21#include "hand.h"
22#include "joker.h"
23#include "layout.h"
24#include "list.h"
25#include "random.h"
26#include "save.h"
27#include "selection_grid.h"
28#include "soundbank.h"
29#include "splash_screen.h"
30#include "sprite.h"
31#include "state_machine.h"
32#include "timer.h"
33#include "tonc_memdef.h"
34#include "util.h"
35
36#include <maxmod.h>
37#include <stdint.h>
38#include <stdlib.h>
39#include <string.h>
40
41#define STRAIGHT_AND_FLUSH_SIZE_FOUR_FINGERS 4
42#define STRAIGHT_AND_FLUSH_SIZE_DEFAULT 5
43
44// SE sizes
45
46#define STARTING_ROUND 0
47#define STARTING_ANTE 1
48#define STARTING_MONEY 4
49#define STARTING_SCORE 0
50
51#define EXPIRE_ANIMATION_FRAME_COUNT 3
52
53// These functions need to be forward declared
54// so they're visible to the state_info array,
55// and the sub-state function tables.
56// This could be done, and maybe should be done,
57// with an X macro, but I'll leave that to the
58// reviewer(s).
59
60int deck_get_size(void);
61static int deck_get_max_size(void);
62
63// Consts
64
65// clang-format off
66// Rects left top right bottom
67
68// Rects for TTE (in pixels)
69
70// Score displayed in the same place as the hand type
71static const Rect TEMP_SCORE_RECT = {8, 64, 64, 72 };
72static const Rect SCORE_RECT = {24, 48, 64, 56 };
73
74static const Rect MONEY_TEXT_RECT = {8, 120, 64, 128 };
75static const Rect CHIPS_TEXT_RECT = {8, 80, 32, 88 };
76static const Rect MULT_TEXT_RECT = {40, 80, 64, 88 };
77
78// Rects with UNDEFINED are only used in tte_printf, they need to be fully defined
79// to be used with tte_erase_rect_wrapper()
80static const Rect HANDS_TEXT_RECT = {16, 104, UNDEFINED, UNDEFINED };
81static const Rect DISCARDS_TEXT_RECT = {48, 104, UNDEFINED, UNDEFINED };
82static const Rect DECK_SIZE_RECT = {200, 152, 240, 160 };
83static const Rect ROUND_TEXT_RECT = {48, 144, UNDEFINED, UNDEFINED };
84static const Rect ANTE_TEXT_RECT = {8, 144, UNDEFINED, UNDEFINED };
85// clang-format on
86
87static StateInfo state_info[] = {
88#define DEF_STATE_INFO(stateEnum, init_fn, update_fn, exit_fn) \
89 {.on_init = init_fn, .on_update = update_fn, .on_exit = exit_fn},
90#include "../include/def_state_info_table.h"
91#undef DEF_STATE_INFO
92};
93
94static StateMachine game_sm = STATE_MACHINE_DEFINE(state_info, GAME_STATE_MAX);
95
96// Initialization of the global vars
97// clang-format off
98GameVariables g_game_vars = {
99 .timer = 0,
100 // Setting the seed to an invalid value so that the Run Setup screen knows we're not reusing a previous Run's seed
101 .rng_info = {UNDEFINED, {0}},
102
103 .round = 0, .ante = 0, .money = 0, .hand_size = DEFAULT_HAND_SIZE,
104 .deck = DECK_TYPE_RED,
105
106 .best_hand_score = 0, .nb_played_hands = {0},
107
108 .current_blind = BLIND_TYPE_SMALL,
109 .next_boss_blind = BLIND_TYPE_BIG,
110 .blinds_states =
111 {
112 BLIND_STATE_CURRENT,
113 BLIND_STATE_UPCOMING,
114 BLIND_STATE_UPCOMING
115 },
116
117 .hands = 0,
118 .discards = 0,
119 .score = 0,
120 .chips = 0,
121 .mult = 0,
122
123 .playing_blind_token = NULL,
124 .round_end_blind_token = NULL,
125
126 .game_speed = DEFAULT_GAME_SPEED,
127 .music_volume = DEFAULT_MUSIC_VOLUME,
128 .sound_volume = DEFAULT_SOUND_VOLUME,
129};
130// clang-format on
131
132static List s_owned_jokers_list;
133static List s_discarded_jokers_list;
134static List s_expired_jokers_list;
135
136// Stacks
137static Card* s_deck[MAX_DECK_SIZE] = {NULL};
138static int s_deck_top = -1;
139
140// Joker Special Variables
141static int s_shortcut_joker_count = 0;
142
143static int s_four_fingers_joker_count = 0;
144
145void deck_push(Card* card)
146{
147 if (s_deck_top >= MAX_DECK_SIZE - 1)
148 return;
149 s_deck[++s_deck_top] = card;
150}
151
152Card* deck_pop(void)
153{
154 if (s_deck_top < 0)
155 return NULL;
156 return s_deck[s_deck_top--];
157}
158
159void display_ante(void)
160{
161 tte_printf(
162 "#{P:%d,%d; cx:0x%X000}%ld#{cx:0x%X000}/%d",
163 ANTE_TEXT_RECT.left,
164 ANTE_TEXT_RECT.top,
165 TTE_YELLOW_PB,
166 g_game_vars.ante,
167 TTE_WHITE_PB,
168 MAX_ANTE
169 );
170}
171
172void game_init()
173{
174 state_machine_remove(&game_sm);
175 state_machine_register(&game_sm);
176 // Initialize all jokers list once
177 s_owned_jokers_list = list_init();
178 s_discarded_jokers_list = list_init();
179 s_expired_jokers_list = list_init();
180 // TODO: Move this to an initialization of the play scoring states
181
183
184 g_game_vars.hands = MAX_HANDS;
185 g_game_vars.discards = MAX_DISCARDS;
186 g_game_vars.timer = TM_ZERO;
187 g_game_vars.current_blind = BLIND_TYPE_SMALL;
188 g_game_vars.blinds_states[0] = BLIND_STATE_CURRENT;
189 g_game_vars.blinds_states[1] = BLIND_STATE_UPCOMING;
190 g_game_vars.blinds_states[2] = BLIND_STATE_UPCOMING;
191 g_game_vars.ante = STARTING_ANTE;
192 g_game_vars.money = STARTING_MONEY;
193 g_game_vars.score = STARTING_SCORE;
194 g_game_vars.round = 0;
195 g_game_vars.chips = 0;
196 g_game_vars.mult = 0;
197 g_game_vars.round = STARTING_ROUND;
198
199 g_game_vars.best_hand_score = 0;
200 for (int i = 0; i < HAND_TYPE_MAX; i++)
201 g_game_vars.nb_played_hands[i] = 0;
202}
203
204void game_reset()
205{
206 while (list_get_len(&s_owned_jokers_list) > 0)
207 {
208 JokerObject* joker_object = list_get_at_idx(&s_owned_jokers_list, 0);
209 remove_owned_joker(0);
210 joker_object_destroy(&joker_object);
211 }
212
213 tte_erase_screen();
214
215 // For some reason that I haven't figured out yet,
216 // if I don't destroy the blind tokens they won't
217 // show up on the next run.
218 sprite_destroy(&g_game_vars.playing_blind_token);
219 sprite_destroy(&g_game_vars.round_end_blind_token);
220
221 list_clear(&s_owned_jokers_list);
222 list_clear(&s_discarded_jokers_list);
223 list_clear(&s_expired_jokers_list);
224
225 game_init();
227
228 display_round();
229 display_score(g_game_vars.score);
230 display_chips();
231 display_mult();
232 display_hands();
233 display_discards();
234 display_money();
235 // Ante
236 display_ante();
237
238 affine_background_load_palette(affine_background_gfxPal);
239}
240
241static inline void discarded_jokers_update_loop(void)
242{
243 if (list_is_empty(&s_discarded_jokers_list))
244 {
245 return;
246 }
247
248 ListItr itr = list_itr_create(&s_discarded_jokers_list);
249 JokerObject* joker_object;
250
251 while ((joker_object = list_itr_next(&itr)))
252 {
253 if (joker_object->x == joker_object->tx && joker_object->y == joker_object->ty)
254 {
256 // TODO: joker_object_dispose() instead?
257 joker_object_destroy(&joker_object);
258 }
259 }
260}
261
262static inline void held_jokers_update_loop(void)
263{
264 static const int SPACING_LUT[MAX_JOKERS_HELD_SIZE][MAX_JOKERS_HELD_SIZE] = {
265 {0, 0, 0, 0, 0 },
266 {13, -13, 0, 0, 0 },
267 {26, 0, -26, 0, 0 },
268 {39, 13, -13, -39, 0 },
269 {40, 20, 0, -20, -40}
270 };
271
272 FIXED hand_x = int2fx(HELD_JOKERS_POS.x);
273
274 ListItr itr = list_itr_create(&s_owned_jokers_list);
275 JokerObject* joker;
276 int jokers_top = list_get_len(&s_owned_jokers_list) - 1;
277 int i = 0;
278 while ((joker = list_itr_next(&itr)))
279 {
280 // Let the Shop handle the position of this Joker
281 if (joker != game_shop_get_description_card())
282 joker->tx = hand_x - int2fx(SPACING_LUT[jokers_top][i]);
283 i++;
284 }
285}
286
287bool joker_object_can_acquire(Item* joker_object)
288{
289 GBAL_RETURN_IF_NULL_RET(joker_object, false);
290 return (list_get_len(get_jokers_list()) < MAX_JOKERS_HELD_SIZE);
291}
292
293static inline void expired_jokers_update_loop(void)
294{
295 if (list_is_empty(&s_expired_jokers_list))
296 {
297 return;
298 }
299
300 ListItr itr = list_itr_create(&s_expired_jokers_list);
301 JokerObject* joker_object;
302
303 while ((joker_object = list_itr_next(&itr)))
304 {
305 // let just enough frames pass that we see it rotating and shrinking
306 if (g_game_vars.timer % FRAMES(EXPIRE_ANIMATION_FRAME_COUNT) == 0)
307 {
308 // get joker idx
309 int expired_joker_idx = 0;
310 ListItr joker_itr = list_itr_create(&s_owned_jokers_list);
311 JokerObject* expired_joker;
312 while ((expired_joker = list_itr_next(&joker_itr)) && expired_joker != joker_object)
313 {
314 expired_joker_idx++;
315 }
316
317 // Removing expired Jokers here, instead of immediately like ones we
318 // sell or discard allow us to have a small shrink animation without
319 // the other owned Jokers rearranging themselves to fill the newly
320 // freed space, therefore obscuring the animation
321 remove_owned_joker(expired_joker_idx);
323 joker_object_destroy(&joker_object);
324 }
325 }
326}
327
328static inline void jokers_update_loop(void)
329{
330 held_jokers_update_loop();
331 discarded_jokers_update_loop();
332 expired_jokers_update_loop();
333}
334
335void game_update()
336{
337 rng_update();
338
339 g_game_vars.timer++;
340
341 jokers_update_loop();
342
344
346}
347
348void game_change_state(enum GameState new_game_state)
349{
350 g_game_vars.timer = TM_ZERO; // Reset the timer
351
352 state_machine_change_state(&game_sm, new_game_state);
353}
354
355enum GameState game_get_state(void)
356{
357 return game_sm.state;
358}
359
360bool is_joker_owned(int joker_id)
361{
362 ListItr itr = list_itr_create(&s_owned_jokers_list);
363 JokerObject* joker;
364
365 while ((joker = list_itr_next(&itr)))
366 {
367 if (joker->joker->id == joker_id)
368 {
369 return true;
370 }
371 }
372 return false;
373}
374
375List* get_jokers_list(void)
376{
377 return &s_owned_jokers_list;
378}
379
380List* get_expired_jokers_list(void)
381{
382 return &s_expired_jokers_list;
383}
384
385List* get_discarded_jokers_list(void)
386{
387 return &s_discarded_jokers_list;
388}
389
390bool is_shortcut_joker_active(void)
391{
392 return s_shortcut_joker_count > 0;
393}
394
395int get_straight_and_flush_size(void)
396{
397 return s_four_fingers_joker_count > 0 ? STRAIGHT_AND_FLUSH_SIZE_FOUR_FINGERS
398 : STRAIGHT_AND_FLUSH_SIZE_DEFAULT;
399}
400
401void add_joker(JokerObject* joker_object)
402{
403 list_push_back(&s_owned_jokers_list, joker_object);
404
405 // TODO: Extract to on_joker_added() callback
406 // In case the player gets multiple Four Fingers Jokers,
407 // only change size when the first one is added
408 if (joker_object->joker->id == FOUR_FINGERS_JOKER_ID)
409 {
410 s_four_fingers_joker_count++;
411 }
412
413 if (joker_object->joker->id == SHORTCUT_JOKER_ID)
414 {
415 s_shortcut_joker_count++;
416 }
417}
418
419void remove_owned_joker(int owned_joker_idx)
420{
421 // TODO: Extract to on_joker_removed() callback
422 JokerObject* joker_object = list_get_at_idx(&s_owned_jokers_list, owned_joker_idx);
423 // In case the player gets multiple Four Fingers Jokers,
424 // and only reset the size when all of them have been removed
425 if (joker_object->joker->id == FOUR_FINGERS_JOKER_ID)
426 {
427 s_four_fingers_joker_count--;
428 }
429
430 if (joker_object->joker->id == SHORTCUT_JOKER_ID)
431 {
432 s_shortcut_joker_count--;
433 }
434
435 // TODO: Move to site of joker_destroy()?
436 joker_set_rollable(joker_object->joker->id, true);
437 list_remove_at_idx(&s_owned_jokers_list, owned_joker_idx);
438}
439
440int get_deck_top(void)
441{
442 return s_deck_top;
443}
444
445int get_num_discards_remaining(void)
446{
447 return g_game_vars.discards;
448}
449
450int get_num_hands_remaining(void)
451{
452 return g_game_vars.hands;
453}
454
455void display_money()
456{
457 Rect money_text_rect = MONEY_TEXT_RECT;
458 tte_erase_rect_wrapper(MONEY_TEXT_RECT);
459
460 char money_str_buff[INT_MAX_DIGITS + 2]; // + 2 for null terminator and "$" sign
461 snprintf(money_str_buff, sizeof(money_str_buff), "$%ld", g_game_vars.money);
462
463 // Bias left so the number is centered and the "$" sign is on the left
464 update_text_rect_to_center_str(&money_text_rect, money_str_buff, SCREEN_LEFT);
465
466 tte_printf(
467 "#{P:%d,%d; cx:0x%X000}%s",
468 money_text_rect.left,
469 money_text_rect.top,
470 TTE_YELLOW_PB,
471 money_str_buff
472 );
473}
474
475void display_chips(void)
476{
477 Rect chips_text_rect = CHIPS_TEXT_RECT;
478
479 // In case of overflow, the rect overflow left by 1 char
480 Rect chips_text_overflow_rect = chips_text_rect;
481 chips_text_overflow_rect.left -= TTE_CHAR_SIZE;
482 tte_erase_rect_wrapper(chips_text_overflow_rect);
483
484 char chips_str_buff[UINT_MAX_DIGITS + 1];
486 g_game_vars.chips,
487 rect_width(&chips_text_rect) / TTE_CHAR_SIZE,
488 chips_str_buff
489 );
490
491 update_text_rect_to_right_align_str(&chips_text_rect, chips_str_buff, OVERFLOW_LEFT);
492
493 tte_printf(
494 "#{P:%d,%d; cx:0x%X000;}%s",
495 chips_text_rect.left,
496 chips_text_rect.top,
497 TTE_WHITE_PB,
498 chips_str_buff
499 );
501}
502
503void display_mult(void)
504{
505 Rect mult_text_overflow_rect = MULT_TEXT_RECT;
506 // In case of overflow the rect will overflow right by 1 char
507 mult_text_overflow_rect.right += TTE_CHAR_SIZE;
508 tte_erase_rect_wrapper(mult_text_overflow_rect);
509
510 char mult_str_buff[UINT_MAX_DIGITS + 1];
512 g_game_vars.mult,
513 rect_width(&MULT_TEXT_RECT) / TTE_CHAR_SIZE,
514 mult_str_buff
515 );
516
517 tte_printf(
518 "#{P:%d,%d; cx:0x%X000;}%s",
519 MULT_TEXT_RECT.left,
520 MULT_TEXT_RECT.top,
521 TTE_WHITE_PB,
522 mult_str_buff
523 );
524
526}
527
528void display_deck_size_max(void)
529{
530 // TODO: the text will overflow if deck max size exceeds 99,
531 // we will need a fix at some point for this
532 tte_erase_rect_wrapper(DECK_SIZE_RECT);
533 tte_printf(
534 "#{P:%d,%d; cx:0x%X000}%d/%d",
535 DECK_SIZE_RECT.left,
536 DECK_SIZE_RECT.top,
537 TTE_WHITE_PB,
538 deck_get_size(),
539 deck_get_max_size()
540 );
541}
542
543// Returns true if the card is *considered* a face card
544bool card_is_face(Card* card)
545{
546 // Card is a face card, or Pareidolia is present
547 return (
548 card->rank == JACK || card->rank == QUEEN || card->rank == KING ||
549 is_joker_owned(PAREIDOLIA_JOKER_ID)
550 );
551}
552
553void display_temp_score(u32 value)
554{
555 char temp_score_str_buff[UINT_MAX_DIGITS + 1];
556 Rect temp_score_rect = TEMP_SCORE_RECT;
558 value,
559 rect_width(&temp_score_rect) / TTE_CHAR_SIZE,
560 temp_score_str_buff
561 );
562 update_text_rect_to_center_str(&temp_score_rect, temp_score_str_buff, SCREEN_RIGHT);
563
564 tte_erase_rect_wrapper(TEMP_SCORE_RECT);
565 tte_printf(
566 "#{P:%d,%d; cx:0x%X000}%s",
567 temp_score_rect.left,
568 temp_score_rect.top,
569 TTE_WHITE_PB,
570 temp_score_str_buff
571 );
572}
573
574void erase_temp_score(void)
575{
576 tte_erase_rect_wrapper(TEMP_SCORE_RECT);
577}
578
579void display_score(u32 value)
580{
581 Rect score_rect = SCORE_RECT;
582 // Clear the existing text before redrawing
583 tte_erase_rect_wrapper(SCORE_RECT);
584
585 char score_str_buff[UINT_MAX_DIGITS + 1];
586
587 truncate_uint_to_suffixed_str(value, rect_width(&score_rect) / TTE_CHAR_SIZE, score_str_buff);
588 update_text_rect_to_center_str(&score_rect, score_str_buff, SCREEN_RIGHT);
589
590 tte_printf(
591 "#{P:%d,%d; cx:0x%X000}%s",
592 score_rect.left,
593 score_rect.top,
594 TTE_WHITE_PB,
595 score_str_buff
596 );
597}
598
599void display_round(void)
600{
601 // tte_erase_rect_wrapper(ROUND_TEXT_RECT);
602 tte_printf(
603 "#{P:%d,%d; cx:0x%X000}%ld",
604 ROUND_TEXT_RECT.left,
605 ROUND_TEXT_RECT.top,
606 TTE_YELLOW_PB,
607 g_game_vars.round
608 );
609}
610
611void display_hands(void)
612{
613 tte_printf(
614 "#{P:%d,%d; cx:0x%X000}%ld",
615 HANDS_TEXT_RECT.left,
616 HANDS_TEXT_RECT.top,
617 TTE_BLUE_PB,
618 g_game_vars.hands
619 );
620}
621
622void display_discards(void)
623{
624 tte_printf(
625 "#{P:%d,%d; cx:0x%X000}%ld",
626 DISCARDS_TEXT_RECT.left,
627 DISCARDS_TEXT_RECT.top,
628 TTE_RED_PB,
629 g_game_vars.discards
630 );
631}
632
633int deck_get_size(void)
634{
635 return s_deck_top + 1;
636}
637
638static int deck_get_max_size(void)
639{
640 // This is the max amount of cards that the player currently has in their possession
641 return get_hand_top() + get_played_top() + s_deck_top + get_discard_top() + 4;
642}
643
644void deck_shuffle(void)
645{
646 for (int i = s_deck_top; i > 0; i--)
647 {
648 int j = rng_get_u32(RNG_SEQ_CARD_SHUFFLE) % (i + 1);
649 Card* temp = s_deck[i];
650 s_deck[i] = s_deck[j];
651 s_deck[j] = temp;
652 }
653}
654
655void game_start(void)
656{
658 tte_colors_setup();
659
660 g_game_vars.hands = MAX_HANDS;
661 g_game_vars.discards = MAX_DISCARDS;
662
663 // Fill the deck with all the cards. Later on this can be replaced with a more dynamic system
664 // that allows for different decks and card types.
665 for (int suit = 0; suit < NUM_SUITS; suit++)
666 {
667 for (int rank = 0; rank < NUM_RANKS; rank++)
668 {
669 Card* card = card_new(suit, rank);
670 deck_push(card);
671 }
672 }
673
674 change_background(BG_BLIND_SELECT, false);
675
676 // Deck size/max size
677 tte_erase_rect_wrapper(DECK_SIZE_RECT);
678 tte_printf(
679 "#{P:%d,%d; cx:0x%X000}%d/%d",
680 DECK_SIZE_RECT.left,
681 DECK_SIZE_RECT.top,
682 TTE_WHITE_PB,
683 deck_get_size(),
684 deck_get_max_size()
685 );
686
687 display_round(); // Set the round display
688 display_score(g_game_vars.score); // Set the score display
689
690 display_chips(); // Set the chips display
691 display_mult(); // Set the multiplier display
692
693 display_hands(); // Hand
694 display_discards(); // Discard
695
696 display_money(); // Set the money display
697 display_ante();
698
699 game_change_state(GAME_STATE_BLIND_SELECT);
700}
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.
Definition blind.c:156
Blind select state functions.
A button structure containing the common button functionalities Including highlight and pressing func...
Common functions to render UI elements.
void change_background(enum BackgroundId id, bool force_redraw)
Definition common_ui.c:35
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.
Definition hand.c:105
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.
Definition joker.c:310
All the functions used specifically to interact with Jokers. This includes browsing,...
Header of shared rects and points needed for ui.
A doubly-linked list.
bool list_is_empty(const List *list)
Definition list.c:62
List list_init(void)
Definition list.c:38
void * list_get_at_idx(List *list, unsigned int idx)
Definition list.c:219
int list_get_len(const List *list)
Definition list.c:214
void list_clear(List *list)
Definition list.c:44
void list_itr_remove_current_node(ListItr *itr)
Definition list.c:307
void * list_itr_next(ListItr *itr)
Definition list.c:281
bool list_remove_at_idx(List *list, unsigned int idx)
Definition list.c:237
void list_push_back(List *list, void *data)
Definition list.c:89
ListItr list_itr_create(List *list)
Definition list.c:257
Main menu state functions.
Options 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.
Definition random.c:22
u32 rng_get_u32(enum RngSequence key)
Get the next "randomly" generated number in the sequence corresponding to the given type.
Definition random.c:56
API relative to the Rounds we play.
int get_discard_top(void)
Get the index of the last discarded card.
Definition round.c:265
void toggle_flaming_score(void)
Checks whether the score that would result from the current Chips and Mult exceeds the current Blind'...
Definition round.c:1425
int get_played_top(void)
Get the index of the last played card.
Definition round.c:243
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.
Shop state functions.
JokerObject * game_shop_get_description_card(void)
Get a pointer to the Card we are currently showing the description of.
Definition shop.c:182
void game_shop_reset(void)
Initialize the shop for a run. Resets all the shop data for the run, needs to be called once per run.
Definition shop.c:187
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.
Definition sprite.c:340
void sprite_destroy(Sprite **sprite)
Destroy Sprite.
Definition sprite.c:93
State Machine.
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.
Definition card.h:50
A central location for all game variables.
A generic interface for all items that can appear in the shop or be in the inventory....
Definition item.h:76
An iterator into a list.
Definition list.h:91
A doubly-linked list.
Definition list.h:61
State machine callbacks.
State machine instance.
int state
The current state of the state machine, the offset into state_infos.
Timer constants.
Utilities relating around number string representation and protected arithmatic helper functions.
#define GBAL_RETURN_IF_NULL_RET(param, ret_val)
Checks if param is equal to NULL and prints error message and returns in case it is....
Definition util.h:95
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...
Definition util.c:116