فهرست منبع

update 2 apps

MX 2 سال پیش
والد
کامیت
8e23f104aa
3فایلهای تغییر یافته به همراه326 افزوده شده و 307 حذف شده
  1. 21 0
      LICENSE
  2. 9 3
      defines.h
  3. 296 304
      solitaire.c

+ 21 - 0
LICENSE

@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2023 Tibor Tálosi
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.

+ 9 - 3
defines.h

@@ -19,10 +19,15 @@ typedef struct {
     InputEvent input;
 } AppEvent;
 
-typedef enum { GameStateGameOver, GameStateStart, GameStatePlay, GameStateAnimate } PlayState;
+typedef enum {
+    GameStateGameOver,
+    GameStateStart,
+    GameStatePlay,
+    GameStateAnimate
+} PlayState;
 
 typedef struct {
-    uint8_t* buffer;
+    uint8_t *buffer;
     Card card;
     int8_t deck;
     int indexes[4];
@@ -44,6 +49,7 @@ typedef struct {
     InputKey input;
 
     bool started;
+    bool had_change;
     bool processing;
     bool longPress;
     PlayState state;
@@ -52,6 +58,6 @@ typedef struct {
     uint8_t selectColumn;
     int8_t selected_card;
     CardAnimation animation;
-    uint8_t* buffer;
+    uint8_t *buffer;
     FuriMutex* mutex;
 } GameState;

+ 296 - 304
solitaire.c

@@ -7,257 +7,235 @@
 #include "solitaire_icons.h"
 #include <notification/notification.h>
 #include <notification/notification_messages.h>
-void init(GameState* game_state);
+void init(GameState *game_state);
+
 const NotificationSequence sequence_fail = {
-    &message_vibro_on,
-    &message_note_c4,
-    &message_delay_10,
-    &message_vibro_off,
-    &message_sound_off,
-    &message_delay_10,
-
-    &message_vibro_on,
-    &message_note_a3,
-    &message_delay_10,
-    &message_vibro_off,
-    &message_sound_off,
-    NULL,
+        &message_vibro_on,
+        &message_note_c4,
+        &message_delay_10,
+        &message_vibro_off,
+        &message_sound_off,
+        &message_delay_10,
+
+        &message_vibro_on,
+        &message_note_a3,
+        &message_delay_10,
+        &message_vibro_off,
+        &message_sound_off,
+        NULL,
 };
 int8_t columns[7][3] = {
-    {1, 1, 25},
-    {19, 1, 25},
-    {37, 1, 25},
-    {55, 1, 25},
-    {73, 1, 25},
-    {91, 1, 25},
-    {109, 1, 25},
+        {1,   1, 25},
+        {19,  1, 25},
+        {37,  1, 25},
+        {55,  1, 25},
+        {73,  1, 25},
+        {91,  1, 25},
+        {109, 1, 25},
 };
 
 bool can_place_card(Card where, Card what) {
-    FURI_LOG_D(
-        APP_NAME,
-        "TESTING pip %i, letter %i with pip %i, letter %i",
-        where.pip,
-        where.character,
-        what.pip,
-        what.character);
     bool a_black = where.pip == 0 || where.pip == 3;
     bool b_black = what.pip == 0 || what.pip == 3;
-    if(a_black == b_black) return false;
+    if (a_black == b_black) return false;
 
-    int8_t a_letter = (int8_t)where.character;
-    int8_t b_letter = (int8_t)what.character;
-    if(a_letter == 12) a_letter = -1;
-    if(b_letter == 12) b_letter = -1;
+    int8_t a_letter = (int8_t) where.character;
+    int8_t b_letter = (int8_t) what.character;
+    if (a_letter == 12) a_letter = -1;
+    if (b_letter == 12) b_letter = -1;
 
     return (a_letter - 1) == b_letter;
 }
 
-static void draw_scene(Canvas* const canvas, const GameState* game_state) {
-    int deckIndex = game_state->deck.index;
-    if(game_state->dragging_deck) deckIndex--;
-
-    if((game_state->deck.index < (game_state->deck.card_count - 1) ||
-        game_state->deck.index == -1) &&
-       game_state->deck.card_count > 0) {
-        draw_card_back_at(columns[0][0], columns[0][1], canvas);
-        if(game_state->selectRow == 0 && game_state->selectColumn == 0) {
-            draw_rounded_box(
-                canvas,
-                columns[0][0] + 1,
-                columns[0][1] + 1,
-                CARD_WIDTH - 2,
-                CARD_HEIGHT - 2,
-                Inverse);
-        }
-    } else
-        draw_card_space(
-            columns[0][0],
-            columns[0][1],
-            game_state->selectRow == 0 && game_state->selectColumn == 0,
-            canvas);
-    //deck side
-    if(deckIndex >= 0) {
-        Card c = game_state->deck.cards[deckIndex];
-        draw_card_at_colored(
-            columns[1][0],
-            columns[1][1],
-            c.pip,
-            c.character,
-            game_state->selectRow == 0 && game_state->selectColumn == 1,
-            canvas);
-    } else
-        draw_card_space(
-            columns[1][0],
-            columns[1][1],
-            game_state->selectRow == 0 && game_state->selectColumn == 1,
-            canvas);
-
-    for(uint8_t i = 0; i < 4; i++) {
-        Card current = game_state->top_cards[i];
-        bool selected = game_state->selectRow == 0 && game_state->selectColumn == (i + 3);
-        if(current.disabled) {
-            draw_card_space(columns[i + 3][0], columns[i + 3][1], selected, canvas);
-        } else {
-            draw_card_at(
-                columns[i + 3][0], columns[i + 3][1], current.pip, current.character, canvas);
-            if(selected) {
-                draw_rounded_box(
-                    canvas, columns[i + 3][0], columns[i + 3][1], CARD_WIDTH, CARD_HEIGHT, Inverse);
+static void draw_scene(Canvas *const canvas, const GameState *game_state) {
+
+    if(game_state->had_change){
+        int deckIndex = game_state->deck.index;
+        if (game_state->dragging_deck)
+            deckIndex--;
+
+        if ((game_state->deck.index < (game_state->deck.card_count - 1) || game_state->deck.index == -1) && game_state->deck.card_count>0) {
+            draw_card_back_at(columns[0][0], columns[0][1], canvas);
+            if (game_state->selectRow == 0 && game_state->selectColumn == 0) {
+                draw_rounded_box(canvas, columns[0][0] + 1, columns[0][1] + 1, CARD_WIDTH - 2, CARD_HEIGHT - 2,
+                                 Inverse);
+            }
+        } else
+            draw_card_space(columns[0][0], columns[0][1],
+                            game_state->selectRow == 0 && game_state->selectColumn == 0,
+                            canvas);
+        //deck side
+        if (deckIndex >= 0) {
+            Card c = game_state->deck.cards[deckIndex];
+            draw_card_at_colored(columns[1][0], columns[1][1], c.pip, c.character,
+                                 game_state->selectRow == 0 && game_state->selectColumn == 1, canvas);
+        } else
+            draw_card_space(columns[1][0], columns[1][1],
+                            game_state->selectRow == 0 && game_state->selectColumn == 1,
+                            canvas);
+
+        for (uint8_t i = 0; i < 4; i++) {
+            Card current = game_state->top_cards[i];
+            bool selected = game_state->selectRow == 0 && game_state->selectColumn == (i + 3);
+            if (current.disabled) {
+                draw_card_space(columns[i + 3][0], columns[i + 3][1], selected, canvas);
+            } else {
+                draw_card_at(columns[i + 3][0], columns[i + 3][1], current.pip, current.character, canvas);
+                if (selected) {
+                    draw_rounded_box(canvas, columns[i + 3][0], columns[i + 3][1], CARD_WIDTH, CARD_HEIGHT,
+                                     Inverse);
+                }
             }
         }
-    }
 
-    for(uint8_t i = 0; i < 7; i++) {
-        bool selected = game_state->selectRow == 1 && game_state->selectColumn == i;
-        int8_t index = (game_state->bottom_columns[i].index - 1 - game_state->selected_card);
-        if(index < 0) index = 0;
-        draw_hand_column(
-            game_state->bottom_columns[i],
-            columns[i][0],
-            columns[i][2],
-            selected ? index : -1,
-            canvas);
-    }
+        for (uint8_t i = 0; i < 7; i++) {
+            bool selected = game_state->selectRow == 1 && game_state->selectColumn == i;
+            int8_t index= (game_state->bottom_columns[i].index - 1 - game_state->selected_card);
+            if(index<0)index=0;
+            draw_hand_column(game_state->bottom_columns[i], columns[i][0], columns[i][2],
+                             selected ? index : -1, canvas);
+        }
 
-    int8_t pos[2] = {
-        columns[game_state->selectColumn][0],
-        columns[game_state->selectColumn][game_state->selectRow + 1]};
+        int8_t pos[2] = {columns[game_state->selectColumn][0],
+                         columns[game_state->selectColumn][game_state->selectRow + 1]};
 
-    /*     draw_icon_clip(canvas, &I_card_graphics, pos[0] + CARD_HALF_WIDTH, pos[1] + CARD_HALF_HEIGHT, 30, 5, 5, 5,
-                        Filled);*/
+        /*     draw_icon_clip(canvas, &I_card_graphics, pos[0] + CARD_HALF_WIDTH, pos[1] + CARD_HALF_HEIGHT, 30, 5, 5, 5,
+                            Filled);*/
+
+        if (game_state->dragging_hand.index > 0) {
+            draw_hand_column(game_state->dragging_hand,
+                             pos[0] + CARD_HALF_WIDTH + 3, pos[1] + CARD_HALF_HEIGHT + 3,
+                             -1, canvas);
+        }
 
-    if(game_state->dragging_hand.index > 0) {
-        draw_hand_column(
-            game_state->dragging_hand,
-            pos[0] + CARD_HALF_WIDTH + 3,
-            pos[1] + CARD_HALF_HEIGHT + 3,
-            -1,
-            canvas);
+        clone_buffer(get_buffer(canvas), game_state->animation.buffer);
+    }else{
+        clone_buffer(game_state->animation.buffer, get_buffer(canvas));
     }
 }
 
-static void draw_animation(Canvas* const canvas, const GameState* game_state) {
-    if(!game_state->animation.started) {
+static void draw_animation(Canvas *const canvas, const GameState *game_state) {
+    if (!game_state->animation.started) {
         draw_scene(canvas, game_state);
     } else {
         clone_buffer(game_state->animation.buffer, get_buffer(canvas));
 
-        draw_card_at(
-            (int8_t)game_state->animation.x,
-            (int8_t)game_state->animation.y,
-            game_state->animation.card.pip,
-            game_state->animation.card.character,
-            canvas);
+        draw_card_at((int8_t) game_state->animation.x, (int8_t) game_state->animation.y, game_state->animation.card.pip,
+                     game_state->animation.card.character, canvas);
+
     }
 
     clone_buffer(get_buffer(canvas), game_state->animation.buffer);
 }
 
-static void render_callback(Canvas* const canvas, void* ctx) {
-    furi_assert(ctx);
-    const GameState* game_state = ctx;
-    furi_mutex_acquire(game_state->mutex, FuriWaitForever);
-
-    switch(game_state->state) {
-    case GameStateAnimate:
-        draw_animation(canvas, game_state);
-        break;
-    case GameStateStart:
-        canvas_draw_icon(canvas, 0, 0, &I_solitaire_main);
-        break;
-    case GameStatePlay:
-        draw_scene(canvas, game_state);
-        break;
-    default:
-        break;
+static void render_callback(Canvas *const canvas, void *ctx) {
+    const GameState *game_state = ctx;
+    furi_mutex_acquire(game_state->mutex, 25);
+    if (game_state == NULL) {
+        return;
+    }
+
+    switch (game_state->state) {
+        case GameStateAnimate:
+            draw_animation(canvas, game_state);
+            break;
+        case GameStateStart:
+            canvas_draw_icon(canvas, 0, 0, &I_solitaire_main);
+            break;
+        case GameStatePlay:
+            draw_scene(canvas, game_state);
+            break;
+        default:
+            break;
     }
 
     furi_mutex_release(game_state->mutex);
+
 }
 
-void remove_drag(GameState* game_state) {
-    if(game_state->dragging_deck) {
+void remove_drag(GameState *game_state) {
+    if (game_state->dragging_deck) {
         remove_from_deck(game_state->deck.index, &(game_state->deck));
         game_state->dragging_deck = false;
-    } else if(game_state->dragging_column < 7) {
+    } else if (game_state->dragging_column < 7) {
         game_state->dragging_column = 8;
     }
     game_state->dragging_hand.index = 0;
 }
 
-bool handleInput(GameState* game_state) {
+bool handleInput(GameState *game_state) {
     Hand currentHand = game_state->bottom_columns[game_state->selectColumn];
-    switch(game_state->input) {
-    case InputKeyUp:
-        if(game_state->selectRow > 0) {
-            int first = first_non_flipped_card(currentHand);
-            first = currentHand.index - first;
-            if((first - 1) > game_state->selected_card && game_state->dragging_hand.index == 0 &&
-               !game_state->longPress) {
-                game_state->selected_card++;
+    switch (game_state->input) {
+        case InputKeyUp:
+            if (game_state->selectRow > 0) {
+                int first = first_non_flipped_card(currentHand);
+                first = currentHand.index - first;
+                if ((first - 1) > game_state->selected_card && game_state->dragging_hand.index == 0 &&
+                    !game_state->longPress) {
+                    game_state->selected_card++;
+                } else {
+                    game_state->selectRow--;
+                    game_state->selected_card = 0;
+                }
+            }
+            break;
+        case InputKeyDown:
+            if (game_state->selectRow < 1) {
+                game_state->selectRow++;
+                game_state->selected_card = 0;
             } else {
-                game_state->selectRow--;
+                if (game_state->selected_card > 0) {
+                    if (game_state->longPress)
+                        game_state->selected_card = 0;
+                    else
+                        game_state->selected_card--;
+                }
+            }
+            break;
+        case InputKeyRight:
+            if (game_state->selectColumn < 6) {
+                game_state->selectColumn++;
                 game_state->selected_card = 0;
             }
-        }
-        break;
-    case InputKeyDown:
-        if(game_state->selectRow < 1) {
-            game_state->selectRow++;
-            game_state->selected_card = 0;
-        } else {
-            if(game_state->selected_card > 0) {
-                if(game_state->longPress)
-                    game_state->selected_card = 0;
-                else
-                    game_state->selected_card--;
+            break;
+        case InputKeyLeft:
+            if (game_state->selectColumn > 0) {
+                game_state->selectColumn--;
+                game_state->selected_card = 0;
             }
-        }
-        break;
-    case InputKeyRight:
-        if(game_state->selectColumn < 6) {
-            game_state->selectColumn++;
-            game_state->selected_card = 0;
-        }
-        break;
-    case InputKeyLeft:
-        if(game_state->selectColumn > 0) {
-            game_state->selectColumn--;
-            game_state->selected_card = 0;
-        }
-        break;
-    case InputKeyOk:
-        return true;
-        break;
-    default:
-        break;
+            break;
+        case InputKeyOk:
+            return true;
+            break;
+        default:
+            break;
     }
-    if(game_state->selectRow == 0 && game_state->selectColumn == 2) {
-        if(game_state->input == InputKeyRight)
+    if (game_state->selectRow == 0 && game_state->selectColumn == 2) {
+        if (game_state->input == InputKeyRight)
             game_state->selectColumn++;
         else
             game_state->selectColumn--;
     }
-    if(game_state->dragging_hand.index > 0) game_state->selected_card = 0;
+    if (game_state->dragging_hand.index > 0)
+        game_state->selected_card = 0;
     return false;
 }
 
-bool place_on_top(Card* where, Card what) {
-    if(where->disabled && what.character == 12) {
+bool place_on_top(Card *where, Card what) {
+    if (where->disabled && what.character == 12) {
         where->disabled = what.disabled;
         where->pip = what.pip;
         where->character = what.character;
         return true;
-    } else if(where->pip == what.pip) {
-        int8_t a_letter = (int8_t)where->character;
-        int8_t b_letter = (int8_t)what.character;
-        if(a_letter == 12) a_letter = -1;
-        if(b_letter == 12) b_letter = -1;
-
-        if(where->disabled && b_letter != -1) return false;
-
-        if((a_letter + 1) == b_letter) {
+    } else if (where->pip == what.pip) {
+        int8_t a_letter = (int8_t) where->character;
+        int8_t b_letter = (int8_t) what.character;
+        if (a_letter == 12) a_letter = -1;
+        if (b_letter == 12) b_letter = -1;
+        if(where->disabled && b_letter!=-1)
+            return false;
+
+        if ((a_letter + 1) == b_letter) {
             where->disabled = what.disabled;
             where->pip = what.pip;
             where->character = what.character;
@@ -267,92 +245,91 @@ bool place_on_top(Card* where, Card what) {
     return false;
 }
 
-void tick(GameState* game_state, NotificationApp* notification) {
+void tick(GameState *game_state, NotificationApp *notification) {
     game_state->last_tick = furi_get_tick();
     uint8_t row = game_state->selectRow;
     uint8_t column = game_state->selectColumn;
-    if(game_state->state != GameStatePlay && game_state->state != GameStateAnimate) return;
+    if (game_state->state != GameStatePlay && game_state->state != GameStateAnimate) return;
     bool wasAction = false;
-    if(game_state->state == GameStatePlay) {
-        if(game_state->top_cards[0].character == 11 && game_state->top_cards[1].character == 11 &&
-           game_state->top_cards[2].character == 11 && game_state->top_cards[3].character == 11) {
-            dolphin_deed(DolphinDeedPluginGameWin);
+    if (game_state->state == GameStatePlay) {
+        if (game_state->top_cards[0].character == 11 && game_state->top_cards[1].character == 11 &&
+            game_state->top_cards[2].character == 11 && game_state->top_cards[3].character == 11) {
             game_state->state = GameStateAnimate;
+            game_state->had_change=true;
+            dolphin_deed(DolphinDeedPluginGameWin);
+
             return;
         }
     }
-    if(handleInput(game_state)) {
-        if(game_state->state == GameStatePlay) {
-            if(game_state->longPress && game_state->dragging_hand.index == 1) {
-                for(uint8_t i = 0; i < 4; i++) {
-                    if(place_on_top(
-                           &(game_state->top_cards[i]), game_state->dragging_hand.cards[0])) {
+    if (handleInput(game_state)) {
+        if (game_state->state == GameStatePlay) {
+            if (game_state->longPress && game_state->dragging_hand.index == 1) {
+                for (uint8_t i = 0; i < 4; i++) {
+                    if (place_on_top(&(game_state->top_cards[i]), game_state->dragging_hand.cards[0])) {
                         remove_drag(game_state);
                         wasAction = true;
                         break;
                     }
                 }
             } else {
-                if(row == 0 && column == 0 && game_state->dragging_hand.index == 0) {
+                if (row == 0 && column == 0 && game_state->dragging_hand.index == 0) {
                     FURI_LOG_D(APP_NAME, "Drawing card");
                     game_state->deck.index++;
                     wasAction = true;
-                    if(game_state->deck.index >= (game_state->deck.card_count))
+                    if (game_state->deck.index >= (game_state->deck.card_count))
                         game_state->deck.index = -1;
                 }
-                //pick/place from deck
-                else if(row == 0 && column == 1) {
+                    //pick/place from deck
+                else if (row == 0 && column == 1) {
                     //place
-                    if(game_state->dragging_deck) {
+                    if (game_state->dragging_deck) {
                         wasAction = true;
                         game_state->dragging_deck = false;
                         game_state->dragging_hand.index = 0;
                     }
-                    //pick
+                        //pick
                     else {
-                        if(game_state->dragging_hand.index == 0 && game_state->deck.index >= 0) {
+                        if (game_state->dragging_hand.index == 0 && game_state->deck.index >= 0) {
                             wasAction = true;
                             game_state->dragging_deck = true;
-                            add_to_hand(
-                                &(game_state->dragging_hand),
-                                game_state->deck.cards[game_state->deck.index]);
+                            add_to_hand(&(game_state->dragging_hand), game_state->deck.cards[game_state->deck.index]);
                         }
                     }
                 }
-                //place on top row
-                else if(row == 0 && game_state->dragging_hand.index == 1) {
+                    //place on top row
+                else if (row == 0 && game_state->dragging_hand.index == 1) {
                     column -= 3;
                     Card currCard = game_state->dragging_hand.cards[0];
                     wasAction = place_on_top(&(game_state->top_cards[column]), currCard);
-                    if(wasAction) remove_drag(game_state);
+                    if (wasAction)
+                        remove_drag(game_state);
                 }
-                //pick/place from bottom
-                else if(row == 1) {
-                    Hand* curr_hand = &(game_state->bottom_columns[column]);
+                    //pick/place from bottom
+                else if (row == 1) {
+                    Hand *curr_hand = &(game_state->bottom_columns[column]);
                     //pick up
-                    if(game_state->dragging_hand.index == 0) {
+                    if (game_state->dragging_hand.index == 0) {
                         Card curr_card = curr_hand->cards[curr_hand->index - 1];
-                        if(curr_card.flipped) {
+                        if (curr_card.flipped) {
                             curr_hand->cards[curr_hand->index - 1].flipped = false;
                             wasAction = true;
                         } else {
-                            if(curr_hand->index > 0) {
-                                extract_hand_region(
-                                    curr_hand,
-                                    &(game_state->dragging_hand),
-                                    curr_hand->index - game_state->selected_card - 1);
+                            if (curr_hand->index > 0) {
+                                extract_hand_region(curr_hand, &(game_state->dragging_hand),
+                                                    curr_hand->index - game_state->selected_card - 1);
                                 game_state->selected_card = 0;
                                 game_state->dragging_column = column;
                                 wasAction = true;
                             }
                         }
                     }
-                    //place
+                        //place
                     else {
                         Card first = game_state->dragging_hand.cards[0];
-                        if(game_state->dragging_column == column ||
-                           (curr_hand->index == 0 && first.character == 11) ||
-                           can_place_card(curr_hand->cards[curr_hand->index - 1], first)) {
+                        if (game_state->dragging_column == column ||
+                            (curr_hand->index == 0 && first.character == 11) ||
+                            can_place_card(curr_hand->cards[curr_hand->index - 1], first)
+                                ) {
                             add_hand_region(curr_hand, &(game_state->dragging_hand));
                             remove_drag(game_state);
                             wasAction = true;
@@ -361,34 +338,41 @@ void tick(GameState* game_state, NotificationApp* notification) {
                 }
             }
 
-            if(!wasAction) {
+
+            if (!wasAction) {
                 notification_message(notification, &sequence_fail);
             }
         }
     }
-    if(game_state->state == GameStateAnimate) {
-        if(game_state->animation.started && !game_state->longPress &&
-           game_state->input == InputKeyOk) {
+    if (game_state->state == GameStateAnimate) {
+        if (game_state->animation.started && !game_state->longPress && game_state->input==InputKeyOk) {
             init(game_state);
             game_state->state = GameStateStart;
         }
 
         game_state->animation.started = true;
-        if(game_state->animation.x < -20 || game_state->animation.x > 128) {
+        if (game_state->animation.x < -20 || game_state->animation.x > 128) {
             game_state->animation.deck++;
-            if(game_state->animation.deck > 3) game_state->animation.deck = 0;
+            if (game_state->animation.deck > 3)
+                game_state->animation.deck = 0;
             int8_t cardIndex = 11 - game_state->animation.indexes[game_state->animation.deck];
 
-            if(game_state->animation.indexes[0] == 13 && game_state->animation.indexes[1] == 13 &&
-               game_state->animation.indexes[2] == 13 && game_state->animation.indexes[3] == 13) {
+            if (game_state->animation.indexes[0] == 13 &&
+                game_state->animation.indexes[1] == 13 &&
+                game_state->animation.indexes[2] == 13 &&
+                game_state->animation.indexes[3] == 13) {
                 init(game_state);
                 game_state->state = GameStateStart;
                 return;
             }
 
-            if(cardIndex == -1) cardIndex = 12;
-            game_state->animation.card = (Card){
-                game_state->top_cards[game_state->animation.deck].pip, cardIndex, false, false};
+            if (cardIndex == -1)
+                cardIndex = 12;
+            game_state->animation.card = (Card) {
+                    game_state->top_cards[game_state->animation.deck].pip,
+                    cardIndex,
+                    false, false
+            };
             game_state->animation.indexes[game_state->animation.deck]++;
             game_state->animation.vx = -(rand() % 3 + 1) * (rand() % 2 == 1 ? 1 : -1);
             game_state->animation.vy = (rand() % 3 + 1);
@@ -398,16 +382,17 @@ void tick(GameState* game_state, NotificationApp* notification) {
         game_state->animation.x += game_state->animation.vx;
         game_state->animation.y -= game_state->animation.vy;
         game_state->animation.vy -= 1;
-        if(game_state->animation.vy < -10) game_state->animation.vy = -10;
+        if (game_state->animation.vy < -10)game_state->animation.vy = -10;
 
-        if(game_state->animation.y > 41) {
+        if (game_state->animation.y > 41) {
             game_state->animation.y = 41;
             game_state->animation.vy = -(game_state->animation.vy * 0.7f);
         }
     }
 }
 
-void init(GameState* game_state) {
+void init(GameState *game_state) {
+    dolphin_deed(DolphinDeedPluginGameStart);
     game_state->selectColumn = 0;
     game_state->selected_card = 0;
     game_state->selectRow = 0;
@@ -420,49 +405,52 @@ void init(GameState* game_state) {
     game_state->state = GameStatePlay;
     game_state->dragging_column = 8;
 
-    for(uint8_t i = 0; i < 7; i++) {
+    for (uint8_t i = 0; i < 7; i++) {
         free_hand(&(game_state->bottom_columns[i]));
         init_hand(&(game_state->bottom_columns[i]), 21);
         game_state->bottom_columns[i].index = 0;
-        for(uint8_t j = 0; j <= i; j++) {
+        for (uint8_t j = 0; j <= i; j++) {
             Card cur = remove_from_deck(0, &(game_state->deck));
             cur.flipped = i != j;
             add_to_hand(&(game_state->bottom_columns[i]), cur);
         }
     }
 
-    for(uint8_t i = 0; i < 4; i++) {
+    for (uint8_t i = 0; i < 4; i++) {
         game_state->animation.indexes[i] = 0;
-        game_state->top_cards[i] = (Card){0, 0, true, false};
+        game_state->top_cards[i] = (Card) {0, 0, true, false};
     }
     game_state->deck.index = -1;
 }
 
-void init_start(GameState* game_state) {
+void init_start(GameState *game_state) {
     game_state->input = InputKeyMAX;
-    for(uint8_t i = 0; i < 7; i++) init_hand(&(game_state->bottom_columns[i]), 21);
+    for (uint8_t i = 0; i < 7; i++)
+        init_hand(&(game_state->bottom_columns[i]), 21);
 
     init_hand(&(game_state->dragging_hand), 13);
     game_state->animation.buffer = make_buffer();
+
 }
 
-static void input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) {
+
+static void input_callback(InputEvent *input_event, FuriMessageQueue *event_queue) {
     furi_assert(event_queue);
     AppEvent event = {.type = EventTypeKey, .input = *input_event};
     furi_message_queue_put(event_queue, &event, FuriWaitForever);
 }
 
-static void update_timer_callback(FuriMessageQueue* event_queue) {
+static void update_timer_callback(FuriMessageQueue *event_queue) {
     furi_assert(event_queue);
     AppEvent event = {.type = EventTypeTick};
     furi_message_queue_put(event_queue, &event, 0);
 }
 
-int32_t solitaire_app(void* p) {
+int32_t solitaire_app(void *p) {
     UNUSED(p);
     int32_t return_code = 0;
-    FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(AppEvent));
-    GameState* game_state = malloc(sizeof(GameState));
+    FuriMessageQueue *event_queue = furi_message_queue_alloc(8, sizeof(AppEvent));
+    GameState *game_state = malloc(sizeof(GameState));
     init_start(game_state);
     set_card_graphics(&I_card_graphics);
 
@@ -470,85 +458,87 @@ int32_t solitaire_app(void* p) {
 
     game_state->processing = true;
     game_state->mutex = furi_mutex_alloc(FuriMutexTypeNormal);
-    if(!game_state->mutex) {
+    if (!game_state->mutex) {
         FURI_LOG_E(APP_NAME, "cannot create mutex\r\n");
         return_code = 255;
         goto free_and_exit;
     }
-    NotificationApp* notification = furi_record_open(RECORD_NOTIFICATION);
+    NotificationApp *notification = furi_record_open(RECORD_NOTIFICATION);
 
     notification_message_block(notification, &sequence_display_backlight_enforce_on);
 
-    ViewPort* view_port = view_port_alloc();
+    ViewPort *view_port = view_port_alloc();
     view_port_draw_callback_set(view_port, render_callback, game_state);
     view_port_input_callback_set(view_port, input_callback, event_queue);
 
-    FuriTimer* timer = furi_timer_alloc(update_timer_callback, FuriTimerTypePeriodic, event_queue);
+    FuriTimer *timer =
+            furi_timer_alloc(update_timer_callback, FuriTimerTypePeriodic, event_queue);
     furi_timer_start(timer, furi_kernel_get_tick_frequency() / 30);
 
-    Gui* gui = furi_record_open(RECORD_GUI);
+    Gui *gui = furi_record_open("gui");
     gui_add_view_port(gui, view_port, GuiLayerFullscreen);
 
     AppEvent event;
-
-    // Call Dolphin deed on game start
-    dolphin_deed(DolphinDeedPluginGameStart);
-
-    for(bool processing = true; processing;) {
+    for (bool processing = true; processing;) {
         FuriStatus event_status = furi_message_queue_get(event_queue, &event, 150);
         furi_mutex_acquire(game_state->mutex, FuriWaitForever);
-        if(event_status == FuriStatusOk) {
-            if(event.type == EventTypeKey) {
-                if(event.input.type == InputTypeLong) {
+        game_state->had_change = false;
+        if (event_status == FuriStatusOk) {
+            if (event.type == EventTypeKey) {
+                game_state->had_change = true;
+                if (event.input.type == InputTypeLong) {
                     game_state->longPress = true;
-                    switch(event.input.key) {
-                    case InputKeyUp:
-                    case InputKeyDown:
-                    case InputKeyRight:
-                    case InputKeyLeft:
-                    case InputKeyOk:
-                        game_state->input = event.input.key;
-                        break;
-                    case InputKeyBack:
-                        processing = false;
-                        return_code = 1;
-                    default:
-                        break;
+                    switch (event.input.key) {
+                        case InputKeyUp:
+                        case InputKeyDown:
+                        case InputKeyRight:
+                        case InputKeyLeft:
+                        case InputKeyOk:
+                            game_state->input = event.input.key;
+                            break;
+                        case InputKeyBack:
+                            processing = false;
+                            return_code = 1;
+                        default:
+                            break;
                     }
-                } else if(event.input.type == InputTypePress) {
+                } else if (event.input.type == InputTypePress) {
                     game_state->longPress = false;
-                    switch(event.input.key) {
-                    case InputKeyUp:
-                    case InputKeyDown:
-                    case InputKeyRight:
-                    case InputKeyLeft:
-                    case InputKeyOk:
-                        if(event.input.key == InputKeyOk && game_state->state == GameStateStart) {
-                            game_state->state = GameStatePlay;
+                    switch (event.input.key) {
+                        case InputKeyUp:
+                        case InputKeyDown:
+                        case InputKeyRight:
+                        case InputKeyLeft:
+                        case InputKeyOk:
+                            if (event.input.key == InputKeyOk && game_state->state == GameStateStart) {
+                                game_state->state = GameStatePlay;
+                                init(game_state);
+                            }
+                            else {
+                                game_state->input = event.input.key;
+                            }
+                            break;
+                        case InputKeyBack:
                             init(game_state);
-                        } else {
-                            game_state->input = event.input.key;
-                        }
-                        break;
-                    case InputKeyBack:
-                        init(game_state);
-                        processing = false;
-                        return_code = 1;
-                        break;
-                    default:
-                        break;
+                            processing = false;
+                            return_code = 1;
+                            break;
+                        default:
+                            break;
                     }
                 }
-            } else if(event.type == EventTypeTick) {
+            } else if (event.type == EventTypeTick) {
                 tick(game_state, notification);
                 processing = game_state->processing;
                 game_state->input = InputKeyMAX;
             }
         }
+
         view_port_update(view_port);
         furi_mutex_release(game_state->mutex);
     }
 
+
     notification_message_block(notification, &sequence_display_backlight_enforce_auto);
     furi_timer_free(timer);
     view_port_enabled_set(view_port, false);
@@ -558,13 +548,15 @@ int32_t solitaire_app(void* p) {
     view_port_free(view_port);
     furi_mutex_free(game_state->mutex);
 
-free_and_exit:
+    free_and_exit:
     free(game_state->animation.buffer);
     ui_cleanup();
-    for(uint8_t i = 0; i < 7; i++) free_hand(&(game_state->bottom_columns[i]));
+    for (uint8_t i = 0; i < 7; i++)
+        free_hand(&(game_state->bottom_columns[i]));
 
     free(game_state->deck.cards);
     free(game_state);
     furi_message_queue_free(event_queue);
+
     return return_code;
 }