Compare commits

..

No commits in common. "7d6a0291b7c68f766cc74335dce1ea1134bccf01" and "5ad8fa1534676ba1b8ce3776a5065be25e45696c" have entirely different histories.

7 changed files with 62 additions and 308 deletions

28
card.c
View File

@ -44,34 +44,6 @@ void shuffle_hand(Hand *h) {
} }
} }
void order_deck(Hand *h) {
Card *swap;
swap = h->cards[1];
h->cards[1] = h->cards[47-0];
h->cards[47-0] = swap;
swap = h->cards[5];
h->cards[5] = h->cards[47-1];
h->cards[47-1] = swap;
swap = h->cards[9];
h->cards[9] = h->cards[47-2];
h->cards[47-2] = swap;
swap = h->cards[0];
h->cards[0] = h->cards[47-12];
h->cards[47-12] = swap;
swap = h->cards[4];
h->cards[4] = h->cards[47-13];
h->cards[47-13] = swap;
swap = h->cards[8];
h->cards[8] = h->cards[47-14];
h->cards[47-14] = swap;
}
void remove_from_hand(Hand *h, Card *c) { void remove_from_hand(Hand *h, Card *c) {
bool card_found = false; bool card_found = false;
for (int i = 0; i < h->count - 1; i++) { for (int i = 0; i < h->count - 1; i++) {

View File

@ -1,5 +1,4 @@
#include <stddef.h> #include <stddef.h>
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -7,7 +6,7 @@
#include "dialog.h" #include "dialog.h"
Dialog dialogs[6]; Dialog dialogs[2];
void handle_click_cancel_yes(Game *g) { void handle_click_cancel_yes(Game *g) {
g->player.dekiyaku_action = DEKIYAKU_ACTION_CANCEL; g->player.dekiyaku_action = DEKIYAKU_ACTION_CANCEL;
@ -25,23 +24,13 @@ void handle_click_shoubu(Game *g) {
void handle_click_sage(Game *g) { void handle_click_sage(Game *g) {
g->player.dekiyaku_action = DEKIYAKU_ACTION_SAGE; g->player.dekiyaku_action = DEKIYAKU_ACTION_SAGE;
g->turn_number++;
g->state = GAME_STATE_CHOOSING_FROM_HAND; g->state = GAME_STATE_CHOOSING_FROM_HAND;
} }
void handle_click_ok_end_of_round(Game *g) {
g->state = GAME_STATE_END_OF_ROUND;
}
void handle_click_ok_end_of_game(Game *g) {
g->state = GAME_STATE_TITLE_SCREEN;
}
void init_dialogs(Game *g) { void init_dialogs(Game *g) {
Dialog *cancel_dialog = &dialogs[0]; Dialog *cancel_dialog = &dialogs[0];
cancel_dialog->text_count = 1; cancel_dialog->text = malloc(200);
cancel_dialog->text[0] = malloc(200); strcpy(cancel_dialog->text, "Would you like to cancel?");
strcpy(cancel_dialog->text[0], "Would you like to cancel?");
cancel_dialog->text_color = BLACK; cancel_dialog->text_color = BLACK;
cancel_dialog->options_count = 2; cancel_dialog->options_count = 2;
cancel_dialog->game = g; cancel_dialog->game = g;
@ -56,10 +45,10 @@ void init_dialogs(Game *g) {
cancel_dialog->options[1].color = RED; cancel_dialog->options[1].color = RED;
cancel_dialog->options[1].handle = &handle_click_cancel_no; cancel_dialog->options[1].handle = &handle_click_cancel_no;
Dialog *shoubu_dialog = &dialogs[1]; Dialog *shoubu_dialog = &dialogs[1];
shoubu_dialog->text_count = 1; shoubu_dialog->text = malloc(200);
shoubu_dialog->text[0] = malloc(200); strcpy(shoubu_dialog->text, "You have dekiyaku! Sage or shoubu?");
strcpy(shoubu_dialog->text[0], "You have dekiyaku! Sage or shoubu?");
shoubu_dialog->text_color = BLACK; shoubu_dialog->text_color = BLACK;
shoubu_dialog->options_count = 2; shoubu_dialog->options_count = 2;
shoubu_dialog->game = g; shoubu_dialog->game = g;
@ -67,48 +56,16 @@ void init_dialogs(Game *g) {
shoubu_dialog->options[0].text = malloc(50); shoubu_dialog->options[0].text = malloc(50);
strcpy(shoubu_dialog->options[0].text, "Sage"); strcpy(shoubu_dialog->options[0].text, "Sage");
shoubu_dialog->options[0].color = GREEN; shoubu_dialog->options[0].color = GREEN;
shoubu_dialog->options[0].handle = &handle_click_sage; shoubu_dialog->options[0].handle = NULL;
shoubu_dialog->options[1].text = malloc(50); shoubu_dialog->options[1].text = malloc(50);
strcpy(shoubu_dialog->options[1].text, "Shoubu"); strcpy(shoubu_dialog->options[1].text, "Shoubu");
shoubu_dialog->options[1].color = RED; shoubu_dialog->options[1].color = RED;
shoubu_dialog->options[1].handle = &handle_click_shoubu; shoubu_dialog->options[1].handle = NULL;
Dialog *no_dekiyaku_end_of_round_dialog = &dialogs[2];
no_dekiyaku_end_of_round_dialog->text_count = 3;
no_dekiyaku_end_of_round_dialog->text[0] = malloc(200);
no_dekiyaku_end_of_round_dialog->text[1] = malloc(200);
no_dekiyaku_end_of_round_dialog->text[2] = malloc(200);
strcpy(no_dekiyaku_end_of_round_dialog->text[0], "Player score");
strcpy(no_dekiyaku_end_of_round_dialog->text[1], "Right score");
strcpy(no_dekiyaku_end_of_round_dialog->text[2], "Left score");
no_dekiyaku_end_of_round_dialog->text_color = BLACK;
no_dekiyaku_end_of_round_dialog->options_count = 1;
no_dekiyaku_end_of_round_dialog->game = g;
no_dekiyaku_end_of_round_dialog->options[0].text = malloc(50);
strcpy(no_dekiyaku_end_of_round_dialog->options[0].text, "Okay");
no_dekiyaku_end_of_round_dialog->options[0].color = GREEN;
no_dekiyaku_end_of_round_dialog->options[0].handle = &handle_click_ok_end_of_round;
Dialog *end_of_game_dialog = &dialogs[3];
end_of_game_dialog->text_count = 3;
end_of_game_dialog->text[0] = malloc(200);
strcpy(end_of_game_dialog->text[0], "Game over something");
end_of_game_dialog->text_color = BLACK;
end_of_game_dialog->options_count = 1;
end_of_game_dialog->game = g;
end_of_game_dialog->options[0].text = malloc(50);
strcpy(end_of_game_dialog->options[0].text, "Okay");
end_of_game_dialog->options[0].color = GREEN;
end_of_game_dialog->options[0].handle = &handle_click_ok_end_of_game;
} }
void cancel_dialog(Game *g) { g->dialog = &dialogs[0]; } Dialog *cancel_dialog() { return &dialogs[0]; }
void shoubu_dialog(Game *g) { g->dialog = &dialogs[1]; } Dialog *shoubu_dialog() { return &dialogs[1]; }
void no_dekiyaku_end_of_round_dialog(Game *g) { g->dialog = &dialogs[2]; }
void end_of_game_dialog(Game *g) { g->dialog = &dialogs[3]; }
Rectangle dialog_option_outer_rectangle(Dialog *d, int i) { Rectangle dialog_option_outer_rectangle(Dialog *d, int i) {
return (Rectangle) { return (Rectangle) {
@ -133,11 +90,8 @@ void dialog_draw(Dialog *d) {
int text_width; int text_width;
DrawRectangleRec(DIALOG_OUTER_RECTANGLE, BLACK); DrawRectangleRec(DIALOG_OUTER_RECTANGLE, BLACK);
DrawRectangleRec(DIALOG_INNER_RECTANGLE, WHITE); DrawRectangleRec(DIALOG_INNER_RECTANGLE, WHITE);
text_width = MeasureText(d->text, DIALOG_TEXT_FONT_SIZE);
for (int i = 0; i < d->text_count; i++) { DrawText(d->text, 700 - (text_width / 2), 400, DIALOG_TEXT_FONT_SIZE, d->text_color);
text_width = MeasureText(d->text[i], DIALOG_TEXT_FONT_SIZE);
DrawText(d->text[i], 700 - (text_width / 2), 300 + (70 * (i - 1)), DIALOG_TEXT_FONT_SIZE, d->text_color);
}
for (int i = 0; i < d->options_count; i++) { for (int i = 0; i < d->options_count; i++) {
DialogOption *o = &d->options[i]; DialogOption *o = &d->options[i];

View File

@ -18,8 +18,7 @@ struct DialogOption {
}; };
struct Dialog { struct Dialog {
char *text[3]; char *text;
int text_count;
Color text_color; Color text_color;
DialogOption options[3]; DialogOption options[3];
int options_count; int options_count;
@ -27,10 +26,8 @@ struct Dialog {
}; };
void init_dialogs(Game *g); void init_dialogs(Game *g);
void cancel_dialog(Game *g); Dialog *cancel_dialog();
void shoubu_dialog(Game *g); Dialog *shoubu_dialog();
void no_dekiyaku_end_of_round_dialog(Game *g);
void end_of_game_dialog(Game *g);
void dialog_draw(Dialog *d); void dialog_draw(Dialog *d);
void dialog_handle_input(Dialog *d); void dialog_handle_input(Dialog *d);

243
game.c
View File

@ -72,32 +72,17 @@ void initialize_game(Game *g) {
g->cards[i].selected = false; g->cards[i].selected = false;
} }
g->player.points = 100 * g->kan_value; g->player.points = 10 * g->kan_value;
g->right.points = 100 * g->kan_value; g->right.points = 10 * g->kan_value;
g->left.points = 100 * g->kan_value; g->left.points = 10 * g->kan_value;
g->player.points_string[0] = '\0'; g->player.points_string[0] = '\0';
g->right.points_string[0] = '\0'; g->right.points_string[0] = '\0';
g->left.points_string[0] = '\0'; g->left.points_string[0] = '\0';
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.teyaku.calculated = false; g->player.teyaku.calculated = false;
g->right.teyaku.calculated = false; g->right.teyaku.calculated = false;
g->left.teyaku.calculated = false; g->left.teyaku.calculated = false;
g->player.seat = PLAYER;
g->right.seat = RIGHT;
g->left.seat = LEFT;
g->player.hand.position = (Vector2) { 300, 600 }; g->player.hand.position = (Vector2) { 300, 600 };
g->player.hand.display_type = HAND_DISPLAY_ROW; g->player.hand.display_type = HAND_DISPLAY_ROW;
g->right.hand.position = (Vector2) { 750, 125 }; g->right.hand.position = (Vector2) { 750, 125 };
@ -115,22 +100,6 @@ void initialize_game(Game *g) {
strcpy(teyaku_calculation, ""); strcpy(teyaku_calculation, "");
int dealer = rand() % 3;
switch (dealer) {
case PLAYER:
g->dealer = &g->player;
break;
case RIGHT:
g->dealer = &g->right;
break;
case LEFT:
g->dealer = &g->left;
break;
}
g->dealer = &g->player;
g->number_of_rounds = 3;
g->current_round = 0;
g->state = GAME_STATE_INITIALIZING; g->state = GAME_STATE_INITIALIZING;
} }
@ -156,12 +125,8 @@ void handle_input(Game *g) {
g->state = GAME_STATE_INITIALIZING; g->state = GAME_STATE_INITIALIZING;
return; return;
} }
if (g->dialog) {
return dialog_handle_input(g->dialog);
}
if (!is_player_turn(g)) return; if (!is_player_turn(g)) return;
if (g->dialog) return dialog_handle_input(g->dialog);
switch (g->state) { switch (g->state) {
case GAME_STATE_CHOOSING_FROM_HAND: case GAME_STATE_CHOOSING_FROM_HAND:
@ -225,23 +190,6 @@ void handle_input(Game *g) {
} }
} }
break; break;
case GAME_STATE_CHOOSING_TARGET_FROM_DECK:
if (IsMouseButtonPressed(0)) {
mouse_pos = GetMousePosition();
for (int i = 0; i < g->field.count; i++) {
if (point_within_card(g->field.cards[i], mouse_pos)) {
Card *selected_card = g->deck.cards[g->deck.count - 1];
if (valid_play(&g->field, selected_card, g->field.cards[i])) {
g->current_play_from_hand = selected_card;
g->current_play_target = g->field.cards[i];
} else {
printf("Invalid\n");
}
break;
}
}
}
break;
default: default:
break; break;
} }
@ -288,7 +236,8 @@ void run_frame_ai_playing(Game *g) {
} }
void run_frame_initializing(Game *g) { void run_frame_initializing(Game *g) {
g->turn_number = g->dealer->seat; // TODO: choose the dealer in a more effective manner
g->turn_number = -1;
g->player.hand.count = 0; g->player.hand.count = 0;
g->right.hand.count = 0; g->right.hand.count = 0;
@ -316,7 +265,6 @@ void run_frame_initializing(Game *g) {
} }
shuffle_hand(&g->deck); shuffle_hand(&g->deck);
// order_deck(&g->deck);
kan_points_string(g, g->player.points, g->player.points_string); 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->right.points, g->right.points_string);
@ -338,14 +286,20 @@ bool misdeal(Game *g) {
} }
void run_frame_dealing(Game *g) { void run_frame_dealing(Game *g) {
if (current_player(g)->hand.count < 4) { if (g->player.hand.count < 4) {
deal(&g->deck, &current_player(g)->hand, 4, is_player_turn(g)); deal(&g->deck, &g->player.hand, 4, true);
g->turn_number++; } else if (g->left.hand.count < 4) {
deal(&g->deck, &g->left.hand, 4, false);
} else if (g->right.hand.count < 4) {
deal(&g->deck, &g->right.hand, 4, false);
} else if (g->field.count < 3) { } else if (g->field.count < 3) {
deal(&g->deck, &g->field, 3, true); deal(&g->deck, &g->field, 3, true);
} else if (current_player(g)->hand.count < 7) { } else if (g->player.hand.count < 7) {
deal(&g->deck, &current_player(g)->hand, 3, is_player_turn(g)); deal(&g->deck, &g->player.hand, 3, true);
g->turn_number++; } else if (g->left.hand.count < 7) {
deal(&g->deck, &g->left.hand, 3, false);
} else if (g->right.hand.count < 7) {
deal(&g->deck, &g->right.hand, 3, false);
} else if (g->field.count < 6) { } else if (g->field.count < 6) {
deal(&g->deck, &g->field, 3, true); deal(&g->deck, &g->field, 3, true);
} else { } else {
@ -353,7 +307,6 @@ void run_frame_dealing(Game *g) {
printf("misdeal\n"); printf("misdeal\n");
g->state = GAME_STATE_INITIALIZING; g->state = GAME_STATE_INITIALIZING;
} else { } else {
g->turn_number++;
g->state = GAME_STATE_CALCULATING_FIELD_MULTIPLIER; g->state = GAME_STATE_CALCULATING_FIELD_MULTIPLIER;
} }
} }
@ -383,7 +336,7 @@ void run_frame_start_of_turn(Game *g) {
void run_frame_checking_for_cancel(Game *g) { void run_frame_checking_for_cancel(Game *g) {
if (current_player(g)->dekiyaku_action == DEKIYAKU_ACTION_SAGE) { if (current_player(g)->dekiyaku_action == DEKIYAKU_ACTION_SAGE) {
if (is_player_turn(g)) { if (is_player_turn(g)) {
cancel_dialog(g); g->dialog = cancel_dialog();
} else { } else {
// TODO: the AI might want to cancel at some point // TODO: the AI might want to cancel at some point
g->state = GAME_STATE_CHOOSING_FROM_HAND; g->state = GAME_STATE_CHOOSING_FROM_HAND;
@ -407,7 +360,7 @@ void run_frame_choosing_from_hand(Game *g) {
run_frame_player_choosing_from_hand(g); run_frame_player_choosing_from_hand(g);
} else { } else {
run_frame_ai_playing(g); run_frame_ai_playing(g);
g->state = GAME_STATE_SHOWING_CARD_FROM_DECK; g->state = GAME_STATE_PLAYING_FROM_DECK;
} }
} }
@ -451,58 +404,29 @@ void run_frame_choosing_target(Game *g) {
add_to_hand(&g->field, g->current_play_from_hand); add_to_hand(&g->field, g->current_play_from_hand);
g->current_play_from_hand = NULL; g->current_play_from_hand = NULL;
} }
g->state = GAME_STATE_SHOWING_CARD_FROM_DECK; g->state = GAME_STATE_PLAYING_FROM_DECK;
} }
} }
void run_frame_showing_card_from_deck(Game *g) {
Card *top_card = g->deck.cards[g->deck.count - 1];
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;
g->state = GAME_STATE_PLAYING_FROM_DECK;
}
void run_frame_playing_from_deck(Game *g) { void run_frame_playing_from_deck(Game *g) {
Hand *to_hand = &current_player(g)->scored; Hand *to_hand = &current_player(g)->scored;
Card *top_card = g->deck.cards[g->deck.count - 1]; Card *top_card = g->deck.cards[g->deck.count - 1];
Card *targets[4]; if (top_card->visible) {
int target_count = 0; Card *target = valid_target(top_card, &g->field);
valid_targets(top_card, &g->field, &targets[0], &target_count); if (target) {
capture_card_from_field(g, top_card, target, &g->deck, to_hand);
if (target_count == 1) { } else {
capture_card_from_field(g, top_card, targets[0], &g->deck, to_hand); remove_from_hand(&g->deck, top_card);
g->state = GAME_STATE_CHECKING_FOR_NEW_DEKIYAKU; add_to_hand(&g->field, top_card);
} else if(target_count == 0) {
remove_from_hand(&g->deck, top_card);
add_to_hand(&g->field, top_card);
g->state = GAME_STATE_CHECKING_FOR_NEW_DEKIYAKU;
} else {
g->state = GAME_STATE_CHOOSING_TARGET_FROM_DECK;
return;
}
}
void run_frame_choosing_target_from_deck(Game *g) {
Hand *to_hand = &current_player(g)->scored;
Card *top_card = g->deck.cards[g->deck.count - 1];
Card *targets[4];
int target_count = 0;
valid_targets(top_card, &g->field, &targets[0], &target_count);
if (is_player_turn(g)) {
if (g->current_play_target) {
capture_card_from_field(g, top_card, g->current_play_target, &g->deck, to_hand);
g->state = GAME_STATE_CHECKING_FOR_NEW_DEKIYAKU;
} }
} else {
// TODO: better AI
capture_card_from_field(g, top_card, targets[0], &g->deck, to_hand);
g->state = GAME_STATE_CHECKING_FOR_NEW_DEKIYAKU; 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;
} }
} }
@ -513,7 +437,7 @@ void run_frame_checking_for_new_dekiyaku(Game *g) {
if (new_score != cp->dekiyaku_score) { if (new_score != cp->dekiyaku_score) {
cp->dekiyaku_score = new_score; cp->dekiyaku_score = new_score;
if (is_player_turn(g)) { if (is_player_turn(g)) {
shoubu_dialog(g); g->dialog = shoubu_dialog();
} else { } else {
// TODO: better AI // TODO: better AI
cp->dekiyaku_action = DEKIYAKU_ACTION_SHOUBU; cp->dekiyaku_action = DEKIYAKU_ACTION_SHOUBU;
@ -529,7 +453,7 @@ void run_frame_selecting_dekiyaku_action(Game *g) {
if (g->player.dekiyaku_action != DEKIYAKU_ACTION_NONE) { if (g->player.dekiyaku_action != DEKIYAKU_ACTION_NONE) {
g->state = GAME_STATE_CALCULATING_DEKIYAKU_SCORE; g->state = GAME_STATE_CALCULATING_DEKIYAKU_SCORE;
} else { } else {
shoubu_dialog(g); g->dialog = shoubu_dialog();
} }
} else { } else {
// TODO: better AI // TODO: better AI
@ -539,63 +463,38 @@ void run_frame_selecting_dekiyaku_action(Game *g) {
} }
void run_frame_calculating_scores(Game *g) { void run_frame_calculating_scores(Game *g) {
no_dekiyaku_end_of_round_dialog(g); printf("Hand scores: %d %d %d\n", hand_points(&g->player.scored), hand_points(&g->right.scored), hand_points(&g->left.scored));
int hp[3];
hp[0] = hand_points(&g->player.scored);
hp[1] = hand_points(&g->right.scored);
hp[2] = hand_points(&g->left.scored);
SpecialCase special_case = calculate_special_case(g); SpecialCase special_case = calculate_special_case(g);
switch(special_case.type) { switch(special_case.type) {
case SPECIAL_CASE_ALL_EIGHTS: case SPECIAL_CASE_ALL_EIGHTS:
sprintf(g->dialog->text[0], "All eights!"); printf("All eights! Dealer gets %d kan\n", special_case.score);
sprintf(g->dialog->text[0], "Dealer gets %d kan", special_case.score);
transfer_kan(g, &g->dealer->points, &g->player.points, special_case.score);
transfer_kan(g, &g->dealer->points, &g->right.points, special_case.score);
transfer_kan(g, &g->dealer->points, &g->left.points, special_case.score);
break; break;
case SPECIAL_CASE_DOUBLE_EIGHTS: case SPECIAL_CASE_DOUBLE_EIGHTS:
case SPECIAL_CASE_SIXTEEN_CHAFF: case SPECIAL_CASE_SIXTEEN_CHAFF:
if (special_case.type == SPECIAL_CASE_DOUBLE_EIGHTS) sprintf(g->dialog->text[0], "Double eights!"); printf("Double eights or 16 chaff! Player %d gets %d kan\n", special_case.target, special_case.score);
else sprintf(g->dialog->text[0], "Sixteen chaff!");
sprintf(g->dialog->text[1], "Player %d gets %d kan\n", special_case.target, special_case.score);
switch (special_case.target) { switch (special_case.target) {
case SPECIAL_CASE_TARGET_PLAYER: case SPECIAL_CASE_TARGET_PLAYER:
transfer_kan(g, &g->player.points, &g->right.points, special_case.score); transfer_kan(g, &g->player.points, &g->right.points, special_case.score);
transfer_kan(g, &g->player.points, &g->left.points, special_case.score); transfer_kan(g, &g->player.points, &g->left.points, special_case.score);
g->dealer = &g->player;
break; break;
case SPECIAL_CASE_TARGET_RIGHT: case SPECIAL_CASE_TARGET_RIGHT:
transfer_kan(g, &g->right.points, &g->player.points, special_case.score); transfer_kan(g, &g->right.points, &g->player.points, special_case.score);
transfer_kan(g, &g->right.points, &g->left.points, special_case.score); transfer_kan(g, &g->right.points, &g->left.points, special_case.score);
g->dealer = &g->right;
break; break;
case SPECIAL_CASE_TARGET_LEFT: case SPECIAL_CASE_TARGET_LEFT:
transfer_kan(g, &g->left.points, &g->right.points, special_case.score); transfer_kan(g, &g->left.points, &g->right.points, special_case.score);
transfer_kan(g, &g->left.points, &g->player.points, special_case.score); transfer_kan(g, &g->left.points, &g->player.points, special_case.score);
g->dealer = &g->left;
break; break;
} }
break; break;
default: default:
sprintf(g->dialog->text[0], "Player score: %d", hp[0]); transfer_points(g, &g->player.points, &g->temp_points, hand_points(&g->player.scored));
sprintf(g->dialog->text[1], "Right score: %d", hp[1]); transfer_points(g, &g->right.points, &g->temp_points, hand_points(&g->right.scored));
sprintf(g->dialog->text[2], "Left score: %d", hp[2]); transfer_points(g, &g->left.points, &g->temp_points, hand_points(&g->left.scored));
transfer_points(g, &g->player.points, &g->temp_points, hp[0]);
transfer_points(g, &g->right.points, &g->temp_points, hp[1]);
transfer_points(g, &g->left.points, &g->temp_points, hp[2]);
if (hp[0] > hp[1]) {
if (hp[0] > hp[2]) g->dealer = &g->player;
else
if (hp[2] > hp[1]) g->dealer = &g->left;
else g->dealer = &g->right;
} else {
if (hp[1] > hp[2]) g->dealer = &g->right;
else g->dealer = &g->left;
}
break; break;
} }
g->state = GAME_STATE_INITIALIZING;
} }
void run_frame_calculating_dekiyaku_score(Game *g) { void run_frame_calculating_dekiyaku_score(Game *g) {
@ -603,19 +502,6 @@ void run_frame_calculating_dekiyaku_score(Game *g) {
g->state = GAME_STATE_INITIALIZING; g->state = GAME_STATE_INITIALIZING;
} }
void run_frame_end_of_round(Game *g) {
g->current_round++;
if (g->current_round >= g->number_of_rounds) {
g->state = GAME_STATE_END_OF_GAME;
} else {
g->state = GAME_STATE_INITIALIZING;
}
}
void run_frame_end_of_game(Game *g) {
end_of_game_dialog(g);
}
void move_cards(Game *g) { void move_cards(Game *g) {
float delta = GetFrameTime(); float delta = GetFrameTime();
for (int i = 0; i < 48; i++) { for (int i = 0; i < 48; i++) {
@ -663,15 +549,9 @@ void run_frame(Game *g) {
case GAME_STATE_CHOOSING_TARGET: case GAME_STATE_CHOOSING_TARGET:
run_frame_choosing_target(g); run_frame_choosing_target(g);
break; break;
case GAME_STATE_SHOWING_CARD_FROM_DECK:
run_frame_showing_card_from_deck(g);
break;
case GAME_STATE_PLAYING_FROM_DECK: case GAME_STATE_PLAYING_FROM_DECK:
run_frame_playing_from_deck(g); run_frame_playing_from_deck(g);
break; break;
case GAME_STATE_CHOOSING_TARGET_FROM_DECK:
run_frame_choosing_target_from_deck(g);
break;
case GAME_STATE_CHECKING_FOR_NEW_DEKIYAKU: case GAME_STATE_CHECKING_FOR_NEW_DEKIYAKU:
run_frame_checking_for_new_dekiyaku(g); run_frame_checking_for_new_dekiyaku(g);
break; break;
@ -684,46 +564,17 @@ void run_frame(Game *g) {
case GAME_STATE_CALCULATING_DEKIYAKU_SCORE: case GAME_STATE_CALCULATING_DEKIYAKU_SCORE:
run_frame_calculating_dekiyaku_score(g); run_frame_calculating_dekiyaku_score(g);
break; break;
case GAME_STATE_END_OF_ROUND:
run_frame_end_of_round(g);
break;
case GAME_STATE_END_OF_GAME:
run_frame_end_of_game(g);
break;
}
}
void draw_player_cards(Game *g, Player *p) {
for (int i = 0; i < p->hand.count; i++) {
draw_card(p->hand.cards[i], &g->cards_texture);
}
for (int i = 0; i < p->scored.count; i++) {
draw_card(p->scored.cards[i], &g->cards_texture);
}
}
void draw_cards(Game *g) {
draw_player_cards(g, &g->player);
draw_player_cards(g, &g->right);
draw_player_cards(g, &g->left);
for (int i = 0; i < g->field.count; i++) {
draw_card(g->field.cards[i], &g->cards_texture);
}
for (int i = 0; i < g->deck.count; i++) {
draw_card(g->deck.cards[i], &g->cards_texture);
} }
} }
void draw_frame(Game *g) { void draw_frame(Game *g) {
BeginDrawing(); BeginDrawing();
ClearBackground(RAYWHITE); ClearBackground(RAYWHITE);
for (int i = 0; i < 48; i++) {
draw_card(&g->cards[i], &g->cards_texture);
}
draw_cards(g); if (g->field_multiplier) DrawText(g->field_multiplier->name, 60, 385, 40, BLACK);
if (g->state == GAME_STATE_DEALING) DrawText("Dealing....", 60, 385, 40, BLACK);
else if (g->field_multiplier) DrawText(g->field_multiplier->name, 60, 385, 40, BLACK);
if (g->player.teyaku.calculated) { if (g->player.teyaku.calculated) {
char s[200]; char s[200];

8
game.h
View File

@ -22,16 +22,11 @@ typedef enum GameState {
GAME_STATE_CHECKING_FOR_CANCEL, GAME_STATE_CHECKING_FOR_CANCEL,
GAME_STATE_CHOOSING_FROM_HAND, GAME_STATE_CHOOSING_FROM_HAND,
GAME_STATE_CHOOSING_TARGET, GAME_STATE_CHOOSING_TARGET,
GAME_STATE_SHOWING_CARD_FROM_DECK,
GAME_STATE_PLAYING_FROM_DECK, GAME_STATE_PLAYING_FROM_DECK,
GAME_STATE_CHOOSING_TARGET_FROM_DECK,
GAME_STATE_CHECKING_FOR_NEW_DEKIYAKU, GAME_STATE_CHECKING_FOR_NEW_DEKIYAKU,
GAME_STATE_SELECTING_DEKIYAKU_ACTION, GAME_STATE_SELECTING_DEKIYAKU_ACTION,
GAME_STATE_CALCULATING_SCORES, GAME_STATE_CALCULATING_SCORES,
GAME_STATE_CALCULATING_DEKIYAKU_SCORE, GAME_STATE_CALCULATING_DEKIYAKU_SCORE,
GAME_STATE_END_OF_ROUND,
GAME_STATE_END_OF_GAME,
GAME_STATE_TITLE_SCREEN,
} GameState; } GameState;
struct Game { struct Game {
@ -47,9 +42,6 @@ struct Game {
int temp_points; int temp_points;
int turn_number; int turn_number;
Dialog *dialog; Dialog *dialog;
Player *dealer;
int number_of_rounds;
int current_round;
}; };
void initialize_game(Game *g); void initialize_game(Game *g);

11
play.c
View File

@ -1,5 +1,4 @@
#include <stddef.h> #include <stddef.h>
#include <stdio.h>
#include <stdbool.h> #include <stdbool.h>
#include "play.h" #include "play.h"
@ -26,16 +25,6 @@ bool valid_play(Hand *field, Card *played, Card *target) {
} }
} }
void valid_targets(Card *active, Hand *field, Card **targets, int *target_count) {
*target_count = 0;
for (int i = 0; i < field->count; i++) {
if (field->cards[i]->month == active->month) {
targets[(*target_count)++] = field->cards[i];
}
}
targets[*target_count] = NULL; // Sentinel
}
Card *valid_target(Card *active, Hand *field) { Card *valid_target(Card *active, Hand *field) {
for (int i = 0; i < field->count; i++) { for (int i = 0; i < field->count; i++) {
if (field->cards[i]->month == active->month) { if (field->cards[i]->month == active->month) {

1
play.h
View File

@ -13,7 +13,6 @@ struct Play {
}; };
bool valid_play(Hand *field, Card *played, Card *target); bool valid_play(Hand *field, Card *played, Card *target);
void valid_targets(Card *active, Hand *field, Card **targets, int *target_count);
Card *valid_target(Card *active, Hand *field); Card *valid_target(Card *active, Hand *field);
Play ai_play(Hand *hand, Hand *field); Play ai_play(Hand *hand, Hand *field);