game.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  1. #include "game.h"
  2. #include "wave/data_structures/queue.h"
  3. #include "wave/data_structures/list.h"
  4. #include "wave/exception_manager.h"
  5. #include <gui/gui.h>
  6. #include <stdlib.h>
  7. #include <math.h>
  8. Card AllCardsData[NUMBER_OF_CARDS];
  9. const int CARD_NONE = -1;
  10. struct GameState {
  11. int cardLocation[NUMBER_OF_CARDS]; // 0 = deck, -1 = discard, 1+ = player index
  12. int playerTurn;
  13. int direction;
  14. int topCard;
  15. CardSuit forcedSuit;
  16. int cardToPlay;
  17. CardSuit forcedSuitToPlay;
  18. int winner;
  19. Queue* shuffleQueue;
  20. };
  21. void fill_shuffle_queue(GameState* state) {
  22. int array[NUMBER_OF_CARDS];
  23. for(int i = 0; i < NUMBER_OF_CARDS; i++) array[i] = i;
  24. for(int i = 0; i < NUMBER_OF_CARDS; i++) {
  25. int j = rand() % NUMBER_OF_CARDS;
  26. int temp = array[i];
  27. array[i] = array[j];
  28. array[j] = temp;
  29. }
  30. for(int i = 0; i < NUMBER_OF_CARDS; i++) queue_enqueue(state->shuffleQueue, &array[i]);
  31. }
  32. int game_step_draw_card(GameState* state, int playerNumber) {
  33. if(game_get_player_hand_count(state, 0) == 0) {
  34. for(int i = 0; i < NUMBER_OF_CARDS; i++)
  35. if(state->cardLocation[i] == -1) state->cardLocation[i] = 0;
  36. }
  37. int cardIndex;
  38. do {
  39. if(queue_count(state->shuffleQueue) == 0) fill_shuffle_queue(state);
  40. queue_dequeue(state->shuffleQueue, &cardIndex);
  41. } while(state->cardLocation[cardIndex] != 0);
  42. state->cardLocation[cardIndex] = playerNumber;
  43. return cardIndex;
  44. }
  45. bool game_is_draw_four_valid_to_play(GameState* state, int playerIndex) {
  46. Card topCard = AllCardsData[game_get_top_card(state)];
  47. CardSuit forbiddenSuit = state->forcedSuit != CardSuit_None ? state->forcedSuit : topCard.suit;
  48. for(int i = 0; i < NUMBER_OF_CARDS; i++) {
  49. if(state->cardLocation[i] == playerIndex) {
  50. Card card = AllCardsData[i];
  51. if(card.suit == forbiddenSuit) return false;
  52. }
  53. }
  54. return true;
  55. }
  56. bool game_is_card_valid_to_play(GameState* state, int cardIndex) {
  57. Card card = AllCardsData[cardIndex];
  58. Card topCard = AllCardsData[game_get_top_card(state)];
  59. // Playing a joker
  60. if(card.action == ActionType_ChangeSuit) return true;
  61. if(card.action == ActionType_ChangeSuitPlus4)
  62. return game_is_draw_four_valid_to_play(state, state->playerTurn);
  63. // Playing on a joker (forced suit)
  64. if(state->forcedSuit != CardSuit_None && card.suit == state->forcedSuit) return true;
  65. // Playing a card of the same suit or number
  66. if(card.suit == topCard.suit) return true;
  67. if(card.number != -1 && card.number == topCard.number) return true;
  68. // Playing an action card of the same action
  69. if(card.action != ActionType_None && card.action == topCard.action) return true;
  70. return false;
  71. }
  72. void assert_valid_play(GameState* state, int cardIndex, CardSuit forcedSuit) {
  73. char message[100];
  74. Card card = AllCardsData[cardIndex];
  75. bool isForcingSuit = forcedSuit != CardSuit_None;
  76. bool requiresForcedSuit = card.action == ActionType_ChangeSuit ||
  77. card.action == ActionType_ChangeSuitPlus4;
  78. if(isForcingSuit != requiresForcedSuit) {
  79. snprintf(message, 100, "Invalid forced suit: %d on %d", forcedSuit, card.action);
  80. throw_exception(message);
  81. }
  82. if(!game_is_card_valid_to_play(state, cardIndex)) {
  83. snprintf(message, 100, "Invalid play: %d on %d", cardIndex, state->topCard);
  84. throw_exception(message);
  85. }
  86. }
  87. int game_get_winner(GameState* state) {
  88. return state->winner;
  89. }
  90. void game_update_winner(GameState* state) {
  91. for(int playerIndex = 1; playerIndex <= NUMBER_OF_PLAYERS; playerIndex++) {
  92. if(game_get_player_hand_count(state, playerIndex) == 0) {
  93. state->winner = playerIndex;
  94. break;
  95. }
  96. }
  97. }
  98. void game_set_card_to_play(GameState* state, int cardIndex, int forcedSuit) {
  99. assert_valid_play(state, cardIndex, forcedSuit);
  100. state->cardToPlay = cardIndex;
  101. state->forcedSuitToPlay = forcedSuit;
  102. }
  103. int game_get_card_to_play(GameState* state) {
  104. return state->cardToPlay;
  105. }
  106. CardSuit game_get_forced_suit_to_play(GameState* state) {
  107. return state->forcedSuitToPlay;
  108. }
  109. void game_apply_card_to_play(GameState* state) {
  110. int cardIndex = state->cardToPlay;
  111. CardSuit forcedSuit = state->forcedSuitToPlay;
  112. game_step_play_card(state, cardIndex);
  113. if(game_get_winner(state) != 0) return;
  114. Card card = AllCardsData[cardIndex];
  115. if(card.action == ActionType_Invert) game_step_reverse(state);
  116. if(card.action == ActionType_Skip) game_step_next_player(state);
  117. if(card.action == ActionType_ChangeSuit) game_step_set_suit(state, forcedSuit);
  118. if(card.action == ActionType_Plus2) {
  119. game_step_draw_card(state, game_get_next_player(state));
  120. game_step_draw_card(state, game_get_next_player(state));
  121. game_step_next_player(state);
  122. }
  123. if(card.action == ActionType_ChangeSuitPlus4) {
  124. game_step_draw_card(state, game_get_next_player(state));
  125. game_step_draw_card(state, game_get_next_player(state));
  126. game_step_draw_card(state, game_get_next_player(state));
  127. game_step_draw_card(state, game_get_next_player(state));
  128. game_step_set_suit(state, forcedSuit);
  129. game_step_next_player(state);
  130. }
  131. state->cardToPlay = CARD_NONE;
  132. state->forcedSuitToPlay = CardSuit_None;
  133. // Next player
  134. game_step_next_player(state);
  135. }
  136. void game_step_play_card(GameState* state, int cardIndex) {
  137. state->cardLocation[cardIndex] = -1;
  138. state->topCard = cardIndex;
  139. state->forcedSuit = CardSuit_None;
  140. game_update_winner(state);
  141. }
  142. void game_step_next_player(GameState* state) {
  143. state->playerTurn = game_get_next_player(state);
  144. }
  145. void game_step_reverse(GameState* state) {
  146. state->direction = -state->direction;
  147. }
  148. void game_step_set_suit(GameState* state, int suit) {
  149. state->forcedSuit = suit;
  150. }
  151. void initialize_cards_data() {
  152. // Initializes cards data.
  153. // Order is useful: it will be used when displaying the cards so they are already sorted.
  154. static bool initialized = false;
  155. if(initialized) return;
  156. initialized = true;
  157. int cardIndex = 0;
  158. for(int suit = 1; suit <= 4; suit++) {
  159. for(int number = 0; number < 10; number++) {
  160. Card card;
  161. card.suit = suit;
  162. card.number = number;
  163. card.action = ActionType_None;
  164. AllCardsData[cardIndex++] = card;
  165. if(number != 0) // 0 is only once per suit
  166. AllCardsData[cardIndex++] = card;
  167. }
  168. }
  169. for(int suit = 1; suit <= 4; suit++) {
  170. Card card;
  171. card = (Card){.suit = suit, .number = -1, .action = ActionType_Skip};
  172. AllCardsData[cardIndex++] = card;
  173. AllCardsData[cardIndex++] = card;
  174. card = (Card){.suit = suit, .number = -1, .action = ActionType_Invert};
  175. AllCardsData[cardIndex++] = card;
  176. AllCardsData[cardIndex++] = card;
  177. card = (Card){.suit = suit, .number = -1, .action = ActionType_Plus2};
  178. AllCardsData[cardIndex++] = card;
  179. AllCardsData[cardIndex++] = card;
  180. }
  181. for(int i = 0; i < 4; i++) {
  182. Card card = {.suit = CardSuit_None, .number = -1, .action = ActionType_ChangeSuit};
  183. AllCardsData[cardIndex++] = card;
  184. }
  185. for(int i = 0; i < 4; i++) {
  186. Card card = {.suit = CardSuit_None, .number = -1, .action = ActionType_ChangeSuitPlus4};
  187. AllCardsData[cardIndex++] = card;
  188. }
  189. }
  190. GameState* game_alloc() {
  191. GameState* state = malloc(sizeof(GameState));
  192. state->shuffleQueue = queue_alloc(NUMBER_OF_CARDS, sizeof(int));
  193. game_reset(state);
  194. return state;
  195. }
  196. void game_free(GameState* state) {
  197. queue_free(state->shuffleQueue);
  198. free(state);
  199. }
  200. void game_reset_top_card(GameState* state) {
  201. int cardIndex;
  202. do {
  203. cardIndex = rand() % NUMBER_OF_CARDS;
  204. } while(AllCardsData[cardIndex].number == -1);
  205. game_step_play_card(state, cardIndex);
  206. }
  207. void game_reset(GameState* state) {
  208. initialize_cards_data();
  209. for(int i = 0; i < NUMBER_OF_CARDS; i++) state->cardLocation[i] = 0;
  210. for(int playerIndex = 1; playerIndex <= NUMBER_OF_PLAYERS; playerIndex++) {
  211. for(int j = 0; j < NUMBER_OF_STARTING_CARDS; j++) {
  212. game_step_draw_card(state, playerIndex);
  213. }
  214. }
  215. game_reset_top_card(state);
  216. state->playerTurn = rand() % NUMBER_OF_PLAYERS + 1;
  217. state->direction = rand() % 2 == 0 ? 1 : -1;
  218. state->cardToPlay = CARD_NONE;
  219. state->forcedSuitToPlay = CardSuit_None;
  220. state->winner = 0;
  221. }
  222. int game_get_player_turn(GameState* state) {
  223. return state->playerTurn;
  224. }
  225. int game_get_next_player(GameState* state) {
  226. return game_calculate_next_player(state, state->playerTurn);
  227. }
  228. int game_calculate_next_player(GameState* state, int playerIndex) {
  229. return (playerIndex - 1 + state->direction + NUMBER_OF_PLAYERS) % NUMBER_OF_PLAYERS + 1;
  230. }
  231. int game_get_top_card(GameState* state) {
  232. return state->topCard;
  233. }
  234. int game_get_card_location(GameState* state, int index) {
  235. return state->cardLocation[index];
  236. }
  237. CardSuit game_get_forced_suit(GameState* state) {
  238. return state->forcedSuit;
  239. }
  240. void game_get_player_hand(GameState* state, int playerIndex, List* result) {
  241. list_clear(result);
  242. for(int i = 0; i < NUMBER_OF_CARDS; i++) {
  243. if(state->cardLocation[i] == playerIndex) list_add(result, &i);
  244. }
  245. }
  246. int game_get_player_hand_count(GameState* state, int playerIndex) {
  247. int count = 0;
  248. for(int i = 0; i < NUMBER_OF_CARDS; i++) {
  249. if(state->cardLocation[i] == playerIndex) count++;
  250. }
  251. return count;
  252. }
  253. void game_get_player_hand_valid_cards(GameState* state, int playerIndex, List* result) {
  254. list_clear(result);
  255. for(int i = 0; i < NUMBER_OF_CARDS; i++) {
  256. if(state->cardLocation[i] == playerIndex && game_is_card_valid_to_play(state, i))
  257. list_add(result, &i);
  258. }
  259. }
  260. int game_get_player_hand_valid_cards_count(GameState* state, int playerIndex) {
  261. int count = 0;
  262. for(int i = 0; i < NUMBER_OF_CARDS; i++) {
  263. if(state->cardLocation[i] == playerIndex && game_is_card_valid_to_play(state, i)) count++;
  264. }
  265. return count;
  266. }
  267. int game_get_direction(GameState* state) {
  268. return state->direction;
  269. }