solve_screen.c 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. #include "solve_screen.h"
  2. #include "../../game_state.h"
  3. #include "play_screen.h"
  4. uint8_t target_foundation;
  5. static double accumulated_delta = 0;
  6. static Vector animation_target = VECTOR_ZERO;
  7. static Vector animation_from = VECTOR_ZERO;
  8. void start_solve_screen(void* data) {
  9. UNUSED(data);
  10. accumulated_delta = 0;
  11. target_foundation = 0;
  12. }
  13. void render_solve_screen(void* data) {
  14. GameState* state = (GameState*)data;
  15. render_play_screen(state);
  16. if(state->animated_card.card) {
  17. card_render_front(
  18. state->animated_card.card,
  19. (uint8_t)state->animated_card.position.x,
  20. (uint8_t)state->animated_card.position.y,
  21. false,
  22. state->buffer,
  23. 22);
  24. }
  25. }
  26. bool end_solve_screen(GameState* state) {
  27. for(uint8_t i = 0; i < 4; i++) {
  28. Card* c = list_peek_back(state->foundation[i]);
  29. if(!c || c->value != KING) return false;
  30. }
  31. return true;
  32. }
  33. static int8_t missing_suit(GameState* state) {
  34. bool found[4] = {false, false, false, false};
  35. for(uint8_t i = 0; i < 4; i++) {
  36. if(state->foundation[i]->count) {
  37. Card* c = list_peek_back(state->foundation[i]);
  38. found[c->suit] = true;
  39. }
  40. }
  41. for(int8_t i = 0; i < 4; i++) {
  42. if(!found[i]) return i;
  43. }
  44. return -1;
  45. }
  46. static void quick_solve(GameState* state) {
  47. //remove all cards that are not placed to the foundation yet
  48. list_free_data(state->deck);
  49. list_free_data(state->waste);
  50. for(uint8_t i = 0; i < 7; i++) {
  51. list_free_data(state->tableau[i]);
  52. }
  53. list_free_data(state->hand);
  54. state->animated_card.card = NULL;
  55. //fill up the foundations with cards
  56. for(uint8_t i = 0; i < 4; i++) {
  57. //add ace to the start
  58. if(state->foundation[i]->count == 0) {
  59. Card* c = malloc(sizeof(Card));
  60. c->value = ACE;
  61. c->suit = missing_suit(state);
  62. c->exposed = true;
  63. list_push_back(c, state->foundation[i]);
  64. }
  65. //fill up the rest
  66. for(uint8_t v = state->foundation[i]->count; v < 13; v++) {
  67. Card* c = malloc(sizeof(Card));
  68. c->value = v - 1;
  69. c->suit = ((Card*)list_peek_back(state->foundation[i]))->suit;
  70. c->exposed = true;
  71. list_push_back(c, state->foundation[i]);
  72. }
  73. }
  74. end_solve_screen(state);
  75. }
  76. static bool animation_done(GameState* state) {
  77. if(!state->animated_card.card) return true;
  78. accumulated_delta += state->delta_time * 4;
  79. vector_lerp(
  80. &(animation_from), &animation_target, accumulated_delta, &(state->animated_card.position));
  81. double dist = vector_distance(&(state->animated_card.position), &animation_target);
  82. return dist < 1;
  83. }
  84. static Card* find_and_remove(List* list, uint8_t suit, uint8_t value) {
  85. //go reversed order because tableau will always have at the end
  86. ListItem* current = list->tail;
  87. while(current) {
  88. if(((Card*)current->data)->value == value && ((Card*)current->data)->suit == suit) {
  89. Card* c = current->data;
  90. list_remove_item(c, list);
  91. return c;
  92. }
  93. current = current->prev;
  94. }
  95. return NULL;
  96. }
  97. static uint8_t positions[9] = {2, 20, 2, 20, 38, 56, 74, 92, 110};
  98. static void find_next_card(GameState* state) {
  99. List* order[9] = {
  100. state->deck,
  101. state->waste,
  102. state->tableau[0],
  103. state->tableau[1],
  104. state->tableau[2],
  105. state->tableau[3],
  106. state->tableau[4],
  107. state->tableau[5],
  108. state->tableau[6]};
  109. int8_t missing = missing_suit(state);
  110. if(missing >= 0) {
  111. //find the missing ACE
  112. for(uint8_t id = 0; id < 9; id++) {
  113. Card* ace = find_and_remove(order[id], missing, ACE);
  114. if(ace) {
  115. ace->exposed = true;
  116. for(uint8_t i = 0; i < 4; i++) {
  117. if(state->foundation[i]->count == 0) {
  118. state->animated_card.card = ace;
  119. target_foundation = i;
  120. animation_from.x = positions[id];
  121. animation_from.y =
  122. id < 2 ? 1 :
  123. ((float)MIN(
  124. (uint8_t)state->tableau[state->selected[0]]->count, 4) *
  125. 4 +
  126. 15);
  127. state->animated_card.position = animation_from;
  128. animation_target.x = (float)(56 + target_foundation * 18);
  129. animation_target.y = 1;
  130. }
  131. }
  132. }
  133. }
  134. } else {
  135. uint8_t lowestValue = 14, lowestSuit = 0;
  136. //get the lowest value
  137. for(uint8_t i = 0; i < 4; i++) {
  138. Card* c = list_peek_back(state->foundation[i]);
  139. if(lowestValue > ((c->value + 1) % 13)) {
  140. lowestValue = ((c->value + 1) % 13);
  141. target_foundation = i;
  142. lowestSuit = c->suit;
  143. }
  144. }
  145. //store that card to animate
  146. for(uint8_t id = 0; id < 9; id++) {
  147. Card* c = find_and_remove(order[id], lowestSuit, lowestValue);
  148. if(c) {
  149. state->animated_card.card = c;
  150. animation_from.x = positions[id];
  151. animation_from.y =
  152. id < 2 ?
  153. 1 :
  154. ((float)MIN((uint8_t)state->tableau[state->selected[0]]->count, 4) * 4 +
  155. 15);
  156. state->animated_card.position = animation_from;
  157. animation_target.x = (float)(56 + target_foundation * 18);
  158. animation_target.y = 1;
  159. break;
  160. }
  161. }
  162. }
  163. }
  164. void update_solve_screen(void* data) {
  165. GameState* state = (GameState*)data;
  166. state->isDirty = true;
  167. if(!end_solve_screen(state)) {
  168. if(animation_done(state)) {
  169. if(state->animated_card.card) {
  170. state->animated_card.card->exposed = true;
  171. list_push_back(state->animated_card.card, state->foundation[target_foundation]);
  172. state->animated_card.card = NULL;
  173. accumulated_delta = 0;
  174. }
  175. find_next_card(state);
  176. }
  177. } else {
  178. state->scene_switch = 1;
  179. }
  180. }
  181. void input_solve_screen(void* data, InputKey key, InputType type) {
  182. if(key == InputKeyOk && type == InputTypePress) {
  183. quick_solve(data);
  184. }
  185. }