]> git.draconx.ca Git - rrace.git/blob - src/game.h
Reduce the amount of redundant drawing in the game area.
[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
24 enum {
25         TILE_EMPTY,
26         TILE_RED,
27         TILE_ORANGE,
28         TILE_YELLOW,
29         TILE_GREEN,
30         TILE_BLUE,
31         TILE_WHITE,
32         TILE_MAX
33 };
34
35 enum { GOAL_SHIFT = 6 };
36 struct board {
37         /*
38          * Bit planes representing the current game area.
39          *
40          * The 5x5 game board is represented by these four 25-bit values.
41          * The bits are arranged in row-major order so, for example, bit 0
42          * corresponds to position (0,0), bit 4 is position (4,0) and bit 25
43          * is position (4, 4).
44          *
45          *   game[0] - least significant bit of the tile's colour.
46          *   game[1] - tile colour.
47          *   game[2] - most significant bit of the tile's colour.
48          *   game[3] - No internal meaning.  The game_reset function will clear
49          *             the bit at the empty position and set all others, and
50          *             game_do_move will adjust it.
51          */
52         uint_least32_t game[4];
53
54         /*
55          * Bit planes representing the goal area.
56          *
57          * These are encoded identically to the game area, except the values
58          * are shifted right by 6 as only bits 6 through 18 are relevant.
59          *
60          *   goal[0] - least significant bit of the tile's colour.
61          *   goal[2] - tile colour.
62          *   goal[3] - most significant bit of the tile's colour.
63          */
64         uint_least16_t goal[3];
65
66         /* (x, y) position of the current empty position. */
67         uint_least8_t x, y;
68 };
69
70 /* Return the board bitmap with all bits in column x set */
71 static inline uint_fast32_t board_column(int x)
72 {
73         return 0x108421ul << x;
74 }
75
76 /* Return the board bitmap with all bits in row y set */
77 static inline uint_fast32_t board_row(int y)
78 {
79         return 0x1ful << 5*y;
80 }
81
82 /* Return the board bitmap with the bit at position (x, y) set. */
83 static inline uint_fast32_t board_position(int x, int y)
84 {
85         return 1ul << x << 5*y;
86 }
87
88 /*
89  * Return the board bitmap with set bits indicating tile locations
90  * that change with the hole at (x0, y) and the play at (x1, y).
91  */
92 static inline uint_fast32_t board_mask_h(int y, int x0, int x1)
93 {
94         uint_fast32_t row = board_row(y);
95
96         if (x0 < x1)
97                 return (row << x0) & (row >> (4-x1));
98         return (row << x1) & (row >> (4-x0));
99 }
100
101 /*
102  * Return the board bitmap with set bits indicating tile locations
103  * that change with the hole at (x, y0) and the play at (x, y1).
104  */
105 static inline uint_fast32_t board_mask_v(int x, int y0, int y1)
106 {
107         uint_fast32_t col = board_column(x);
108
109         if (y0 < y1)
110                 return (col << 5*y0) & (col >> 5*(4-y1));
111         return (col << 5*y1) & (col >> 5*(4-y0));
112 }
113
114 /*
115  * Return the board bitmap setting locations on or above row y.
116  */
117 static inline uint_fast32_t board_above(int y)
118 {
119         uint_fast32_t val = board_row(y);
120
121         return val | (val-1);
122 }
123
124 /*
125  * Return the board bitmap setting locations on or below row y.
126  */
127 static inline uint_fast32_t board_below(int y)
128 {
129         uint_fast32_t val = board_row(y);
130
131         return val | (~val + 1);
132 }
133
134 /*
135  * Return the board bitmap setting locations on or left of column x.
136  */
137 static inline uint_fast32_t board_left(int x)
138 {
139         uint_fast32_t val = board_column(x);
140
141         return val | (val - 0x108421);
142 }
143
144 /*
145  * Return the board bitmap setting locations on or right of column x.
146  */
147 static inline uint_fast32_t board_right(int x)
148 {
149         uint_fast32_t val = board_column(x);
150
151         return ~val + 0x108421;
152 }
153
154 /*
155  * Move the bits in the game bitmaps according to a move at position (x, y),
156  * and update the location of the empty position which, if the move was valid
157  * is now (x, y).
158  *
159  * Returns 0 if the move was valid (and board has been updated), -1 otherwise.
160  */
161 int game_do_move(struct board *board, int x, int y);
162
163 /*
164  * Returns 1 if the game is in a winning position, or 0 otherwise.
165  */
166 int game_check_goal(struct board *board);
167
168 /*
169  * Initialize the game RNG such that the next call to game_reset will produce a
170  * new board that is entirely dependent on the given seed value.
171  */
172 void game_reseed(unsigned long long seed);
173
174 /*
175  * Shuffle the game and goal tiles to produce a new game state.
176  */
177 void game_reset(struct board *board);
178
179 /*
180  * Disable new moves and clear all tile bits other than the 9 goal tiles.
181  */
182 void game_finish(struct board *board);
183
184 #endif