Compare commits
4 Commits
6a58fa2601
...
5ad8fa1534
Author | SHA1 | Date | |
---|---|---|---|
5ad8fa1534 | |||
08823cc3b9 | |||
453060ee07 | |||
4963835a13 |
@ -7,6 +7,7 @@ typedef enum DekiyakuAction {
|
||||
DEKIYAKU_ACTION_NONE,
|
||||
DEKIYAKU_ACTION_SAGE,
|
||||
DEKIYAKU_ACTION_SHOUBU,
|
||||
DEKIYAKU_ACTION_CANCEL,
|
||||
} DekiyakuAction;
|
||||
|
||||
typedef enum DekiyakuMeldType {
|
||||
|
13
dialog.c
13
dialog.c
@ -9,13 +9,24 @@
|
||||
Dialog dialogs[2];
|
||||
|
||||
void handle_click_cancel_yes(Game *g) {
|
||||
g->state = GAME_STATE_CHOOSING_FROM_HAND;
|
||||
g->player.dekiyaku_action = DEKIYAKU_ACTION_CANCEL;
|
||||
g->state = GAME_STATE_CALCULATING_DEKIYAKU_SCORE;
|
||||
}
|
||||
|
||||
void handle_click_cancel_no(Game *g) {
|
||||
g->state = GAME_STATE_CHOOSING_FROM_HAND;
|
||||
}
|
||||
|
||||
void handle_click_shoubu(Game *g) {
|
||||
g->player.dekiyaku_action = DEKIYAKU_ACTION_SHOUBU;
|
||||
g->state = GAME_STATE_CALCULATING_DEKIYAKU_SCORE;
|
||||
}
|
||||
|
||||
void handle_click_sage(Game *g) {
|
||||
g->player.dekiyaku_action = DEKIYAKU_ACTION_SAGE;
|
||||
g->state = GAME_STATE_CHOOSING_FROM_HAND;
|
||||
}
|
||||
|
||||
void init_dialogs(Game *g) {
|
||||
Dialog *cancel_dialog = &dialogs[0];
|
||||
cancel_dialog->text = malloc(200);
|
||||
|
201
game.c
201
game.c
@ -14,23 +14,19 @@ Vector2 mouse_pos;
|
||||
char teyaku_calculation[400];
|
||||
|
||||
void initialize_game(Game *g) {
|
||||
Image cards_image = LoadImage("img/cards.png");
|
||||
g->cards_texture = LoadTextureFromImage(cards_image);
|
||||
UnloadImage(cards_image);
|
||||
|
||||
g->deck.count = 0;
|
||||
g->deck.position = (Vector2) { 800, 400 };
|
||||
g->deck.display_type = HAND_DISPLAY_DECK;
|
||||
g->should_close = false;
|
||||
g->state = GAME_STATE_INITIALIZING;
|
||||
g->field_multiplier = NULL;
|
||||
g->player.teyaku.calculated = false;
|
||||
g->left.teyaku.calculated = false;
|
||||
g->right.teyaku.calculated = false;
|
||||
g->player.dekiyaku_score = 0;
|
||||
g->left.dekiyaku_score = 0;
|
||||
g->right.dekiyaku_score = 0;
|
||||
g->kan_value = 12;
|
||||
g->current_play_from_hand = NULL;
|
||||
g->current_play_target = NULL;
|
||||
g->turn_number = -1;
|
||||
g->dialog = NULL;
|
||||
|
||||
init_dialogs(g);
|
||||
|
||||
for (int i = 0; i < 48; i++) {
|
||||
@ -74,12 +70,8 @@ void initialize_game(Game *g) {
|
||||
g->cards[i].move.destination = (Vector2) { 800, 400 };
|
||||
g->cards[i].order = i;
|
||||
g->cards[i].selected = false;
|
||||
g->deck.cards[i] = &g->cards[i];
|
||||
g->deck.count++;
|
||||
}
|
||||
|
||||
shuffle_hand(&g->deck);
|
||||
|
||||
g->player.points = 10 * g->kan_value;
|
||||
g->right.points = 10 * g->kan_value;
|
||||
g->left.points = 10 * g->kan_value;
|
||||
@ -87,34 +79,28 @@ void initialize_game(Game *g) {
|
||||
g->right.points_string[0] = '\0';
|
||||
g->left.points_string[0] = '\0';
|
||||
|
||||
g->player.hand.count = 0;
|
||||
g->player.teyaku.calculated = false;
|
||||
g->right.teyaku.calculated = false;
|
||||
g->left.teyaku.calculated = false;
|
||||
|
||||
g->player.hand.position = (Vector2) { 300, 600 };
|
||||
g->player.hand.display_type = HAND_DISPLAY_ROW;
|
||||
g->right.hand.count = 0;
|
||||
g->right.hand.position = (Vector2) { 750, 125 };
|
||||
g->right.hand.display_type = HAND_DISPLAY_ROW;
|
||||
g->left.hand.count = 0;
|
||||
g->left.hand.position = (Vector2) { 50, 125 };
|
||||
g->left.hand.display_type = HAND_DISPLAY_ROW;
|
||||
g->field.count = 0;
|
||||
g->field.position = (Vector2) { 400, 300 };
|
||||
g->field.display_type = HAND_DISPLAY_FIELD;
|
||||
g->player.scored.count = 0;
|
||||
g->player.scored.position = (Vector2) { 300, 750 };
|
||||
g->player.scored.display_type = HAND_DISPLAY_SCORED;
|
||||
g->right.scored.count = 0;
|
||||
g->right.scored.position = (Vector2) { 750, 25 };
|
||||
g->right.scored.display_type = HAND_DISPLAY_SCORED;
|
||||
g->left.scored.count = 0;
|
||||
g->left.scored.position = (Vector2) { 50, 25 };
|
||||
g->left.scored.display_type = HAND_DISPLAY_SCORED;
|
||||
|
||||
strcpy(teyaku_calculation, "");
|
||||
|
||||
Image cards_image = LoadImage("img/cards.png");
|
||||
g->cards_texture = LoadTextureFromImage(cards_image);
|
||||
UnloadImage(cards_image);
|
||||
g->state = GAME_STATE_DEALING;
|
||||
g->state = GAME_STATE_INITIALIZING;
|
||||
}
|
||||
|
||||
Player *current_player(Game *g) {
|
||||
@ -126,14 +112,19 @@ Player *current_player(Game *g) {
|
||||
case 2:
|
||||
return &g->left;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool is_player_turn(Game *g) {
|
||||
return current_player(g) == &g->player;
|
||||
}
|
||||
|
||||
bool stale_calculation = true;
|
||||
void handle_input(Game *g) {
|
||||
if (IsKeyPressed(KEY_R)) {
|
||||
g->state = GAME_STATE_INITIALIZING;
|
||||
return;
|
||||
}
|
||||
if (!is_player_turn(g)) return;
|
||||
if (g->dialog) return dialog_handle_input(g->dialog);
|
||||
|
||||
@ -204,6 +195,31 @@ void handle_input(Game *g) {
|
||||
}
|
||||
}
|
||||
|
||||
void capture_card_from_field(Game *g, Card *played, Card *target, Hand *hand, Hand *scored) {
|
||||
// capture all three cards if they play the fourth
|
||||
Card *same_month_card[3];
|
||||
int same_month_card_count = 0;
|
||||
for (int i = 0; i < g->field.count; i++) {
|
||||
Card *c = g->field.cards[i];
|
||||
if (c->month == played->month) {
|
||||
same_month_card[same_month_card_count++] = c;
|
||||
}
|
||||
}
|
||||
|
||||
remove_from_hand(hand, played);
|
||||
add_to_hand(scored, played);
|
||||
|
||||
if (same_month_card_count == 3) {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
remove_from_hand(&g->field, same_month_card[i]);
|
||||
add_to_hand(scored, same_month_card[i]);
|
||||
}
|
||||
} else {
|
||||
remove_from_hand(&g->field, target);
|
||||
add_to_hand(scored, target);
|
||||
}
|
||||
}
|
||||
|
||||
void run_frame_ai_playing(Game *g) {
|
||||
Hand *hand = ¤t_player(g)->hand;
|
||||
Hand *scored = ¤t_player(g)->scored;
|
||||
@ -212,22 +228,64 @@ void run_frame_ai_playing(Game *g) {
|
||||
play.played->visible = true;
|
||||
|
||||
if (play.target) {
|
||||
remove_from_hand(hand, play.played);
|
||||
add_to_hand(scored, play.played);
|
||||
remove_from_hand(&g->field, play.target);
|
||||
add_to_hand(scored, play.target);
|
||||
capture_card_from_field(g, play.played, play.target, hand, scored);
|
||||
} else {
|
||||
remove_from_hand(hand, play.played);
|
||||
add_to_hand(&g->field, play.played);
|
||||
}
|
||||
}
|
||||
|
||||
void run_frame_dealing(Game *g) {
|
||||
// TODO maybe we only need these once per game
|
||||
void run_frame_initializing(Game *g) {
|
||||
// TODO: choose the dealer in a more effective manner
|
||||
g->turn_number = -1;
|
||||
|
||||
g->player.hand.count = 0;
|
||||
g->right.hand.count = 0;
|
||||
g->left.hand.count = 0;
|
||||
g->field.count = 0;
|
||||
g->player.scored.count = 0;
|
||||
g->right.scored.count = 0;
|
||||
g->left.scored.count = 0;
|
||||
g->player.dekiyaku_score = 0;
|
||||
g->left.dekiyaku_score = 0;
|
||||
g->right.dekiyaku_score = 0;
|
||||
|
||||
g->player.dekiyaku_action = DEKIYAKU_ACTION_NONE;
|
||||
g->right.dekiyaku_action = DEKIYAKU_ACTION_NONE;
|
||||
g->left.dekiyaku_action = DEKIYAKU_ACTION_NONE;
|
||||
|
||||
g->current_play_from_hand = NULL;
|
||||
g->current_play_target = NULL;
|
||||
|
||||
g->deck.count = 0;
|
||||
for (int i = 0; i < 48; i++) {
|
||||
Card *c = &g->cards[i];
|
||||
c->visible = false;
|
||||
add_to_hand(&g->deck, c);
|
||||
}
|
||||
|
||||
shuffle_hand(&g->deck);
|
||||
|
||||
kan_points_string(g, g->player.points, g->player.points_string);
|
||||
kan_points_string(g, g->right.points, g->right.points_string);
|
||||
kan_points_string(g, g->left.points, g->left.points_string);
|
||||
g->state = GAME_STATE_DEALING;
|
||||
}
|
||||
|
||||
bool misdeal(Game *g) {
|
||||
int month_count[12] = { 0,0,0,0,0,0,0,0,0,0,0,0 };
|
||||
for (int i = 0; i < g->field.count; i++) {
|
||||
Card *c = g->field.cards[i];
|
||||
month_count[c->month]++;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 12; i++)
|
||||
if (month_count[i] >= 4) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void run_frame_dealing(Game *g) {
|
||||
if (g->player.hand.count < 4) {
|
||||
deal(&g->deck, &g->player.hand, 4, true);
|
||||
} else if (g->left.hand.count < 4) {
|
||||
@ -245,7 +303,12 @@ void run_frame_dealing(Game *g) {
|
||||
} else if (g->field.count < 6) {
|
||||
deal(&g->deck, &g->field, 3, true);
|
||||
} else {
|
||||
g->state = GAME_STATE_CALCULATING_FIELD_MULTIPLIER;
|
||||
if (misdeal(g)) {
|
||||
printf("misdeal\n");
|
||||
g->state = GAME_STATE_INITIALIZING;
|
||||
} else {
|
||||
g->state = GAME_STATE_CALCULATING_FIELD_MULTIPLIER;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -271,21 +334,11 @@ void run_frame_start_of_turn(Game *g) {
|
||||
}
|
||||
|
||||
void run_frame_checking_for_cancel(Game *g) {
|
||||
if (g->dialog) return;
|
||||
if (is_player_turn(g)) { g->dialog = cancel_dialog(); return; }
|
||||
|
||||
if (current_player(g)->dekiyaku_action == DEKIYAKU_ACTION_SAGE) {
|
||||
if (is_player_turn(g)) {
|
||||
// check for player canceling
|
||||
// if they do:
|
||||
// g->state = GAME_STATE_CALCULATING_DEKIYAKU_SCORE;
|
||||
// else
|
||||
g->state = GAME_STATE_CHOOSING_FROM_HAND;
|
||||
g->dialog = cancel_dialog();
|
||||
} else {
|
||||
// AI decides whether to cancel or not
|
||||
// if they do:
|
||||
// g->state = GAME_STATE_CALCULATING_DEKIYAKU_SCORE;
|
||||
// else
|
||||
// TODO: the AI might want to cancel at some point
|
||||
g->state = GAME_STATE_CHOOSING_FROM_HAND;
|
||||
}
|
||||
} else {
|
||||
@ -333,10 +386,16 @@ void run_frame_choosing_target(Game *g) {
|
||||
if (g->current_play_from_hand) {
|
||||
if (g->current_play_target) {
|
||||
g->current_play_from_hand->selected = false;
|
||||
remove_from_hand(&g->player.hand, g->current_play_from_hand);
|
||||
add_to_hand(&g->player.scored, g->current_play_from_hand);
|
||||
remove_from_hand(&g->field, g->current_play_target);
|
||||
add_to_hand(&g->player.scored, g->current_play_target);
|
||||
|
||||
capture_card_from_field(
|
||||
g,
|
||||
g->current_play_from_hand,
|
||||
g->current_play_target,
|
||||
&g->player.hand,
|
||||
&g->player.scored
|
||||
);
|
||||
|
||||
|
||||
g->current_play_from_hand = NULL;
|
||||
g->current_play_target = NULL;
|
||||
} else {
|
||||
@ -356,10 +415,7 @@ void run_frame_playing_from_deck(Game *g) {
|
||||
if (top_card->visible) {
|
||||
Card *target = valid_target(top_card, &g->field);
|
||||
if (target) {
|
||||
remove_from_hand(&g->field, target);
|
||||
add_to_hand(to_hand, target);
|
||||
remove_from_hand(&g->deck, top_card);
|
||||
add_to_hand(to_hand, top_card);
|
||||
capture_card_from_field(g, top_card, target, &g->deck, to_hand);
|
||||
} else {
|
||||
remove_from_hand(&g->deck, top_card);
|
||||
add_to_hand(&g->field, top_card);
|
||||
@ -380,8 +436,13 @@ void run_frame_checking_for_new_dekiyaku(Game *g) {
|
||||
int new_score = dekiyaku_score(&cp->dekiyaku);
|
||||
if (new_score != cp->dekiyaku_score) {
|
||||
cp->dekiyaku_score = new_score;
|
||||
cp->dekiyaku_action = DEKIYAKU_ACTION_NONE;
|
||||
g->state = GAME_STATE_SELECTING_DEKIYAKU_ACTION;
|
||||
if (is_player_turn(g)) {
|
||||
g->dialog = shoubu_dialog();
|
||||
} else {
|
||||
// TODO: better AI
|
||||
cp->dekiyaku_action = DEKIYAKU_ACTION_SHOUBU;
|
||||
g->state = GAME_STATE_CALCULATING_DEKIYAKU_SCORE;
|
||||
}
|
||||
} else {
|
||||
g->state = GAME_STATE_START_OF_TURN;
|
||||
}
|
||||
@ -392,8 +453,7 @@ void run_frame_selecting_dekiyaku_action(Game *g) {
|
||||
if (g->player.dekiyaku_action != DEKIYAKU_ACTION_NONE) {
|
||||
g->state = GAME_STATE_CALCULATING_DEKIYAKU_SCORE;
|
||||
} else {
|
||||
printf("Hey you can't choose a dekiyaku action yet, sorry\n");
|
||||
g->player.dekiyaku_action = DEKIYAKU_ACTION_SAGE;
|
||||
g->dialog = shoubu_dialog();
|
||||
}
|
||||
} else {
|
||||
// TODO: better AI
|
||||
@ -438,23 +498,35 @@ void run_frame_calculating_scores(Game *g) {
|
||||
}
|
||||
|
||||
void run_frame_calculating_dekiyaku_score(Game *g) {
|
||||
printf("Somebody won with dekiyaku. Cool.\n");
|
||||
printf("Somebody won with dekiyaku. Cool.\n"); fflush(stdout);
|
||||
g->state = GAME_STATE_INITIALIZING;
|
||||
}
|
||||
|
||||
void move_cards(Game *g) {
|
||||
float delta = GetFrameTime();
|
||||
for (int i = 0; i < 48; i++) {
|
||||
move_position(&g->cards[i].move, delta);
|
||||
}
|
||||
}
|
||||
|
||||
bool done_moving(Game *g) {
|
||||
for (int i = 0; i < 48; i++) {
|
||||
if (!card_done_moving(&g->cards[i])) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void run_frame(Game *g) {
|
||||
handle_input(g);
|
||||
if (g->dialog) return;
|
||||
|
||||
float delta = GetFrameTime();
|
||||
bool done_moving = true;
|
||||
for (int i = 0; i < 48; i++) {
|
||||
move_position(&g->cards[i].move, delta);
|
||||
if (!card_done_moving(&g->cards[i])) done_moving = false;
|
||||
}
|
||||
if (!done_moving) return;
|
||||
move_cards(g);
|
||||
if (!done_moving(g)) return;
|
||||
|
||||
switch (g->state) {
|
||||
case GAME_STATE_INITIALIZING:
|
||||
run_frame_initializing(g);
|
||||
return;
|
||||
case GAME_STATE_DEALING:
|
||||
run_frame_dealing(g);
|
||||
@ -503,6 +575,7 @@ void draw_frame(Game *g) {
|
||||
}
|
||||
|
||||
if (g->field_multiplier) DrawText(g->field_multiplier->name, 60, 385, 40, BLACK);
|
||||
|
||||
if (g->player.teyaku.calculated) {
|
||||
char s[200];
|
||||
teyaku_to_string(&g->player.teyaku, s);
|
||||
|
Loading…
Reference in New Issue
Block a user