/* * 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 . */ #ifndef RRACE_GAME_H_ #define RRACE_GAME_H_ #include #include enum { TILE_EMPTY, TILE_RED, TILE_ORANGE, TILE_YELLOW, TILE_GREEN, TILE_BLUE, TILE_WHITE, TILE_MAX }; #define GOAL_SHIFT 6 #define GOAL_MASK 0x739c0ul struct board { /* * Bit planes representing the current game area. * * The 5x5 game board is represented by these four 25-bit values. * The bits are arranged in row-major order so, for example, bit 0 * corresponds to position (0,0), bit 4 is position (4,0) and bit 25 * is position (4, 4). * * game[0] - least significant bit of the tile's colour. * game[1] - tile colour. * game[2] - most significant bit of the tile's colour. * game[3] - No internal meaning. The game_reset function will clear * the bit at the empty position and set all others, and * game_do_move will adjust it. */ uint_least32_t game[4]; /* * Bit planes representing the goal area. * * These are encoded identically to the game area, except the values * are shifted right by 6 as only bits 6 through 18 are relevant. * * goal[0] - least significant bit of the tile's colour. * goal[2] - tile colour. * goal[3] - most significant bit of the tile's colour. */ uint_least16_t goal[3]; /* (x, y) position of the current empty space. */ uint_least8_t x, y; xtime_t time_start; }; /* Return the board bitmap with all bits in column x set */ static inline uint_fast32_t board_column(int x) { return 0x108421ul << x; } /* Return the board bitmap with all bits in row y set */ static inline uint_fast32_t board_row(int y) { return 0x1ful << 5*y; } /* Return the board bitmap with the bit at position (x, y) set. */ static inline uint_fast32_t board_position(int x, int y) { return 1ul << x << 5*y; } /* * Return the board bitmap with set bits indicating tile locations * that change with the hole at (x0, y) and the play at (x1, y). */ static inline uint_fast32_t board_mask_h(int y, int x0, int x1) { uint_fast32_t row = board_row(y); if (x0 < x1) return (row << x0) & (row >> (4-x1)); return (row << x1) & (row >> (4-x0)); } /* * Return the board bitmap with set bits indicating tile locations * that change with the hole at (x, y0) and the play at (x, y1). */ static inline uint_fast32_t board_mask_v(int x, int y0, int y1) { uint_fast32_t col = board_column(x); if (y0 < y1) return (col << 5*y0) & (col >> 5*(4-y1)); return (col << 5*y1) & (col >> 5*(4-y0)); } /* * Return the board bitmap setting locations on or above row y. */ static inline uint_fast32_t board_above(int y) { uint_fast32_t val = board_row(y); return val | (val-1); } /* * Return the board bitmap setting locations on or below row y. */ static inline uint_fast32_t board_below(int y) { uint_fast32_t val = board_row(y); return val | (~val + 1); } /* * Return the board bitmap setting locations on or left of column x. */ static inline uint_fast32_t board_left(int x) { uint_fast32_t val = board_column(x); return val | (val - 0x108421); } /* * Return the board bitmap setting locations on or right of column x. */ static inline uint_fast32_t board_right(int x) { uint_fast32_t val = board_column(x); return ~val + 0x108421; } /* * Move the bits in the game bitmaps according to a move at position (x, y), * and update the location of the empty position which, if the move was valid * is now (x, y). * * Returns the board bitmap indicating which positions changed. A return * value of 0 therefore indicates an invalid move. */ uint_fast32_t game_do_move(struct board *board, int x, int y); /* * Returns the board bitmap setting game locations that differ from the goal. * A return value of 0 therefore indicates a winning position. */ uint_fast32_t game_check_goal(struct board *board); /* * Initialize the game RNG such that the next call to game_reset will produce a * new board that is entirely dependent on the given seed value. */ void game_reseed(unsigned long long seed); /* * Shuffle the game and goal tiles to produce a new game state. */ void game_reset(struct board *board); /* * Reset the game start time. */ void game_begin(struct board *board); /* * Disable new moves and clear all tile bits other than the 9 goal tiles. * Returns the total elapsed time (in ms). */ int_fast32_t game_finish(struct board *board); #endif