diff --git a/game.c b/game.c index 5966b34..32f1484 100644 --- a/game.c +++ b/game.c @@ -22,9 +22,13 @@ void initialize_game(Game *g) { 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 = 0; for (int i = 0; i < 48; i++) { CardType t = CHAFF; @@ -66,6 +70,7 @@ void initialize_game(Game *g) { g->cards[i].move.position = &g->cards[i].position; 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++; } @@ -109,10 +114,27 @@ void initialize_game(Game *g) { g->state = GAME_STATE_DEALING; } +Player *current_player(Game *g) { + switch (g->turn_number % 3) { + case 0: + return &g->player; + case 1: + return &g->right; + case 2: + return &g->left; + } +} + +bool is_player_turn(Game *g) { + return current_player(g) == &g->player; +} + bool stale_calculation = true; void handle_input(Game *g) { + if (!is_player_turn(g)) return; + switch (g->state) { - case GAME_STATE_PLAYER_CHOOSING_FROM_HAND: + case GAME_STATE_CHOOSING_FROM_HAND: if (IsMouseButtonPressed(0)) { mouse_pos = GetMousePosition(); for (int i = 0; i < g->player.hand.count; i++) { @@ -126,7 +148,7 @@ void handle_input(Game *g) { } } break; - case GAME_STATE_PLAYER_CHOOSING_TARGET: + case GAME_STATE_CHOOSING_TARGET: if (IsMouseButtonPressed(0)) { mouse_pos = GetMousePosition(); for (int i = 0; i < g->player.hand.count; i++) { @@ -178,31 +200,10 @@ void handle_input(Game *g) { } } -bool run_frame_from_deck(Game *g, Hand *to_hand) { - Card *top_card = g->deck.cards[g->deck.count - 1]; - 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); - } else { - remove_from_hand(&g->deck, top_card); - add_to_hand(&g->field, top_card); - } - return true; - } else { - remove_from_hand(&g->deck, top_card); - add_to_hand(&g->deck, top_card); - top_card->visible = true; - top_card->move.end_time = 0.3; - top_card->move.destination.x = top_card->move.destination.x + 100; - return false; - } -} +void run_frame_ai_playing(Game *g) { + Hand *hand = ¤t_player(g)->hand; + Hand *scored = ¤t_player(g)->scored; -void run_frame_ai_playing(Game *g, Hand *hand, Hand *scored) { Play play = ai_play(hand, &g->field); play.played->visible = true; @@ -251,22 +252,64 @@ void run_frame_calculating_field_multiplier(Game *g) { void run_frame_calculating_teyaku(Game *g) { calculate_teyaku(g->player.hand, &g->player.teyaku); - for (int i = 0; i < 48; i++) { - g->cards[i].selected = false; + calculate_teyaku(g->right.hand, &g->right.teyaku); + calculate_teyaku(g->left.hand, &g->left.teyaku); + g->state = GAME_STATE_START_OF_TURN; +} + +void run_frame_start_of_turn(Game *g) { + g->turn_number++; + if(g->player.hand.count == 0 && g->right.hand.count == 0 && g->left.hand.count == 0) { + g->state = GAME_STATE_CALCULATING_SCORES; + } else { + g->state = GAME_STATE_CHECKING_FOR_CANCEL; + } +} + +void run_frame_checking_for_cancel(Game *g) { + 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; + } else { + // AI decides whether to cancel or not + // if they do: + // g->state = GAME_STATE_CALCULATING_DEKIYAKU_SCORE; + // else + g->state = GAME_STATE_CHOOSING_FROM_HAND; + } + } else { + g->state = GAME_STATE_CHOOSING_FROM_HAND; } - g->state = GAME_STATE_PLAYER_CHOOSING_FROM_HAND; } void run_frame_player_choosing_from_hand(Game *g) { for (int i = 0; i < g->player.hand.count; i++) { if (g->player.hand.cards[i]->selected) { - g->state = GAME_STATE_PLAYER_CHOOSING_TARGET; + g->state = GAME_STATE_CHOOSING_TARGET; return; } } } -void run_frame_player_choosing_target(Game *g) { +void run_frame_choosing_from_hand(Game *g) { + if (is_player_turn(g)) { + run_frame_player_choosing_from_hand(g); + } else { + run_frame_ai_playing(g); + g->state = GAME_STATE_PLAYING_FROM_DECK; + } +} + +void run_frame_choosing_target(Game *g) { + if (!is_player_turn(g)) { + printf("An AI player is choosing a target. That ain't right\n"); + return; + } + bool no_cards_selected = true; for (int i = 0; i < g->player.hand.count; i++) { if (g->player.hand.cards[i]->selected) { @@ -276,7 +319,7 @@ void run_frame_player_choosing_target(Game *g) { } if (no_cards_selected) { - g->state = GAME_STATE_PLAYER_CHOOSING_FROM_HAND; + g->state = GAME_STATE_CHOOSING_FROM_HAND; return; } @@ -295,57 +338,63 @@ void run_frame_player_choosing_target(Game *g) { add_to_hand(&g->field, g->current_play_from_hand); g->current_play_from_hand = NULL; } - g->state = GAME_STATE_PLAYER_FROM_DECK; + g->state = GAME_STATE_PLAYING_FROM_DECK; } } -void run_frame_player_from_deck(Game *g) { - if (run_frame_from_deck(g, &g->player.scored)) { - calculate_dekiyaku(&g->player.scored, &g->player.dekiyaku); - if (dekiyaku_score(&g->player.dekiyaku) != g->player.dekiyaku_score) { - g->player.dekiyaku_score = dekiyaku_score(&g->player.dekiyaku); - g->state = GAME_STATE_PLAYER_HAS_DEKIYAKU; +void run_frame_playing_from_deck(Game *g) { + Hand *to_hand = ¤t_player(g)->scored; + + Card *top_card = g->deck.cards[g->deck.count - 1]; + 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); } else { - g->state = GAME_STATE_RIGHT_PLAYING; + remove_from_hand(&g->deck, top_card); + add_to_hand(&g->field, top_card); } + g->state = GAME_STATE_CHECKING_FOR_NEW_DEKIYAKU; + } else { + remove_from_hand(&g->deck, top_card); + add_to_hand(&g->deck, top_card); + top_card->visible = true; + top_card->move.end_time = 0.3; + top_card->move.destination.x = top_card->move.destination.x + 100; } } -void run_frame_player_has_dekiyaku(Game *g) { - if (g->player.dekiyaku_action == DEKIYAKU_ACTION_SAGE) { - g->state = GAME_STATE_RIGHT_PLAYING; - } else if (g->player.dekiyaku_action == DEKIYAKU_ACTION_SHOUBU) { +void run_frame_checking_for_new_dekiyaku(Game *g) { + Player *cp = current_player(g); + calculate_dekiyaku(&cp->scored, &cp->dekiyaku); + 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; + } else { + g->state = GAME_STATE_START_OF_TURN; + } +} + +void run_frame_selecting_dekiyaku_action(Game *g) { + if (is_player_turn(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; + } + } else { + // TODO: better AI + current_player(g)->dekiyaku_action = DEKIYAKU_ACTION_SHOUBU; g->state = GAME_STATE_CALCULATING_DEKIYAKU_SCORE; } } -void run_frame_right_playing(Game *g) { - run_frame_ai_playing(g, &g->right.hand, &g->right.scored); - g->state = GAME_STATE_RIGHT_FROM_DECK; -} - -void run_frame_right_from_deck(Game *g) { - if (run_frame_from_deck(g, &g->right.scored)) { - calculate_dekiyaku(&g->right.scored, &g->right.dekiyaku); - g->state = GAME_STATE_LEFT_PLAYING; - } -} - -void run_frame_left_playing(Game *g) { - run_frame_ai_playing(g, &g->left.hand, &g->left.scored); - g->state = GAME_STATE_LEFT_FROM_DECK; -} - -void run_frame_left_from_deck(Game *g) { - if (run_frame_from_deck(g, &g->left.scored)) { - if (g->player.hand.count) { - g->state = GAME_STATE_PLAYER_CHOOSING_FROM_HAND; - } else { - g->state = GAME_STATE_CALCULATING_SCORES; - } - } -} - void run_frame_calculating_scores(Game *g) { printf("Hand scores: %d %d %d\n", hand_points(&g->player.scored), hand_points(&g->right.scored), hand_points(&g->left.scored)); @@ -381,6 +430,11 @@ void run_frame_calculating_scores(Game *g) { g->state = GAME_STATE_INITIALIZING; } +void run_frame_calculating_dekiyaku_score(Game *g) { + printf("Somebody won with dekiyaku. Cool.\n"); + g->state = GAME_STATE_INITIALIZING; +} + void run_frame(Game *g) { handle_input(g); @@ -404,30 +458,33 @@ void run_frame(Game *g) { case GAME_STATE_CALCULATING_TEYAKU: run_frame_calculating_teyaku(g); break; - case GAME_STATE_PLAYER_CHOOSING_FROM_HAND: - run_frame_player_choosing_from_hand(g); + case GAME_STATE_START_OF_TURN: + run_frame_start_of_turn(g); break; - case GAME_STATE_PLAYER_CHOOSING_TARGET: - run_frame_player_choosing_target(g); + case GAME_STATE_CHECKING_FOR_CANCEL: + run_frame_checking_for_cancel(g); break; - case GAME_STATE_PLAYER_FROM_DECK: - run_frame_player_from_deck(g); + case GAME_STATE_CHOOSING_FROM_HAND: + run_frame_choosing_from_hand(g); break; - case GAME_STATE_RIGHT_PLAYING: - run_frame_right_playing(g); + case GAME_STATE_CHOOSING_TARGET: + run_frame_choosing_target(g); break; - case GAME_STATE_RIGHT_FROM_DECK: - run_frame_right_from_deck(g); + case GAME_STATE_PLAYING_FROM_DECK: + run_frame_playing_from_deck(g); break; - case GAME_STATE_LEFT_PLAYING: - run_frame_left_playing(g); + case GAME_STATE_CHECKING_FOR_NEW_DEKIYAKU: + run_frame_checking_for_new_dekiyaku(g); break; - case GAME_STATE_LEFT_FROM_DECK: - run_frame_left_from_deck(g); + case GAME_STATE_SELECTING_DEKIYAKU_ACTION: + run_frame_selecting_dekiyaku_action(g); break; case GAME_STATE_CALCULATING_SCORES: run_frame_calculating_scores(g); break; + case GAME_STATE_CALCULATING_DEKIYAKU_SCORE: + run_frame_calculating_dekiyaku_score(g); + break; } } @@ -449,16 +506,18 @@ void draw_frame(Game *g) { DrawText(g->right.points_string, 40, 750, 20, BLACK); DrawText(g->left.points_string, 40, 800, 20, BLACK); - switch (g->state) { - case GAME_STATE_PLAYER_CHOOSING_FROM_HAND: - DrawText("Choose a card to play", 60, 485, 20, BLACK); - break; - case GAME_STATE_PLAYER_CHOOSING_TARGET: - DrawText("Choose a target on the field", 60, 485, 20, BLACK); - DrawRectangleRec(next_card_position(&g->field), BLUE); - break; - default: - break; + if (is_player_turn(g)) { + switch (g->state) { + case GAME_STATE_CHOOSING_FROM_HAND: + DrawText("Choose a card to play", 60, 485, 20, BLACK); + break; + case GAME_STATE_CHOOSING_TARGET: + DrawText("Choose a target on the field", 60, 485, 20, BLACK); + DrawRectangleRec(next_card_position(&g->field), BLUE); + break; + default: + break; + } } EndDrawing(); diff --git a/game.h b/game.h index f3cf1f2..8da0a0d 100644 --- a/game.h +++ b/game.h @@ -17,14 +17,13 @@ typedef enum GameState { GAME_STATE_DEALING, GAME_STATE_CALCULATING_FIELD_MULTIPLIER, GAME_STATE_CALCULATING_TEYAKU, - GAME_STATE_PLAYER_CHOOSING_FROM_HAND, - GAME_STATE_PLAYER_CHOOSING_TARGET, - GAME_STATE_PLAYER_FROM_DECK, - GAME_STATE_PLAYER_HAS_DEKIYAKU, - GAME_STATE_RIGHT_PLAYING, - GAME_STATE_RIGHT_FROM_DECK, - GAME_STATE_LEFT_PLAYING, - GAME_STATE_LEFT_FROM_DECK, + GAME_STATE_START_OF_TURN, + GAME_STATE_CHECKING_FOR_CANCEL, + GAME_STATE_CHOOSING_FROM_HAND, + GAME_STATE_CHOOSING_TARGET, + GAME_STATE_PLAYING_FROM_DECK, + GAME_STATE_CHECKING_FOR_NEW_DEKIYAKU, + GAME_STATE_SELECTING_DEKIYAKU_ACTION, GAME_STATE_CALCULATING_SCORES, GAME_STATE_CALCULATING_DEKIYAKU_SCORE, } GameState; @@ -40,6 +39,7 @@ struct Game { int kan_value; Player player, right, left; int temp_points; + int turn_number; }; void initialize_game(Game *g);