]> git.draconx.ca Git - rrace.git/blob - src/game.h
958cc60f94168489d966fc5ff21466d93c7ff2df
[rrace.git] / src / game.h
1 /*
2  * Slide puzzle core game logic
3  * Copyright © 2022 Nick Bowler
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
17  */
18
19 #ifndef RRACE_GAME_H_
20 #define RRACE_GAME_H_
21
22 #include <inttypes.h>
23 #include <xtime.h>
24
25 enum {
26         TILE_EMPTY,
27         TILE_RED,
28         TILE_ORANGE,
29         TILE_YELLOW,
30         TILE_GREEN,
31         TILE_BLUE,
32         TILE_WHITE,
33         TILE_MAX
34 };
35
36 #define GOAL_SHIFT 6
37 #define GOAL_MASK 0x739c0ul
38
39 struct board {
40         /*
41          * Bit planes representing the current game area.
42          *
43          * The 5x5 game board is represented by these four 25-bit values.
44          * The bits are arranged in row-major order so, for example, bit 0
45          * corresponds to position (0,0), bit 4 is position (4,0) and bit 25
46          * is position (4, 4).
47          *
48          *   game[0] - least significant bit of the tile's colour.
49          *   game[1] - tile colour.
50          *   game[2] - most significant bit of the tile's colour.
51          *   game[3] - No internal meaning.  The game_reset function will clear
52          *             the bit at the empty position and set all others, and
53          *             game_do_move will adjust it.
54          */
55         uint_least32_t game[4];
56
57         /*
58          * Bit planes representing the goal area.
59          *
60          * These are encoded identically to the game area, except the values
61          * are shifted right by 6 as only bits 6 through 18 are relevant.
62          *
63          *   goal[0] - least significant bit of the tile's colour.
64          *   goal[2] - tile colour.
65          *   goal[3] - most significant bit of the tile's colour.
66          */
67         uint_least16_t goal[3];
68
69         /* (x, y) position of the current empty space. */
70         uint_least8_t x, y;
71
72         xtime_t time_start;
73 };
74
75 /* Return the board bitmap with all bits in column x set */
76 static inline uint_fast32_t board_column(int x)
77 {
78         return 0x108421ul << x;
79 }
80
81 /* Return the board bitmap with all bits in row y set */
82 static inline uint_fast32_t board_row(int y)
83 {
84         return 0x1ful << 5*y;
85 }
86
87 /* Return the board bitmap with the bit at position (x, y) set. */
88 static inline uint_fast32_t board_position(int x, int y)
89 {
90         return 1ul << x << 5*y;
91 }
92
93 /*
94  * Return the board bitmap with set bits indicating tile locations
95  * that change with the hole at (x0, y) and the play at (x1, y).
96  */
97 static inline uint_fast32_t board_mask_h(int y, int x0, int x1)
98 {
99         uint_fast32_t row = board_row(y);
100
101         if (x0 < x1)
102                 return (row << x0) & (row >> (4-x1));
103         return (row << x1) & (row >> (4-x0));
104 }
105
106 /*
107  * Return the board bitmap with set bits indicating tile locations
108  * that change with the hole at (x, y0) and the play at (x, y1).
109  */
110 static inline uint_fast32_t board_mask_v(int x, int y0, int y1)
111 {
112         uint_fast32_t col = board_column(x);
113
114         if (y0 < y1)
115                 return (col << 5*y0) & (col >> 5*(4-y1));
116         return (col << 5*y1) & (col >> 5*(4-y0));
117 }
118
119 /*
120  * Return the board bitmap setting locations on or above row y.
121  */
122 static inline uint_fast32_t board_above(int y)
123 {
124         uint_fast32_t val = board_row(y);
125
126         return val | (val-1);
127 }
128
129 /*
130  * Return the board bitmap setting locations on or below row y.
131  */
132 static inline uint_fast32_t board_below(int y)
133 {
134         uint_fast32_t val = board_row(y);
135
136         return val | (~val + 1);
137 }
138
139 /*
140  * Return the board bitmap setting locations on or left of column x.
141  */
142 static inline uint_fast32_t board_left(int x)
143 {
144         uint_fast32_t val = board_column(x);
145
146         return val | (val - 0x108421);
147 }
148
149 /*
150  * Return the board bitmap setting locations on or right of column x.
151  */
152 static inline uint_fast32_t board_right(int x)
153 {
154         uint_fast32_t val = board_column(x);
155
156         return ~val + 0x108421;
157 }
158
159 /*
160  * Move the bits in the game bitmaps according to a move at position (x, y),
161  * and update the location of the empty position which, if the move was valid
162  * is now (x, y).
163  *
164  * Returns the board bitmap indicating which positions changed.  A return
165  * value of 0 therefore indicates an invalid move.
166  */
167 uint_fast32_t game_do_move(struct board *board, int x, int y);
168
169 /*
170  * Returns the board bitmap setting game locations that differ from the goal.
171  * A return value of 0 therefore indicates a winning position.
172  */
173 uint_fast32_t game_check_goal(struct board *board);
174
175 /*
176  * Initialize the game RNG such that the next call to game_reset will produce a
177  * new board that is entirely dependent on the given seed value.
178  */
179 void game_reseed(unsigned long long seed);
180
181 /*
182  * Shuffle the game and goal tiles to produce a new game state.
183  */
184 void game_reset(struct board *board);
185
186 /*
187  * Reset the game start time.
188  */
189 void game_begin(struct board *board);
190
191 /*
192  * Return the total elapsed time (in ms) since the last call to game_begin.
193  */
194 int_fast32_t game_elapsed(struct board *board);
195
196 /*
197  * Disable new moves and clear all tile bits other than the 9 goal tiles.
198  * Returns the total elapsed time (in ms).
199  */
200 int_fast32_t game_finish(struct board *board);
201
202 #endif