| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213 |
- #include "solve_screen.h"
- #include "../../game_state.h"
- #include "play_screen.h"
- uint8_t target_foundation;
- static double accumulated_delta = 0;
- static Vector animation_target = VECTOR_ZERO;
- static Vector animation_from = VECTOR_ZERO;
- void start_solve_screen(void* data) {
- UNUSED(data);
- accumulated_delta = 0;
- target_foundation = 0;
- }
- void render_solve_screen(void* data) {
- GameState* state = (GameState*)data;
- render_play_screen(state);
- if(state->animated_card.card) {
- card_render_front(
- state->animated_card.card,
- (uint8_t)state->animated_card.position.x,
- (uint8_t)state->animated_card.position.y,
- false,
- state->buffer,
- 22);
- }
- }
- bool end_solve_screen(GameState* state) {
- for(uint8_t i = 0; i < 4; i++) {
- Card* c = list_peek_back(state->foundation[i]);
- if(!c || c->value != KING) return false;
- }
- return true;
- }
- static int8_t missing_suit(GameState* state) {
- bool found[4] = {false, false, false, false};
- for(uint8_t i = 0; i < 4; i++) {
- if(state->foundation[i]->count) {
- Card* c = list_peek_back(state->foundation[i]);
- found[c->suit] = true;
- }
- }
- for(int8_t i = 0; i < 4; i++) {
- if(!found[i]) return i;
- }
- return -1;
- }
- static void quick_solve(GameState* state) {
- //remove all cards that are not placed to the foundation yet
- list_free_data(state->deck);
- list_free_data(state->waste);
- for(uint8_t i = 0; i < 7; i++) {
- list_free_data(state->tableau[i]);
- }
- list_free_data(state->hand);
- state->animated_card.card = NULL;
- //fill up the foundations with cards
- for(uint8_t i = 0; i < 4; i++) {
- //add ace to the start
- if(state->foundation[i]->count == 0) {
- Card* c = malloc(sizeof(Card));
- c->value = ACE;
- c->suit = missing_suit(state);
- c->exposed = true;
- list_push_back(c, state->foundation[i]);
- }
- //fill up the rest
- for(uint8_t v = state->foundation[i]->count; v < 13; v++) {
- Card* c = malloc(sizeof(Card));
- c->value = v - 1;
- c->suit = ((Card*)list_peek_back(state->foundation[i]))->suit;
- c->exposed = true;
- list_push_back(c, state->foundation[i]);
- }
- }
- end_solve_screen(state);
- }
- static bool animation_done(GameState* state) {
- if(!state->animated_card.card) return true;
- accumulated_delta += state->delta_time * 4;
- vector_lerp(
- &(animation_from), &animation_target, accumulated_delta, &(state->animated_card.position));
- double dist = vector_distance(&(state->animated_card.position), &animation_target);
- return dist < 1;
- }
- static Card* find_and_remove(List* list, uint8_t suit, uint8_t value) {
- //go reversed order because tableau will always have at the end
- ListItem* current = list->tail;
- while(current) {
- if(((Card*)current->data)->value == value && ((Card*)current->data)->suit == suit) {
- Card* c = current->data;
- list_remove_item(c, list);
- return c;
- }
- current = current->prev;
- }
- return NULL;
- }
- static uint8_t positions[9] = {2, 20, 2, 20, 38, 56, 74, 92, 110};
- static void find_next_card(GameState* state) {
- List* order[9] = {
- state->deck,
- state->waste,
- state->tableau[0],
- state->tableau[1],
- state->tableau[2],
- state->tableau[3],
- state->tableau[4],
- state->tableau[5],
- state->tableau[6]};
- int8_t missing = missing_suit(state);
- if(missing >= 0) {
- //find the missing ACE
- for(uint8_t id = 0; id < 9; id++) {
- Card* ace = find_and_remove(order[id], missing, ACE);
- if(ace) {
- ace->exposed = true;
- for(uint8_t i = 0; i < 4; i++) {
- if(state->foundation[i]->count == 0) {
- state->animated_card.card = ace;
- target_foundation = i;
- animation_from.x = positions[id];
- animation_from.y =
- id < 2 ? 1 :
- ((float)MIN(
- (uint8_t)state->tableau[state->selected[0]]->count, 4) *
- 4 +
- 15);
- state->animated_card.position = animation_from;
- animation_target.x = (float)(56 + target_foundation * 18);
- animation_target.y = 1;
- }
- }
- }
- }
- } else {
- uint8_t lowestValue = 14, lowestSuit = 0;
- //get the lowest value
- for(uint8_t i = 0; i < 4; i++) {
- Card* c = list_peek_back(state->foundation[i]);
- if(lowestValue > ((c->value + 1) % 13)) {
- lowestValue = ((c->value + 1) % 13);
- target_foundation = i;
- lowestSuit = c->suit;
- }
- }
- //store that card to animate
- for(uint8_t id = 0; id < 9; id++) {
- Card* c = find_and_remove(order[id], lowestSuit, lowestValue);
- if(c) {
- state->animated_card.card = c;
- animation_from.x = positions[id];
- animation_from.y =
- id < 2 ?
- 1 :
- ((float)MIN((uint8_t)state->tableau[state->selected[0]]->count, 4) * 4 +
- 15);
- state->animated_card.position = animation_from;
- animation_target.x = (float)(56 + target_foundation * 18);
- animation_target.y = 1;
- break;
- }
- }
- }
- }
- void update_solve_screen(void* data) {
- GameState* state = (GameState*)data;
- state->isDirty = true;
- if(!end_solve_screen(state)) {
- if(animation_done(state)) {
- if(state->animated_card.card) {
- state->animated_card.card->exposed = true;
- list_push_back(state->animated_card.card, state->foundation[target_foundation]);
- state->animated_card.card = NULL;
- accumulated_delta = 0;
- }
- find_next_card(state);
- }
- } else {
- state->scene_switch = 1;
- }
- }
- void input_solve_screen(void* data, InputKey key, InputType type) {
- if(key == InputKeyOk && type == InputTypePress) {
- quick_solve(data);
- }
- }
|