]> git.draconx.ca Git - rrace.git/blobdiff - src/game.c
Check victory condition so the game is winnable.
[rrace.git] / src / game.c
index bd1fef98eb5e209d2797868524857743ce99eb30..ca03830545b7ee76392ce3087b66e8da9c417883 100644 (file)
@@ -1,8 +1,25 @@
 /*
+ * Slide puzzle core game logic
+ * Copyright © 2022 Nick Bowler
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
  * The RNG implementation is adapted from xoshiro256** and splitmix64
  * by David Blackman and Sebastiano Vigna, originally distributed under
  * the Creative Commons Zero public domain dedication.
  */
+
 #include <config.h>
 #include <limits.h>
 #include <string.h>
@@ -136,17 +153,17 @@ void game_reset(struct board *board)
                uint_fast32_t position;
 
                position = board_position(x, y);
-               if (tiles[i] == TILE_EMPTY) {
-                       board->game[0] = 0x1ffffff ^ position;
-                       board->x = x;
-                       board->y = y;
-               } else {
+               if (tiles[i] != TILE_EMPTY) {
                        if (tiles[i] & 1)
-                               board->game[1] |= position;
+                               board->game[0] |= position;
                        if (tiles[i] & 2)
-                               board->game[2] |= position;
+                               board->game[1] |= position;
                        if (tiles[i] & 4)
-                               board->game[3] |= position;
+                               board->game[2] |= position;
+               } else {
+                       board->game[3] = 0x1ffffff ^ position;
+                       board->x = x;
+                       board->y = y;
                }
        }
 }
@@ -179,3 +196,29 @@ int game_do_move(struct board *board, int x, int y)
        board->y = y;
        return 0;
 }
+
+#define GOAL_MASK 0x739c0
+
+int game_check_goal(struct board *board)
+{
+       int i, ret = 1;
+
+       for (i = 0; i < 3; i++)
+               ret &= ((board->game[i] & GOAL_MASK) >> 6) == board->goal[i];
+       return ret;
+}
+
+void game_finish(struct board *board)
+{
+       int i;
+
+       for (i = 0; i < 4; i++) {
+               board->game[i] &= GOAL_MASK;
+       }
+
+       /*
+        * Setting both x and y hole location to a bogus value will effectively
+        * disable the game since there will be no valid moves.
+        */
+       board->x = board->y = -1;
+}