card.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. #include "card.h"
  2. #include "../../assets.h"
  3. #include "helpers.h"
  4. static RenderSettings default_render = DEFAULT_RENDER;
  5. static Buffer* letters[] = {
  6. (Buffer*)&sprite_2,
  7. (Buffer*)&sprite_3,
  8. (Buffer*)&sprite_4,
  9. (Buffer*)&sprite_5,
  10. (Buffer*)&sprite_6,
  11. (Buffer*)&sprite_7,
  12. (Buffer*)&sprite_8,
  13. (Buffer*)&sprite_9,
  14. (Buffer*)&sprite_10,
  15. (Buffer*)&sprite_J,
  16. (Buffer*)&sprite_Q,
  17. (Buffer*)&sprite_K,
  18. (Buffer*)&sprite_A,
  19. };
  20. static Buffer* suits[] = {
  21. (Buffer*)&sprite_hearths,
  22. (Buffer*)&sprite_spades,
  23. (Buffer*)&sprite_diamonds,
  24. (Buffer*)&sprite_clubs};
  25. static Buffer* backSide = (Buffer*)&sprite_pattern_big;
  26. void card_render_front(
  27. Card* c,
  28. int16_t x,
  29. int16_t y,
  30. bool selected,
  31. Buffer* buffer,
  32. uint8_t size_limit) {
  33. uint8_t height = y + fmin(size_limit, 22);
  34. buffer_draw_rbox(buffer, x, y, x + 16, height, White);
  35. buffer_draw_rbox_frame(buffer, x, y, x + 16, height, Black);
  36. Vector p = (Vector){(float)x + 6, (float)y + 5};
  37. buffer_draw_all(buffer, letters[c->value], &p, 0);
  38. p = (Vector){(float)x + 12, (float)y + 5};
  39. buffer_draw_all(buffer, suits[c->suit], &p, 0);
  40. if(size_limit > 8) {
  41. p = (Vector){(float)x + 10, (float)y + 16};
  42. buffer_draw_all(buffer, letters[c->value], &p, M_PI);
  43. p = (Vector){(float)x + 4, (float)y + 16};
  44. buffer_draw_all(buffer, suits[c->suit], &p, M_PI);
  45. }
  46. if(selected) {
  47. buffer_draw_box(buffer, x, y, x + 17, height + 1, Flip);
  48. }
  49. }
  50. void card_render_slot(int16_t x, int16_t y, bool selected, Buffer* buffer) {
  51. buffer_draw_rbox(buffer, x, y, x + 17, y + 23, Black);
  52. buffer_draw_rbox_frame(buffer, x + 2, y + 2, x + 14, y + 20, White);
  53. if(selected) buffer_draw_rbox(buffer, x + 1, y + 1, x + 16, y + 22, Flip);
  54. }
  55. void card_render_back(int16_t x, int16_t y, bool selected, Buffer* buffer, uint8_t size_limit) {
  56. uint8_t height = y + fmin(size_limit, 22);
  57. buffer_draw_rbox(buffer, x + 1, y + 1, x + 16, height, White);
  58. buffer_draw_rbox_frame(buffer, x, y, x + 16, height, Black);
  59. Vector pos = (Vector){(float)x + 9, (float)y + 11};
  60. check_pointer(buffer);
  61. check_pointer(backSide);
  62. check_pointer(&pos);
  63. check_pointer(&default_render);
  64. buffer_draw(buffer, backSide, &pos, 15, (int)fmin(size_limit, 22), 0, &default_render);
  65. if(selected) {
  66. buffer_draw_box(buffer, x, y, x + 17, height + 1, Flip);
  67. }
  68. }
  69. void card_try_render(
  70. Card* c,
  71. int16_t x,
  72. int16_t y,
  73. bool selected,
  74. Buffer* buffer,
  75. uint8_t size_limit) {
  76. if(c) {
  77. if(c->exposed)
  78. card_render_front(c, x, y, selected, buffer, size_limit);
  79. else
  80. card_render_back(x, y, selected, buffer, size_limit);
  81. } else {
  82. card_render_slot(x, y, selected, buffer);
  83. }
  84. }
  85. bool card_test_foundation(Card* data, Card* target) {
  86. if(!target || (target->value == -1 && target->suit == data->suit)) {
  87. return data->value == ACE;
  88. }
  89. return target->suit == data->suit && ((target->value + 1) % 13 == data->value % 13);
  90. }
  91. bool card_test_column(Card* data, Card* target) {
  92. if(!target) return data->value == KING;
  93. return target->suit % 2 == (data->suit + 1) % 2 && (data->value + 1) == target->value;
  94. }
  95. List* deck_generate(uint8_t deck_count) {
  96. List* deck = list_make();
  97. int cards_count = 52 * deck_count;
  98. uint8_t cards[cards_count];
  99. for(int i = 0; i < cards_count; i++)
  100. cards[i] = i % 52;
  101. srand(curr_time());
  102. //reorder
  103. for(int i = 0; i < cards_count; i++) {
  104. int r = i + (rand() % (cards_count - i));
  105. uint8_t card = cards[i];
  106. cards[i] = cards[r];
  107. cards[r] = card;
  108. }
  109. //Init deck list
  110. for(int i = 0; i < cards_count; i++) {
  111. Card* c = malloc(sizeof(Card));
  112. c->value = cards[i] % 13;
  113. c->suit = cards[i] / 13;
  114. c->exposed = false;
  115. list_push_back(c, deck);
  116. }
  117. return deck;
  118. }
  119. void deck_free(List* deck) {
  120. list_free(deck);
  121. }
  122. void deck_render_vertical(List* deck, uint8_t x, uint8_t y, int8_t selected, Buffer* buffer) {
  123. check_pointer(deck);
  124. check_pointer(buffer);
  125. uint8_t loop_end = deck->count;
  126. int8_t selection = loop_end - selected;
  127. uint8_t loop_start = MAX(loop_end - 4, 0);
  128. uint8_t position = 0;
  129. int8_t first_non_flipped;
  130. Card* first_non_flipped_card = deck_first_non_flipped(deck, &first_non_flipped);
  131. bool had_top = false;
  132. bool showDark = selection >= 0;
  133. if(first_non_flipped <= loop_start && selection != first_non_flipped &&
  134. first_non_flipped_card) {
  135. // Draw a card back if it is not the first card
  136. if(first_non_flipped > 0) {
  137. card_render_back(x, y + position, false, buffer, 5);
  138. // Increment loop start index and position
  139. position += 4;
  140. loop_start++;
  141. had_top = true;
  142. }
  143. // Draw the front side of the first non-flipped card
  144. card_try_render(
  145. first_non_flipped_card, x, y + position, false, buffer, deck->count == 1 ? 22 : 9);
  146. position += 8;
  147. loop_start++; // Increment loop start index
  148. }
  149. // Draw the selected card with adjusted visibility
  150. if(loop_start > selection) {
  151. if(!had_top && first_non_flipped > 0) {
  152. card_render_back(x, y + position, false, buffer, 5);
  153. position += 4;
  154. loop_start++;
  155. }
  156. Card* selected_card = (Card*)list_peek_index(deck, selection);
  157. check_pointer(selected_card);
  158. // Draw the front side of the selected card
  159. card_try_render(selected_card, x, y + position, showDark, buffer, 9);
  160. position += 8;
  161. loop_start++; // Increment loop start index
  162. }
  163. int height = 5;
  164. ListItem* curr = list_get_index(deck, loop_start);
  165. for(uint8_t i = loop_start; i < loop_end; i++) {
  166. check_pointer(curr);
  167. if(!curr) break;
  168. if(i >= loop_start && i < loop_end) {
  169. height = 5;
  170. if((i + 1) == loop_end)
  171. height = 22;
  172. else if(i == selection || i == first_non_flipped)
  173. height = 9;
  174. Card* c = (Card*)curr->data;
  175. check_pointer(c);
  176. card_try_render(c, x, y + position, i == selection && showDark, buffer, height);
  177. if(i == selection || i == first_non_flipped) position += 4;
  178. position += 4;
  179. }
  180. curr = curr->next;
  181. }
  182. }
  183. void deck_render(
  184. List* deck,
  185. DeckType type,
  186. int16_t x,
  187. int16_t y,
  188. int8_t selected,
  189. bool draw_empty,
  190. Buffer* buffer) {
  191. switch(type) {
  192. case Normal:
  193. card_try_render(list_peek_back(deck), x, y, selected == 1, buffer, 22);
  194. break;
  195. case Vertical:
  196. if(deck && deck->count > 0)
  197. deck_render_vertical(deck, x, y, selected, buffer);
  198. else if(draw_empty)
  199. card_render_slot(x, y, selected == 1, buffer);
  200. break;
  201. case Pile:
  202. break;
  203. }
  204. }
  205. Card* deck_first_non_flipped(List* deck, int8_t* index) {
  206. ListItem* curr = deck->head;
  207. for(int8_t i = 0; i < (int8_t)deck->count; i++) {
  208. if(!curr->data) break;
  209. Card* card = (Card*)curr->data;
  210. if(card->exposed) {
  211. (*index) = i;
  212. return card;
  213. }
  214. curr = curr->next;
  215. }
  216. (*index) = -1;
  217. return NULL;
  218. }