Merge branch 'main' into game_over_screen
This commit is contained in:
Binary file not shown.
|
Before Width: | Height: | Size: 855 B After Width: | Height: | Size: 1.2 KiB |
@@ -0,0 +1 @@
|
||||
-gB4 -Mw4 -Mh4 -m! -pn 16
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.2 KiB |
@@ -0,0 +1 @@
|
||||
-gB4 -Mw4 -Mh4 -m! -pn 16
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
@@ -35,6 +35,8 @@
|
||||
#define NUM_RANKS 13
|
||||
#define RANK_OFFSET 2 // Because the first rank is 2 and ranks start at 0
|
||||
|
||||
#define IMPOSSIBLY_HIGH_CARD_VALUE 100
|
||||
|
||||
// Card types
|
||||
typedef struct
|
||||
{
|
||||
|
||||
+8
-2
@@ -23,6 +23,7 @@
|
||||
#define PEEK_DECK KEY_L // Not implemented
|
||||
#define SORT_HAND KEY_R
|
||||
#define PAUSE_GAME KEY_START // Not implemented
|
||||
#define SELL_KEY KEY_L
|
||||
|
||||
enum GameState
|
||||
{
|
||||
@@ -74,6 +75,10 @@ enum HandType
|
||||
void game_init();
|
||||
void game_update();
|
||||
|
||||
// Forward declaration
|
||||
struct List;
|
||||
typedef struct List List;
|
||||
|
||||
// Utility functions for other files
|
||||
typedef struct CardObject CardObject; // forward declaration, actually declared in card.h
|
||||
typedef struct JokerObject JokerObject;
|
||||
@@ -82,9 +87,10 @@ int get_hand_top(void);
|
||||
int hand_get_size(void);
|
||||
CardObject** get_played_array(void);
|
||||
int get_played_top(void);
|
||||
JokerObject** get_jokers(void);
|
||||
int get_jokers_top(void);
|
||||
List* get_jokers(void);
|
||||
|
||||
int get_deck_top(void);
|
||||
int get_num_discards_remaining(void);
|
||||
int get_money(void);
|
||||
|
||||
#endif // GAME_H
|
||||
+10
-4
@@ -34,14 +34,20 @@
|
||||
#define SE_COL_LEN 32
|
||||
|
||||
// Since y direction goes from the top of the screen to the bottom
|
||||
#define SE_UP -1
|
||||
#define SE_DOWN 1
|
||||
#define SCREEN_UP -1
|
||||
#define SCREEN_DOWN 1
|
||||
#define SCREEN_LEFT -1
|
||||
#define SCREEN_RIGHT 1
|
||||
|
||||
#define OVERFLOW_LEFT -1
|
||||
#define OVERFLOW_RIGHT 1
|
||||
#define SE_UP SCREEN_UP
|
||||
#define SE_DOWN SCREEN_DOWN
|
||||
|
||||
#define OVERFLOW_LEFT SCREEN_LEFT
|
||||
#define OVERFLOW_RIGHT SCREEN_RIGHT
|
||||
|
||||
// Tile size in pixels, both height and width as tiles are square
|
||||
#define TILE_SIZE 8
|
||||
#define EFFECT_TEXT_SEPARATION_AMOUNT 32; // If we need to show multiple effects at once
|
||||
|
||||
// By default TTE characters occupy a single tile
|
||||
#define TTE_CHAR_SIZE TILE_SIZE
|
||||
|
||||
@@ -78,6 +78,7 @@ void joker_destroy(Joker **joker);
|
||||
// Unique effects like "Four Fingers" or "Credit Card" will be hard coded into game.c with a conditional check for the joker ID from the players owned jokers
|
||||
// game.c should probably be restructured so most of the variables in it are moved to some sort of global variable header file so they can be easily accessed and modified for the jokers
|
||||
JokerEffect joker_get_score_effect(Joker *joker, Card *scored_card);
|
||||
int joker_get_sell_value(const Joker* joker);
|
||||
|
||||
JokerObject *joker_object_new(Joker *joker);
|
||||
void joker_object_destroy(JokerObject **joker_object);
|
||||
|
||||
@@ -13,5 +13,7 @@
|
||||
#include "joker_gfx9.h"
|
||||
#include "joker_gfx10.h"
|
||||
#include "joker_gfx11.h"
|
||||
#include "joker_gfx12.h"
|
||||
#include "joker_gfx13.h"
|
||||
|
||||
#endif
|
||||
+171
-63
@@ -76,10 +76,11 @@ static int selection_y = 0;
|
||||
|
||||
static bool sort_by_suit = false;
|
||||
|
||||
// Stacks
|
||||
static JokerObject *jokers[MAX_JOKERS_HELD_SIZE] = {NULL};
|
||||
static int jokers_top = -1;
|
||||
static List *jokers = NULL;
|
||||
static List *discarded_jokers = NULL;
|
||||
static List* jokers_available_to_shop; // List of joker IDs
|
||||
|
||||
// Stacks
|
||||
static CardObject *played[MAX_SELECTION_SIZE] = {NULL};
|
||||
static int played_top = -1;
|
||||
|
||||
@@ -92,19 +93,6 @@ static int deck_top = -1;
|
||||
static Card *discard_pile[MAX_DECK_SIZE] = {NULL};
|
||||
static int discard_top = -1;
|
||||
|
||||
// Joker stack
|
||||
static inline void joker_push(JokerObject *joker)
|
||||
{
|
||||
if (jokers_top >= MAX_JOKERS_HELD_SIZE - 1) return;
|
||||
jokers[++jokers_top] = joker;
|
||||
}
|
||||
|
||||
static inline JokerObject *joker_pop()
|
||||
{
|
||||
if (jokers_top < 0) return NULL;
|
||||
return jokers[jokers_top--];
|
||||
}
|
||||
|
||||
// Played stack
|
||||
static inline void played_push(CardObject *card_object)
|
||||
{
|
||||
@@ -166,15 +154,24 @@ int get_played_top(void) {
|
||||
return played_top;
|
||||
}
|
||||
|
||||
JokerObject **get_jokers(void) {
|
||||
List *get_jokers(void) {
|
||||
return jokers;
|
||||
}
|
||||
|
||||
int get_jokers_top(void) {
|
||||
return jokers_top;
|
||||
|
||||
|
||||
int get_deck_top(void) {
|
||||
return deck_top;
|
||||
}
|
||||
|
||||
int get_num_discards_remaining(void) {
|
||||
return discards;
|
||||
}
|
||||
|
||||
int get_money(void) {
|
||||
return money;
|
||||
}
|
||||
|
||||
List* jokers_available_to_shop; // List of joker IDs
|
||||
|
||||
// Consts
|
||||
|
||||
@@ -240,6 +237,10 @@ static const Rect ROUND_END_NUM_HANDS_RECT = {88, 116, UNDEFINED, UNDEF
|
||||
static const Rect HAND_REWARD_RECT = {168, UNDEFINED, UNDEFINED, UNDEFINED };
|
||||
static const Rect CASHOUT_RECT = {88, 72, UNDEFINED, UNDEFINED };
|
||||
static const Rect SHOP_REROLL_RECT = {88, 96, UNDEFINED, UNDEFINED };
|
||||
|
||||
static const BG_POINT HELD_JOKERS_POS = {108, 10};
|
||||
static const BG_POINT JOKER_DISCARD_TARGET = {240, 30};
|
||||
|
||||
#define ITEM_SHOP_Y 71 // TODO: Needs to be a rect?
|
||||
|
||||
//TODO: Properly define and use
|
||||
@@ -254,10 +255,6 @@ static const Rect SHOP_REROLL_RECT = {88, 96, UNDEFINED, UNDEFI
|
||||
#define PITCH_STEP_UNDISCARD_SFX 2*PITCH_STEP_DRAW_SFX
|
||||
// Naming the stage where cards return from the discard pile to the deck "undiscard"
|
||||
|
||||
int get_num_discards_remaining(void) {
|
||||
return discards;
|
||||
}
|
||||
|
||||
// General functions
|
||||
void set_seed(int seed)
|
||||
{
|
||||
@@ -1021,6 +1018,13 @@ void game_init()
|
||||
{
|
||||
jokers_available_to_shop_init();
|
||||
|
||||
// Initialize jokers list
|
||||
if (jokers) list_destroy(&jokers);
|
||||
jokers = list_new(MAX_JOKERS_HELD_SIZE);
|
||||
|
||||
if (discarded_jokers != NULL) list_destroy(&discarded_jokers);
|
||||
discarded_jokers = list_new(MAX_JOKERS_HELD_SIZE);
|
||||
|
||||
hands = max_hands;
|
||||
discards = max_discards;
|
||||
|
||||
@@ -1614,9 +1618,10 @@ static void played_cards_update_loop(bool* discarded_card, int* played_selection
|
||||
|
||||
if (*played_selections > 0)
|
||||
{
|
||||
for (int k = 0; k <= jokers_top; k++)
|
||||
for (int k = 0; k < list_get_size(jokers); k++)
|
||||
{
|
||||
if (joker_object_score(jokers[k], played[*played_selections - 1]->card, &chips, &mult, NULL, &money, NULL)) // NULLs aren't implemented yet
|
||||
JokerObject *joker = list_get(jokers, k);
|
||||
if (joker_object_score(joker, played[*played_selections - 1]->card, &chips, &mult, NULL, &money, NULL)) // NULLs aren't implemented yet
|
||||
{
|
||||
display_chips(chips);
|
||||
display_mult(mult);
|
||||
@@ -1632,11 +1637,12 @@ static void played_cards_update_loop(bool* discarded_card, int* played_selection
|
||||
scored_cards = j + 1; // Count the number of cards that have been scored
|
||||
if (scored_cards > *played_selections)
|
||||
{
|
||||
for (int k = 0; k <= jokers_top; k++)
|
||||
for (int k = 0; k < list_get_size(jokers); k++)
|
||||
{
|
||||
if (jokers[k] != NULL)
|
||||
JokerObject *joker = list_get(jokers, k);
|
||||
if (joker != NULL)
|
||||
{
|
||||
jokers[k]->joker->processed = false; // Reset the joker's processed state for the next score
|
||||
joker->joker->processed = false; // Reset the joker's processed state for the next score
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1663,9 +1669,10 @@ static void played_cards_update_loop(bool* discarded_card, int* played_selection
|
||||
{
|
||||
tte_erase_rect_wrapper(PLAYED_CARDS_SCORES_RECT);
|
||||
|
||||
for (int k = 0; k <= jokers_top; k++) // Independent joker scoring loop
|
||||
for (int k = 0; k <= list_get_size(jokers); k++) // Independent joker scoring loop
|
||||
{
|
||||
if (joker_object_score(jokers[k], NULL, &chips, &mult, NULL, &money, NULL)) // NULLs aren't implemented yet
|
||||
JokerObject *joker = list_get(jokers, k);
|
||||
if (joker_object_score(joker, NULL, &chips, &mult, NULL, &money, NULL)) // NULLs aren't implemented yet
|
||||
{
|
||||
display_chips(chips);
|
||||
display_mult(mult);
|
||||
@@ -1675,11 +1682,12 @@ static void played_cards_update_loop(bool* discarded_card, int* played_selection
|
||||
}
|
||||
}
|
||||
|
||||
for (int k = 0; k <= jokers_top; k++)
|
||||
for (int k = 0; k <= list_get_size(jokers); k++)
|
||||
{
|
||||
if (jokers[k] != NULL)
|
||||
JokerObject *joker = list_get(jokers, k);
|
||||
if (joker != NULL)
|
||||
{
|
||||
jokers[k]->joker->processed = false; // Reset the joker's processed state for the next round
|
||||
joker->joker->processed = false; // Reset the joker's processed state for the next round
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1774,6 +1782,26 @@ static void played_cards_update_loop(bool* discarded_card, int* played_selection
|
||||
}
|
||||
}
|
||||
|
||||
static void discarded_jokers_update_loop()
|
||||
{
|
||||
if (discarded_jokers == NULL)
|
||||
return;
|
||||
|
||||
// Iterating backwards because of removal within loop
|
||||
for (int i = list_get_size(discarded_jokers) - 1; i >= 0; i--)
|
||||
{
|
||||
JokerObject* joker_object = list_get(discarded_jokers, i);
|
||||
joker_object_update(joker_object);
|
||||
if (joker_object->sprite_object->x == joker_object->sprite_object->tx
|
||||
&& joker_object->sprite_object->y == joker_object->sprite_object->ty)
|
||||
{
|
||||
list_remove_by_idx(discarded_jokers, i);
|
||||
joker_object_destroy(&joker_object);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void held_jokers_update_loop()
|
||||
{
|
||||
const int spacing_lut[MAX_JOKERS_HELD_SIZE][MAX_JOKERS_HELD_SIZE] =
|
||||
@@ -1785,18 +1813,24 @@ static void held_jokers_update_loop()
|
||||
{40, 20, 0, -20, -40}
|
||||
};
|
||||
|
||||
FIXED hand_x = int2fx(108);
|
||||
FIXED hand_y = int2fx(10);
|
||||
FIXED hand_x = int2fx(HELD_JOKERS_POS.x);
|
||||
|
||||
int jokers_top = list_get_size(jokers) - 1;
|
||||
for (int i = jokers_top; i >= 0; i--)
|
||||
{
|
||||
jokers[i]->sprite_object->tx = hand_x - int2fx(spacing_lut[jokers_top][i]);
|
||||
jokers[i]->sprite_object->ty = hand_y;
|
||||
JokerObject *joker = list_get(jokers, i);
|
||||
joker->sprite_object->tx = hand_x - int2fx(spacing_lut[jokers_top][i]);
|
||||
|
||||
joker_object_update(jokers[i]);
|
||||
joker_object_update(joker);
|
||||
}
|
||||
}
|
||||
|
||||
static void jokers_update_loop()
|
||||
{
|
||||
held_jokers_update_loop();
|
||||
discarded_jokers_update_loop();
|
||||
}
|
||||
|
||||
static void game_playing_ui_text_update()
|
||||
{
|
||||
static int last_hand_size = 0;
|
||||
@@ -2148,6 +2182,25 @@ static int reroll_cost = REROLL_BASE_COST;
|
||||
#define REROLL_BTN_FRAME_PAL_IDX 7
|
||||
#define REROLL_BTN_PAL_IDX 3
|
||||
|
||||
void print_price_under_sprite_object(SpriteObject *sprite_object, int price)
|
||||
{
|
||||
int x = fx2int(sprite_object->tx) + TILE_SIZE - (get_digits_even(price) - 1) * TILE_SIZE;
|
||||
int y = fx2int(sprite_object->ty) + CARD_SPRITE_SIZE + TILE_SIZE; // TODO: Should probably extract the sprite size
|
||||
tte_printf("#{P:%d,%d; cx:0xC000}$%d", x, y, price);
|
||||
}
|
||||
|
||||
void erase_price_under_sprite_object(SpriteObject *sprite_object)
|
||||
{
|
||||
Rect price_rect;
|
||||
price_rect.left = fx2int(sprite_object->tx);
|
||||
price_rect.top = fx2int(sprite_object->ty) + CARD_SPRITE_SIZE + TILE_SIZE;
|
||||
// TODO: Should probably extract the size from the sprite
|
||||
|
||||
price_rect.right = price_rect.left + TILE_SIZE * 3;
|
||||
price_rect.bottom = price_rect.top + 2*TILE_SIZE; // Taking 2 tiles down so the highlighted case is also covered
|
||||
tte_erase_rect_wrapper(price_rect);
|
||||
}
|
||||
|
||||
static void game_shop_create_items()
|
||||
{
|
||||
tte_erase_rect_wrapper(SHOP_PRICES_TEXT_RECT);
|
||||
@@ -2173,9 +2226,7 @@ static void game_shop_create_items()
|
||||
joker_object->sprite_object->tx = joker_object->sprite_object->x;
|
||||
joker_object->sprite_object->ty = int2fx(ITEM_SHOP_Y);
|
||||
|
||||
int x = fx2int(joker_object->sprite_object->tx) + TILE_SIZE - (get_digits_even(joker_object->joker->value) - 1) * TILE_SIZE;
|
||||
int y = fx2int(joker_object->sprite_object->ty) + CARD_SPRITE_SIZE + TILE_SIZE;
|
||||
tte_printf("#{P:%d,%d; cx:0xC000}$%d", x, y, joker_object->joker->value);
|
||||
print_price_under_sprite_object(joker_object->sprite_object, joker_object->joker->value);
|
||||
|
||||
sprite_position(joker_object_get_sprite(joker_object), fx2int(joker_object->sprite_object->x), fx2int(joker_object->sprite_object->y));
|
||||
list_append(shop_jokers, joker_object);
|
||||
@@ -2248,28 +2299,86 @@ static void game_shop_reroll(int *reroll_cost)
|
||||
tte_printf("#{P:%d,%d; cx:0xF000}$%d", SHOP_REROLL_RECT.left, SHOP_REROLL_RECT.top, *reroll_cost);
|
||||
}
|
||||
|
||||
static int jokers_sel_row_get_size()
|
||||
{
|
||||
return list_get_size(jokers);
|
||||
}
|
||||
|
||||
static void jokers_sel_row_on_selection_changed(SelectionGrid *selection_grid,
|
||||
int row_idx,
|
||||
const Selection *prev_selection,
|
||||
const Selection *new_selection)
|
||||
{
|
||||
if (prev_selection->y == row_idx)
|
||||
{
|
||||
JokerObject* joker_object = list_get(jokers, prev_selection->x);
|
||||
erase_price_under_sprite_object(joker_object->sprite_object);
|
||||
sprite_object_set_focus(joker_object->sprite_object, false);
|
||||
}
|
||||
|
||||
if (new_selection->y == row_idx)
|
||||
{
|
||||
JokerObject* joker_object = list_get(jokers, new_selection->x);
|
||||
sprite_object_set_focus(joker_object->sprite_object, true);
|
||||
print_price_under_sprite_object(joker_object->sprite_object, joker_get_sell_value(joker_object->joker));
|
||||
}
|
||||
}
|
||||
|
||||
void joker_start_discard_animation(JokerObject *joker_object)
|
||||
{
|
||||
joker_object->sprite_object->tx = int2fx(JOKER_DISCARD_TARGET.x);
|
||||
joker_object->sprite_object->ty = int2fx(JOKER_DISCARD_TARGET.y);
|
||||
list_append(discarded_jokers, joker_object);
|
||||
}
|
||||
|
||||
void game_sell_joker(int joker_idx)
|
||||
{
|
||||
if (joker_idx < 0 || joker_idx > list_get_size(jokers))
|
||||
return;
|
||||
|
||||
JokerObject *joker_object = list_get(jokers, joker_idx);
|
||||
money += joker_get_sell_value(joker_object->joker);
|
||||
display_money(money);
|
||||
erase_price_under_sprite_object(joker_object->sprite_object);
|
||||
|
||||
list_remove_by_idx(jokers, joker_idx);
|
||||
int_list_append(jokers_available_to_shop, (intptr_t)joker_object->joker->id);
|
||||
|
||||
joker_start_discard_animation(joker_object);
|
||||
}
|
||||
|
||||
static void jokers_sel_row_on_key_hit(SelectionGrid* selection_grid, Selection* selection)
|
||||
{
|
||||
if (!key_hit(SELL_KEY))
|
||||
return;
|
||||
|
||||
game_sell_joker(selection->x);
|
||||
// Move the selection away from the jokers so it doesn't point to an invalid place
|
||||
selection_grid_move_selection_vert(selection_grid, SCREEN_DOWN);
|
||||
}
|
||||
|
||||
// Shop input
|
||||
static int shop_top_row_get_size()
|
||||
{
|
||||
return list_get_size(shop_jokers) + 1; // + 1 to account for next round button
|
||||
}
|
||||
|
||||
void add_joker(JokerObject *joker_object)
|
||||
{
|
||||
list_append(jokers, joker_object);
|
||||
joker_object->sprite_object->ty = int2fx(HELD_JOKERS_POS.y);
|
||||
}
|
||||
|
||||
static void game_shop_buy_joker(int shop_joker_idx)
|
||||
{
|
||||
JokerObject *joker_object = list_get(shop_jokers, shop_joker_idx);
|
||||
joker_push(joker_object);
|
||||
|
||||
money -= joker_object->joker->value; // Deduct the money spent on the joker
|
||||
display_money(money); // Update the money display
|
||||
erase_price_under_sprite_object(joker_object->sprite_object);
|
||||
sprite_object_set_focus(joker_object->sprite_object, false);
|
||||
|
||||
Rect joker_price_rect;
|
||||
joker_price_rect.left = fx2int(joker_object->sprite_object->tx);
|
||||
// 2*TILE_SIZE because the item is highlighted and raised by 1 additional tile
|
||||
joker_price_rect.top = fx2int(joker_object->sprite_object->ty) + CARD_SPRITE_SIZE + 2 * TILE_SIZE;
|
||||
joker_price_rect.right = joker_price_rect.left + TILE_SIZE * 3;
|
||||
joker_price_rect.bottom = joker_price_rect.top + TILE_SIZE;
|
||||
|
||||
tte_erase_rect_wrapper(joker_price_rect);
|
||||
|
||||
add_joker(joker_object);
|
||||
list_remove_by_idx(shop_jokers, shop_joker_idx); // Remove the joker from the shop
|
||||
}
|
||||
|
||||
@@ -2297,7 +2406,7 @@ static void shop_top_row_on_key_hit(SelectionGrid* selection_grid, Selection* se
|
||||
int shop_joker_idx = selection->x - 1; // - 1 to account for next round button
|
||||
JokerObject *joker_object = list_get(shop_jokers, shop_joker_idx);
|
||||
if (joker_object == NULL
|
||||
|| jokers_top >= MAX_JOKERS_HELD_SIZE - 1
|
||||
|| list_get_size(jokers) >= MAX_JOKERS_HELD_SIZE
|
||||
|| money < joker_object->joker->value)
|
||||
{
|
||||
return;
|
||||
@@ -2348,12 +2457,12 @@ static void shop_top_row_on_selection_changed(SelectionGrid* selection_grid, int
|
||||
}
|
||||
}
|
||||
|
||||
static int shop_bottom_row_get_size()
|
||||
static int shop_reroll_row_get_size()
|
||||
{
|
||||
return 1; // Currently only the reroll button
|
||||
return 1; // Only the reroll button
|
||||
}
|
||||
|
||||
static void shop_bottom_row_on_selection_changed(SelectionGrid* selection_grid, int row_idx, const Selection* prev_selection, const Selection* new_selection)
|
||||
static void shop_reroll_row_on_selection_changed(SelectionGrid* selection_grid, int row_idx, const Selection* prev_selection, const Selection* new_selection)
|
||||
{
|
||||
if (row_idx == prev_selection->y)
|
||||
{
|
||||
@@ -2366,7 +2475,7 @@ static void shop_bottom_row_on_selection_changed(SelectionGrid* selection_grid,
|
||||
}
|
||||
}
|
||||
|
||||
static void shop_bottom_row_on_key_hit(SelectionGrid* selection_grid, Selection* selection)
|
||||
static void shop_reroll_row_on_key_hit(SelectionGrid* selection_grid, Selection* selection)
|
||||
{
|
||||
if (money >= reroll_cost)
|
||||
{
|
||||
@@ -2376,11 +2485,12 @@ static void shop_bottom_row_on_key_hit(SelectionGrid* selection_grid, Selection*
|
||||
|
||||
SelectionGridRow shop_selection_rows[] =
|
||||
{
|
||||
{0, shop_top_row_get_size, shop_top_row_on_selection_changed, shop_top_row_on_key_hit},
|
||||
{1, shop_bottom_row_get_size, shop_bottom_row_on_selection_changed, shop_bottom_row_on_key_hit}
|
||||
{0, jokers_sel_row_get_size, jokers_sel_row_on_selection_changed, jokers_sel_row_on_key_hit},
|
||||
{1, shop_top_row_get_size, shop_top_row_on_selection_changed, shop_top_row_on_key_hit},
|
||||
{2, shop_reroll_row_get_size, shop_reroll_row_on_selection_changed, shop_reroll_row_on_key_hit}
|
||||
};
|
||||
|
||||
static const Selection SHOP_INIT_SEL = {-1, 0};
|
||||
static const Selection SHOP_INIT_SEL = {-1, 1};
|
||||
|
||||
SelectionGrid shop_selection_grid = {shop_selection_rows, NUM_ELEM_IN_ARR(shop_selection_rows), SHOP_INIT_SEL};
|
||||
|
||||
@@ -2531,8 +2641,6 @@ void game_shop()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void game_blind_select()
|
||||
{
|
||||
switch (state) // I'm only using magic numbers here for the sake of simplicity since it's just sequential, but you can replace them with named constants or enums if it makes it clearer
|
||||
@@ -2710,7 +2818,7 @@ void game_update()
|
||||
}
|
||||
}
|
||||
|
||||
held_jokers_update_loop();
|
||||
jokers_update_loop();
|
||||
|
||||
switch (game_state)
|
||||
{
|
||||
|
||||
+14
-1
@@ -130,6 +130,8 @@ void joker_init()
|
||||
joker_gfxTiles[9] = joker_gfx9Tiles;
|
||||
joker_gfxTiles[10] = joker_gfx10Tiles;
|
||||
joker_gfxTiles[11] = joker_gfx11Tiles;
|
||||
joker_gfxTiles[12] = joker_gfx12Tiles;
|
||||
joker_gfxTiles[13] = joker_gfx13Tiles;
|
||||
|
||||
joker_gfxPal[0] = joker_gfx0Pal;
|
||||
joker_gfxPal[1] = joker_gfx1Pal;
|
||||
@@ -143,6 +145,8 @@ void joker_init()
|
||||
joker_gfxPal[9] = joker_gfx9Pal;
|
||||
joker_gfxPal[10] = joker_gfx10Pal;
|
||||
joker_gfxPal[11] = joker_gfx11Pal;
|
||||
joker_gfxPal[12] = joker_gfx12Pal;
|
||||
joker_gfxPal[13] = joker_gfx13Pal;
|
||||
|
||||
for (int i = 0; i < num_spritesheets; i++)
|
||||
{
|
||||
@@ -181,6 +185,16 @@ JokerEffect joker_get_score_effect(Joker *joker, Card *scored_card)
|
||||
return jinfo->effect(joker, scored_card);
|
||||
}
|
||||
|
||||
int joker_get_sell_value(const Joker* joker)
|
||||
{
|
||||
if (joker == NULL)
|
||||
{
|
||||
return UNDEFINED;
|
||||
}
|
||||
|
||||
return joker->value/2;
|
||||
}
|
||||
|
||||
// JokerObject methods
|
||||
JokerObject *joker_object_new(Joker *joker)
|
||||
{
|
||||
@@ -320,7 +334,6 @@ bool joker_object_score(JokerObject *joker_object, Card* scored_card, int *chips
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void joker_object_set_selected(JokerObject* joker_object, bool selected)
|
||||
{
|
||||
if (joker_object == NULL)
|
||||
|
||||
+226
-24
@@ -2,6 +2,7 @@
|
||||
#include "joker.h"
|
||||
#include "util.h"
|
||||
#include "hand_analysis.h"
|
||||
#include "list.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
static JokerEffect default_joker_effect(Joker *joker, Card *scored_card) {
|
||||
@@ -191,16 +192,19 @@ static JokerEffect joker_stencil_effect(Joker *joker, Card *scored_card) {
|
||||
if (scored_card != NULL)
|
||||
return effect; // if card != null, we are not at the end-phase of scoring yet
|
||||
|
||||
List* jokers = get_jokers();
|
||||
|
||||
// +1 xmult per empty joker slot...
|
||||
int num_jokers = get_jokers_top() + 1;
|
||||
int num_jokers = list_get_size(jokers);
|
||||
|
||||
effect.xmult = (MAX_JOKERS_HELD_SIZE) - num_jokers;
|
||||
|
||||
// ...and also each stencil_joker adds +1 xmult
|
||||
JokerObject** jokers = get_jokers();
|
||||
|
||||
for (int i = 0; i < num_jokers; i++ )
|
||||
{
|
||||
if (jokers[i]->joker->id == JOKER_STENCIL_ID)
|
||||
JokerObject* joker_object = list_get(jokers, i);
|
||||
if (joker_object->joker->id == JOKER_STENCIL_ID)
|
||||
effect.xmult++;
|
||||
}
|
||||
|
||||
@@ -290,30 +294,228 @@ static JokerEffect blackboard_joker_effect(Joker *joker, Card *scored_card) {
|
||||
return effect;
|
||||
}
|
||||
|
||||
static JokerEffect blue_joker_effect(Joker *joker, Card *scored_card) {
|
||||
JokerEffect effect = {0};
|
||||
if (scored_card != NULL)
|
||||
return effect; // if card != null, we are not at the end-phase of scoring yet
|
||||
|
||||
effect.chips = (get_deck_top() + 1) * 2;
|
||||
|
||||
return effect;
|
||||
}
|
||||
|
||||
// Using __attribute__((unused)) for jokers with no sprites yet to avoid warning
|
||||
// Remove the attribute once they have sprites
|
||||
__attribute__((unused))
|
||||
static JokerEffect raised_fist_joker_effect(Joker *joker, Card *scored_card)
|
||||
{
|
||||
JokerEffect effect = {0};
|
||||
if (scored_card != NULL)
|
||||
return effect; // if card != null, we are not at the end-phase of scoring yet
|
||||
|
||||
// Find the lowest rank card in hand
|
||||
// Aces are always considered high value, even in an ace-low straight
|
||||
u8 lowest_value = IMPOSSIBLY_HIGH_CARD_VALUE;
|
||||
CardObject** hand = get_hand_array();
|
||||
int hand_size = hand_get_size();
|
||||
for (int i = 0; i < hand_size; i++ )
|
||||
{
|
||||
u8 value = card_get_value(hand[i]->card);
|
||||
if (lowest_value > value)
|
||||
lowest_value = value;
|
||||
}
|
||||
|
||||
if (lowest_value != IMPOSSIBLY_HIGH_CARD_VALUE)
|
||||
effect.mult = lowest_value * 2;
|
||||
|
||||
return effect;
|
||||
}
|
||||
|
||||
__attribute__((unused))
|
||||
static JokerEffect reserved_parking_joker_effect(Joker *joker, Card *scored_card) {
|
||||
JokerEffect effect = {0};
|
||||
if (scored_card != NULL)
|
||||
return effect; // if card != null, we are not at the end-phase of scoring yet
|
||||
|
||||
CardObject** hand = get_hand_array();
|
||||
int hand_size = hand_get_size();
|
||||
for (int i = 0; i < hand_size; i++ )
|
||||
{
|
||||
switch (hand[i]->card->rank) {
|
||||
case KING: case QUEEN: case JACK:
|
||||
if (random() % 2 == 0)
|
||||
effect.money += 1;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return effect;
|
||||
};
|
||||
|
||||
static JokerEffect business_card_joker_effect(Joker *joker, Card *scored_card) {
|
||||
JokerEffect effect = {0};
|
||||
if (scored_card == NULL)
|
||||
return effect;
|
||||
|
||||
switch (scored_card->rank) {
|
||||
case KING: case QUEEN: case JACK:
|
||||
if (random() % 2 == 0)
|
||||
effect.money = 2;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return effect;
|
||||
}
|
||||
|
||||
static JokerEffect scholar_joker_effect(Joker *joker, Card *scored_card) {
|
||||
JokerEffect effect = {0};
|
||||
if (scored_card == NULL)
|
||||
return effect;
|
||||
|
||||
if (scored_card->rank == ACE) {
|
||||
effect.chips = 20;
|
||||
effect.mult = 4;
|
||||
}
|
||||
|
||||
return effect;
|
||||
}
|
||||
|
||||
__attribute__((unused))
|
||||
static JokerEffect scary_face_joker_effect(Joker *joker, Card *scored_card) {
|
||||
JokerEffect effect = {0};
|
||||
if (scored_card == NULL)
|
||||
return effect;
|
||||
|
||||
switch (scored_card->rank) {
|
||||
case KING: case QUEEN: case JACK:
|
||||
effect.chips = 30;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return effect;
|
||||
}
|
||||
|
||||
__attribute__((unused))
|
||||
static JokerEffect abstract_joker_effect(Joker *joker, Card *scored_card) {
|
||||
JokerEffect effect = {0};
|
||||
if (scored_card != NULL)
|
||||
return effect; // if card != null, we are not at the end-phase of scoring yet
|
||||
|
||||
// +1 xmult per occupied joker slot
|
||||
int num_jokers = list_get_size(get_jokers());
|
||||
effect.mult = num_jokers * 3;
|
||||
|
||||
return effect;
|
||||
}
|
||||
|
||||
__attribute__((unused))
|
||||
static JokerEffect bull_joker_effect(Joker *joker, Card *scored_card) {
|
||||
JokerEffect effect = {0};
|
||||
if (scored_card != NULL)
|
||||
return effect; // if card != null, we are not at the end-phase of scoring yet
|
||||
|
||||
effect.chips = get_money() * 2;
|
||||
|
||||
return effect;
|
||||
}
|
||||
|
||||
__attribute__((unused))
|
||||
static JokerEffect smiley_face_joker_effect(Joker *joker, Card *scored_card) {
|
||||
JokerEffect effect = {0};
|
||||
if (scored_card == NULL)
|
||||
return effect;
|
||||
|
||||
switch (scored_card->rank) {
|
||||
case KING: case QUEEN: case JACK:
|
||||
effect.mult = 5;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return effect;
|
||||
}
|
||||
|
||||
static JokerEffect even_steven_joker_effect(Joker *joker, Card *scored_card) {
|
||||
JokerEffect effect = {0};
|
||||
if (scored_card == NULL)
|
||||
return effect;
|
||||
|
||||
if (card_get_value(scored_card) % 2 == 0) {
|
||||
switch (scored_card->rank) {
|
||||
case KING: case QUEEN: case JACK:
|
||||
break;
|
||||
default:
|
||||
effect.mult = 4;
|
||||
}
|
||||
}
|
||||
|
||||
return effect;
|
||||
}
|
||||
|
||||
static JokerEffect odd_todd_joker_effect(Joker *joker, Card *scored_card) {
|
||||
JokerEffect effect = {0};
|
||||
if (scored_card == NULL)
|
||||
return effect;
|
||||
|
||||
if (card_get_value(scored_card) % 2 == 1) // todo test ace
|
||||
effect.chips = 31;
|
||||
|
||||
return effect;
|
||||
}
|
||||
|
||||
/* The index of a joker in the registry matches its ID.
|
||||
* The joker sprites are matched by ID so the position in the registry
|
||||
* determines the joker's sprite.
|
||||
* Each consecutive NUM_JOKERS_PER_SPRITESHEET (defined in joker.c) jokers
|
||||
* share a spritesheet and thus a color palette.
|
||||
* To make better use of color palettes jokers may be rearranged here
|
||||
* (and put together in the matching spritesheet) to share a color palette.
|
||||
* Otherwise the order is similar to the wiki.
|
||||
*/
|
||||
const JokerInfo joker_registry[] = {
|
||||
{ COMMON_JOKER, 2, default_joker_effect }, // DEFAULT_JOKER_ID = 0
|
||||
{ COMMON_JOKER, 5, greedy_joker_effect }, // GREEDY_JOKER_ID = 1
|
||||
{ COMMON_JOKER, 5, lusty_joker_effect }, // etc...
|
||||
{ COMMON_JOKER, 5, wrathful_joker_effect },
|
||||
{ COMMON_JOKER, 5, gluttonous_joker_effect },
|
||||
{ COMMON_JOKER, 3, jolly_joker_effect },
|
||||
{ COMMON_JOKER, 4, zany_joker_effect },
|
||||
{ COMMON_JOKER, 4, mad_joker_effect },
|
||||
{ COMMON_JOKER, 4, crazy_joker_effect },
|
||||
{ COMMON_JOKER, 4, droll_joker_effect },
|
||||
{ COMMON_JOKER, 3, sly_joker_effect },
|
||||
{ COMMON_JOKER, 4, wily_joker_effect },
|
||||
{ COMMON_JOKER, 4, clever_joker_effect },
|
||||
{ COMMON_JOKER, 4, devious_joker_effect },
|
||||
{ COMMON_JOKER, 4, crafty_joker_effect },
|
||||
{ COMMON_JOKER, 5, half_joker_effect },
|
||||
{ UNCOMMON_JOKER, 8, joker_stencil_effect },
|
||||
{ COMMON_JOKER, 5, banner_joker_effect },
|
||||
{ COMMON_JOKER, 4, walkie_talkie_joker_effect },
|
||||
{ UNCOMMON_JOKER, 8, fibonnaci_joker_effect },
|
||||
{ UNCOMMON_JOKER, 6, blackboard_joker_effect },
|
||||
{ COMMON_JOKER, 5, mystic_summit_joker_effect },
|
||||
{ COMMON_JOKER, 4, misprint_joker_effect },
|
||||
{ COMMON_JOKER, 5, lusty_joker_effect }, // etc... 2
|
||||
{ COMMON_JOKER, 5, wrathful_joker_effect }, // 3
|
||||
{ COMMON_JOKER, 5, gluttonous_joker_effect }, // 4
|
||||
{ COMMON_JOKER, 3, jolly_joker_effect }, // 5
|
||||
{ COMMON_JOKER, 4, zany_joker_effect }, // 6
|
||||
{ COMMON_JOKER, 4, mad_joker_effect }, // 7
|
||||
{ COMMON_JOKER, 4, crazy_joker_effect }, // 8
|
||||
{ COMMON_JOKER, 4, droll_joker_effect }, // 9
|
||||
{ COMMON_JOKER, 3, sly_joker_effect }, // 10
|
||||
{ COMMON_JOKER, 4, wily_joker_effect }, // 11
|
||||
{ COMMON_JOKER, 4, clever_joker_effect }, // 12
|
||||
{ COMMON_JOKER, 4, devious_joker_effect }, // 13
|
||||
{ COMMON_JOKER, 4, crafty_joker_effect }, // 14
|
||||
{ COMMON_JOKER, 5, half_joker_effect }, // 15
|
||||
{ UNCOMMON_JOKER, 8, joker_stencil_effect }, // 16
|
||||
{ COMMON_JOKER, 5, banner_joker_effect }, // 17
|
||||
{ COMMON_JOKER, 4, walkie_talkie_joker_effect }, // 18
|
||||
{ UNCOMMON_JOKER, 8, fibonnaci_joker_effect }, // 19
|
||||
{ UNCOMMON_JOKER, 6, blackboard_joker_effect }, // 20
|
||||
{ COMMON_JOKER, 5, mystic_summit_joker_effect }, // 21
|
||||
{ COMMON_JOKER, 4, misprint_joker_effect }, // 22
|
||||
{ COMMON_JOKER, 4, even_steven_joker_effect }, // 23
|
||||
{ COMMON_JOKER, 5, blue_joker_effect }, // 24
|
||||
{ COMMON_JOKER, 4, odd_todd_joker_effect }, // 25
|
||||
{ COMMON_JOKER, 4, scholar_joker_effect }, // 26
|
||||
{ COMMON_JOKER, 4, business_card_joker_effect }, // 27
|
||||
// Business card should be paired with Shortcut for palette optimization when it's added
|
||||
|
||||
// The following jokers don't have sprites yet,
|
||||
// uncomment them when their sprites are added.
|
||||
#if 0
|
||||
{ COMMON_JOKER, 5, raised_fist_joker_effect },
|
||||
{ COMMON_JOKER, 6, reserved_parking_joker_effect },
|
||||
{ COMMON_JOKER, 4, scary_face_joker_effect },
|
||||
{ COMMON_JOKER, 4, abstract_joker_effect },
|
||||
{ UNCOMMON_JOKER, 6, bull_joker_effect},
|
||||
{ COMMON_JOKER, 4, smiley_face_joker_effect },
|
||||
#endif
|
||||
};
|
||||
|
||||
static const size_t joker_registry_size = NUM_ELEM_IN_ARR(joker_registry);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "list.h"
|
||||
#include "util.h"
|
||||
|
||||
@@ -49,6 +49,9 @@ void selection_grid_move_selection_vert(SelectionGrid *selection_grid, int direc
|
||||
&& new_selection.y < selection_grid->num_rows)
|
||||
{
|
||||
int new_row_size = selection_grid->rows[new_selection.y].get_size();
|
||||
if (new_row_size <= 0)
|
||||
return;
|
||||
|
||||
if (selection.x >= new_row_size)
|
||||
{
|
||||
// TODO: Maintain relative horizontal position
|
||||
|
||||
@@ -119,6 +119,7 @@ SpriteObject* sprite_object_new()
|
||||
sprite_object->sprite = NULL;
|
||||
sprite_object_reset_transform(sprite_object);
|
||||
sprite_object->selected = false;
|
||||
sprite_object->focused = false;
|
||||
|
||||
return sprite_object;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user