Chess Engine
C++ chess engine with movegen, bitboards, and Arduino-friendly docs
Loading...
Searching...
No Matches
move_generator.cpp
Go to the documentation of this file.
1#include <iostream>
2#include "move_generator.h"
3#include "make_move.h"
4#include "../util/attack.h"
5#include "../util/setup.h"
6
7const int LoopSlidePce[8] = { wB, wR, wQ, 0, bB, bR, bQ, 0 };
8const int LoopNonSlidePce[6] = { wN, wK, 0, bN, bK, 0 };
9const int LoopSlideIndex[2] = { 0, 4 };
10const int LoopNonSlideIndex[2]= { 0, 3 };
11
12const int pieceDirection[13][8] = {
13 { 0, 0, 0, 0, 0, 0, 0 },
14 { 0, 0, 0, 0, 0, 0, 0 },
15 { -8, -19, -21, -12, 8, 19, 21, 12 },
16 { -9, -11, 11, 9, 0, 0, 0, 0 },
17 { -1, -10, 1, 10, 0, 0, 0, 0 },
18 { -1, -10, 1, 10, -9, -11, 11, 9 },
19 { -1, -10, 1, 10, -9, -11, 11, 9 },
20 { 0, 0, 0, 0, 0, 0, 0 },
21 { -8, -19, -21, -12, 8, 19, 21, 12 },
22 { -9, -11, 11, 9, 0, 0, 0, 0 },
23 { -1, -10, 1, 10, 0, 0, 0, 0 },
24 { -1, -10, 1, 10, -9, -11, 11, 9 },
25 { -1, -10, 1, 10, -9, -11, 11, 9 }
26};
27
28const int numberDirections[13] = { 0, 0, 8, 4, 4, 8, 8, 0, 8, 4, 4, 8, 8 };
29
30const int VictimScore[13] = { 0,100,200,300,400,500,600,100,200,300,400,500,600 };
31static int MvvLvaScores[13][13];
32
33// ---- helpers (local linkage, C++-style params/locals) ----
34static void AddQuietMove(const S_BOARD* board, int move, S_MOVELIST* moveList) {
35 ASSERT(SqOnBoard(FROMSQ(move)));
36 ASSERT(SqOnBoard(TOSQ(move)));
38 ASSERT(board->ply >= 0 && board->ply < MAXDEPTH);
39
40 auto& slot = moveList->moves[moveList->count];
41 slot.move = move;
42
43 if (board->searchKillers[0][board->ply] == move) {
44 slot.score = 900000;
45 } else if (board->searchKillers[1][board->ply] == move) {
46 slot.score = 800000;
47 } else {
48 slot.score = board->searchHistory[board->pieces[FROMSQ(move)]][TOSQ(move)];
49 }
50 moveList->count++;
51}
52
53static void AddCaptureMove(const S_BOARD* board, int move, S_MOVELIST* moveList) {
54 ASSERT(SqOnBoard(FROMSQ(move)));
55 ASSERT(SqOnBoard(TOSQ(move)));
58
59 auto& slot = moveList->moves[moveList->count];
60 slot.move = move;
61 slot.score = MvvLvaScores[CAPTURED(move)][board->pieces[FROMSQ(move)]] + 1000000;
62 moveList->count++;
63}
64
65static void AddEnPassantMove(const S_BOARD* board, int move, S_MOVELIST* moveList) {
66 ASSERT(SqOnBoard(FROMSQ(move)));
67 ASSERT(SqOnBoard(TOSQ(move)));
69 ASSERT((rankIndex120[TOSQ(move)] == RANK_6 && board->side == WHITE) ||
70 (rankIndex120[TOSQ(move)] == RANK_3 && board->side == BLACK));
71
72 auto& slot = moveList->moves[moveList->count];
73 slot.move = move;
74 slot.score = 105 + 1000000;
75 moveList->count++;
76}
77
78static void AddWhitePawnCapMove(const S_BOARD* board, int fromSq, int toSq, int captured, S_MOVELIST* moveList) {
79 ASSERT(pieceValueidEmpty(captured));
80 ASSERT(SqOnBoard(fromSq));
81 ASSERT(SqOnBoard(toSq));
83
84 if (rankIndex120[fromSq] == RANK_7) {
85 AddCaptureMove(board, MOVE(fromSq, toSq, captured, wQ, 0), moveList);
86 AddCaptureMove(board, MOVE(fromSq, toSq, captured, wR, 0), moveList);
87 AddCaptureMove(board, MOVE(fromSq, toSq, captured, wB, 0), moveList);
88 AddCaptureMove(board, MOVE(fromSq, toSq, captured, wN, 0), moveList);
89 } else {
90 AddCaptureMove(board, MOVE(fromSq, toSq, captured, EMPTY, 0), moveList);
91 }
92}
93
94static void AddWhitePawnMove(const S_BOARD* board, int fromSq, int toSq, S_MOVELIST* moveList) {
95 ASSERT(SqOnBoard(fromSq));
96 ASSERT(SqOnBoard(toSq));
98
99 if (rankIndex120[fromSq] == RANK_7) {
100 AddQuietMove(board, MOVE(fromSq, toSq, EMPTY, wQ, 0), moveList);
101 AddQuietMove(board, MOVE(fromSq, toSq, EMPTY, wR, 0), moveList);
102 AddQuietMove(board, MOVE(fromSq, toSq, EMPTY, wB, 0), moveList);
103 AddQuietMove(board, MOVE(fromSq, toSq, EMPTY, wN, 0), moveList);
104 } else {
105 AddQuietMove(board, MOVE(fromSq, toSq, EMPTY, EMPTY, 0), moveList);
106 }
107}
108
109static void AddBlackPawnCapMove(const S_BOARD* board, int fromSq, int toSq, int captured, S_MOVELIST* moveList) {
110 ASSERT(pieceValueidEmpty(captured));
111 ASSERT(SqOnBoard(fromSq));
112 ASSERT(SqOnBoard(toSq));
114
115 if (rankIndex120[fromSq] == RANK_2) {
116 AddCaptureMove(board, MOVE(fromSq, toSq, captured, bQ, 0), moveList);
117 AddCaptureMove(board, MOVE(fromSq, toSq, captured, bR, 0), moveList);
118 AddCaptureMove(board, MOVE(fromSq, toSq, captured, bB, 0), moveList);
119 AddCaptureMove(board, MOVE(fromSq, toSq, captured, bN, 0), moveList);
120 } else {
121 AddCaptureMove(board, MOVE(fromSq, toSq, captured, EMPTY, 0), moveList);
122 }
123}
124
125static void AddBlackPawnMove(const S_BOARD* board, int fromSq, int toSq, S_MOVELIST* moveList) {
126 ASSERT(SqOnBoard(fromSq));
127 ASSERT(SqOnBoard(toSq));
129
130 if (rankIndex120[fromSq] == RANK_2) {
131 AddQuietMove(board, MOVE(fromSq, toSq, EMPTY, bQ, 0), moveList);
132 AddQuietMove(board, MOVE(fromSq, toSq, EMPTY, bR, 0), moveList);
133 AddQuietMove(board, MOVE(fromSq, toSq, EMPTY, bB, 0), moveList);
134 AddQuietMove(board, MOVE(fromSq, toSq, EMPTY, bN, 0), moveList);
135 } else {
136 AddQuietMove(board, MOVE(fromSq, toSq, EMPTY, EMPTY, 0), moveList);
137 }
138}
139
140// ---- public API (same behavior, C++ locals/loops/names) ----
142 for (int attacker = wP; attacker <= bK; ++attacker) {
143 for (int victim = wP; victim <= bK; ++victim) {
144 MvvLvaScores[victim][attacker] = VictimScore[victim] + 6 - (VictimScore[attacker] / 100);
145 }
146 }
147}
148
149int moveExists(S_BOARD* board, const int move) {
150 S_MOVELIST moveList[1];
151 generateAllMoves(board, moveList);
152
153 for (int i = 0; i < moveList->count; ++i) {
154 if (!makeMove(board, moveList->moves[i].move)) {
155 continue;
156 }
157 takeMove(board);
158 if (moveList->moves[i].move == move) {
159 return TRUE;
160 }
161 }
162 return FALSE;
163}
164
165void generateAllMoves(const S_BOARD* board, S_MOVELIST* moveList) {
167 moveList->count = 0;
168
169 const int side = board->side;
170
171 if (side == WHITE) {
172 for (int pi = 0; pi < board->pceNum[wP]; ++pi) {
173 const int fromSq = board->pList[wP][pi];
174 ASSERT(SqOnBoard(fromSq));
175
176 if (board->pieces[fromSq + 10] == EMPTY) {
177 AddWhitePawnMove(board, fromSq, fromSq + 10, moveList);
178 if (rankIndex120[fromSq] == RANK_2 && board->pieces[fromSq + 20] == EMPTY) {
179 AddQuietMove(board, MOVE(fromSq, fromSq + 20, EMPTY, EMPTY, MFLAGPS), moveList);
180 }
181 }
182 if (!SQOFFBOARD(fromSq + 9) && pieceColor[board->pieces[fromSq + 9]] == BLACK) {
183 AddWhitePawnCapMove(board, fromSq, fromSq + 9, board->pieces[fromSq + 9], moveList);
184 }
185 if (!SQOFFBOARD(fromSq + 11) && pieceColor[board->pieces[fromSq + 11]] == BLACK) {
186 AddWhitePawnCapMove(board, fromSq, fromSq + 11, board->pieces[fromSq + 11], moveList);
187 }
188
189 if (board->enPas != NO_SQ) {
190 if (fromSq + 9 == board->enPas) AddEnPassantMove(board, MOVE(fromSq, fromSq + 9, EMPTY, EMPTY, MFLAGEP), moveList);
191 if (fromSq + 11 == board->enPas) AddEnPassantMove(board, MOVE(fromSq, fromSq + 11, EMPTY, EMPTY, MFLAGEP), moveList);
192 }
193 }
194
195 if (board->castlePerm & WKCA) {
196 if (board->pieces[F1] == EMPTY && board->pieces[G1] == EMPTY) {
197 if (!isSquareAttacked(E1, BLACK, board) && !isSquareAttacked(F1, BLACK, board)) {
198 AddQuietMove(board, MOVE(E1, G1, EMPTY, EMPTY, MFLAGCA), moveList);
199 }
200 }
201 }
202 if (board->castlePerm & WQCA) {
203 if (board->pieces[D1] == EMPTY && board->pieces[C1] == EMPTY && board->pieces[B1] == EMPTY) {
204 if (!isSquareAttacked(E1, BLACK, board) && !isSquareAttacked(D1, BLACK, board)) {
205 AddQuietMove(board, MOVE(E1, C1, EMPTY, EMPTY, MFLAGCA), moveList);
206 }
207 }
208 }
209 } else {
210 for (int pi = 0; pi < board->pceNum[bP]; ++pi) {
211 const int fromSq = board->pList[bP][pi];
212 ASSERT(SqOnBoard(fromSq));
213
214 if (board->pieces[fromSq - 10] == EMPTY) {
215 AddBlackPawnMove(board, fromSq, fromSq - 10, moveList);
216 if (rankIndex120[fromSq] == RANK_7 && board->pieces[fromSq - 20] == EMPTY) {
217 AddQuietMove(board, MOVE(fromSq, fromSq - 20, EMPTY, EMPTY, MFLAGPS), moveList);
218 }
219 }
220 if (!SQOFFBOARD(fromSq - 9) && pieceColor[board->pieces[fromSq - 9]] == WHITE) {
221 AddBlackPawnCapMove(board, fromSq, fromSq - 9, board->pieces[fromSq - 9], moveList);
222 }
223 if (!SQOFFBOARD(fromSq - 11) && pieceColor[board->pieces[fromSq - 11]] == WHITE) {
224 AddBlackPawnCapMove(board, fromSq, fromSq - 11, board->pieces[fromSq - 11], moveList);
225 }
226
227 if (board->enPas != NO_SQ) {
228 if (fromSq - 9 == board->enPas) AddEnPassantMove(board, MOVE(fromSq, fromSq - 9, EMPTY, EMPTY, MFLAGEP), moveList);
229 if (fromSq - 11 == board->enPas) AddEnPassantMove(board, MOVE(fromSq, fromSq - 11, EMPTY, EMPTY, MFLAGEP), moveList);
230 }
231 }
232
233 if (board->castlePerm & BKCA) {
234 if (board->pieces[F8] == EMPTY && board->pieces[G8] == EMPTY) {
235 if (!isSquareAttacked(E8, WHITE, board) && !isSquareAttacked(F8, WHITE, board)) {
236 AddQuietMove(board, MOVE(E8, G8, EMPTY, EMPTY, MFLAGCA), moveList);
237 }
238 }
239 }
240 if (board->castlePerm & BQCA) {
241 if (board->pieces[D8] == EMPTY && board->pieces[C8] == EMPTY && board->pieces[B8] == EMPTY) {
242 if (!isSquareAttacked(E8, WHITE, board) && !isSquareAttacked(D8, WHITE, board)) {
243 AddQuietMove(board, MOVE(E8, C8, EMPTY, EMPTY, MFLAGCA), moveList);
244 }
245 }
246 }
247 }
248
249 // sliding pieces
250 for (int pIndex = LoopSlideIndex[side], piece = LoopSlidePce[pIndex++]; piece != 0; piece = LoopSlidePce[pIndex++]) {
251 ASSERT(pieceValueid(piece));
252 for (int pi = 0; pi < board->pceNum[piece]; ++pi) {
253 const int fromSq = board->pList[piece][pi];
254 ASSERT(SqOnBoard(fromSq));
255
256 for (int d = 0; d < numberDirections[piece]; ++d) {
257 const int delta = pieceDirection[piece][d];
258 int targetSq = fromSq + delta;
259
260 while (!SQOFFBOARD(targetSq)) {
261 if (board->pieces[targetSq] != EMPTY) {
262 if (pieceColor[board->pieces[targetSq]] == (side ^ 1)) {
263 AddCaptureMove(board, MOVE(fromSq, targetSq, board->pieces[targetSq], EMPTY, 0), moveList);
264 }
265 break;
266 }
267 AddQuietMove(board, MOVE(fromSq, targetSq, EMPTY, EMPTY, 0), moveList);
268 targetSq += delta;
269 }
270 }
271 }
272 }
273
274 // non-sliding pieces
275 for (int pIndex = LoopNonSlideIndex[side], piece = LoopNonSlidePce[pIndex++]; piece != 0; piece = LoopNonSlidePce[pIndex++]) {
276 ASSERT(pieceValueid(piece));
277 for (int pi = 0; pi < board->pceNum[piece]; ++pi) {
278 const int fromSq = board->pList[piece][pi];
279 ASSERT(SqOnBoard(fromSq));
280
281 for (int d = 0; d < numberDirections[piece]; ++d) {
282 const int targetSq = fromSq + pieceDirection[piece][d];
283 if (SQOFFBOARD(targetSq)) continue;
284
285 if (board->pieces[targetSq] != EMPTY) {
286 if (pieceColor[board->pieces[targetSq]] == (side ^ 1)) {
287 AddCaptureMove(board, MOVE(fromSq, targetSq, board->pieces[targetSq], EMPTY, 0), moveList);
288 }
289 continue;
290 }
291 AddQuietMove(board, MOVE(fromSq, targetSq, EMPTY, EMPTY, 0), moveList);
292 }
293 }
294 }
295
296 ASSERT(MoveListOk(moveList, board));
297}
298
299void generateAllCaptures(const S_BOARD* board, S_MOVELIST* moveList) {
301 moveList->count = 0;
302
303 const int side = board->side;
304
305 if (side == WHITE) {
306 for (int pi = 0; pi < board->pceNum[wP]; ++pi) {
307 const int fromSq = board->pList[wP][pi];
308 ASSERT(SqOnBoard(fromSq));
309
310 if (!SQOFFBOARD(fromSq + 9) && pieceColor[board->pieces[fromSq + 9]] == BLACK)
311 AddWhitePawnCapMove(board, fromSq, fromSq + 9, board->pieces[fromSq + 9], moveList);
312 if (!SQOFFBOARD(fromSq + 11) && pieceColor[board->pieces[fromSq + 11]] == BLACK)
313 AddWhitePawnCapMove(board, fromSq, fromSq + 11, board->pieces[fromSq + 11], moveList);
314
315 if (board->enPas != NO_SQ) {
316 if (fromSq + 9 == board->enPas) AddEnPassantMove(board, MOVE(fromSq, fromSq + 9, EMPTY, EMPTY, MFLAGEP), moveList);
317 if (fromSq + 11 == board->enPas) AddEnPassantMove(board, MOVE(fromSq, fromSq + 11, EMPTY, EMPTY, MFLAGEP), moveList);
318 }
319 }
320 } else {
321 for (int pi = 0; pi < board->pceNum[bP]; ++pi) {
322 const int fromSq = board->pList[bP][pi];
323 ASSERT(SqOnBoard(fromSq));
324
325 if (!SQOFFBOARD(fromSq - 9) && pieceColor[board->pieces[fromSq - 9]] == WHITE)
326 AddBlackPawnCapMove(board, fromSq, fromSq - 9, board->pieces[fromSq - 9], moveList);
327 if (!SQOFFBOARD(fromSq - 11) && pieceColor[board->pieces[fromSq - 11]] == WHITE)
328 AddBlackPawnCapMove(board, fromSq, fromSq - 11, board->pieces[fromSq - 11], moveList);
329
330 if (board->enPas != NO_SQ) {
331 if (fromSq - 9 == board->enPas) AddEnPassantMove(board, MOVE(fromSq, fromSq - 9, EMPTY, EMPTY, MFLAGEP), moveList);
332 if (fromSq - 11 == board->enPas) AddEnPassantMove(board, MOVE(fromSq, fromSq - 11, EMPTY, EMPTY, MFLAGEP), moveList);
333 }
334 }
335 }
336
337 // sliding captures only
338 for (int pIndex = LoopSlideIndex[side], piece = LoopSlidePce[pIndex++]; piece != 0; piece = LoopSlidePce[pIndex++]) {
339 ASSERT(pieceValueid(piece));
340 for (int pi = 0; pi < board->pceNum[piece]; ++pi) {
341 const int fromSq = board->pList[piece][pi];
342 ASSERT(SqOnBoard(fromSq));
343
344 for (int d = 0; d < numberDirections[piece]; ++d) {
345 const int delta = pieceDirection[piece][d];
346 int targetSq = fromSq + delta;
347
348 while (!SQOFFBOARD(targetSq)) {
349 if (board->pieces[targetSq] != EMPTY) {
350 if (pieceColor[board->pieces[targetSq]] == (side ^ 1)) {
351 AddCaptureMove(board, MOVE(fromSq, targetSq, board->pieces[targetSq], EMPTY, 0), moveList);
352 }
353 break;
354 }
355 targetSq += delta;
356 }
357 }
358 }
359 }
360
361 // non-sliding captures only
362 for (int pIndex = LoopNonSlideIndex[side], piece = LoopNonSlidePce[pIndex++]; piece != 0; piece = LoopNonSlidePce[pIndex++]) {
363 ASSERT(pieceValueid(piece));
364 for (int pi = 0; pi < board->pceNum[piece]; ++pi) {
365 const int fromSq = board->pList[piece][pi];
366 ASSERT(SqOnBoard(fromSq));
367
368 for (int d = 0; d < numberDirections[piece]; ++d) {
369 const int targetSq = fromSq + pieceDirection[piece][d];
370 if (SQOFFBOARD(targetSq)) continue;
371
372 if (board->pieces[targetSq] != EMPTY &&
373 pieceColor[board->pieces[targetSq]] == (side ^ 1)) {
374 AddCaptureMove(board, MOVE(fromSq, targetSq, board->pieces[targetSq], EMPTY, 0), moveList);
375 }
376 }
377 }
378 }
379
380 ASSERT(MoveListOk(moveList, board));
381}
bool isSquareAttacked(const int square, const int side, const S_BOARD *pos)
Determines if a given square is attacked by a given side.
Definition attack.cpp:9
bool isBoardStateValid(const S_BOARD *pos)
Performs a full internal consistency check of the board state.
Definition board.cpp:28
int pieceColor[13]
Color of each piece type.
#define MAXDEPTH
Definition defs.h:33
#define TOSQ(m)
Definition defs.h:165
@ bQ
Definition defs.h:40
@ wN
Definition defs.h:40
@ EMPTY
Definition defs.h:40
@ bN
Definition defs.h:40
@ wR
Definition defs.h:40
@ bP
Definition defs.h:40
@ bR
Definition defs.h:40
@ bB
Definition defs.h:40
@ wB
Definition defs.h:40
@ bK
Definition defs.h:40
@ wP
Definition defs.h:40
@ wK
Definition defs.h:40
@ wQ
Definition defs.h:40
@ WHITE
Definition defs.h:44
@ BLACK
Definition defs.h:44
#define CAPTURED(m)
Definition defs.h:166
#define MFLAGCA
Definition defs.h:171
#define MFLAGEP
Definition defs.h:169
@ WQCA
Definition defs.h:59
@ BQCA
Definition defs.h:59
@ WKCA
Definition defs.h:59
@ BKCA
Definition defs.h:59
@ RANK_7
Definition defs.h:42
@ RANK_6
Definition defs.h:42
@ RANK_3
Definition defs.h:42
@ RANK_2
Definition defs.h:42
#define MFLAGPS
Definition defs.h:170
#define FROMSQ(m)
Definition defs.h:164
#define ASSERT(n)
Definition defs.h:14
@ E8
Definition defs.h:54
@ D1
Definition defs.h:47
@ B8
Definition defs.h:54
@ F1
Definition defs.h:47
@ C8
Definition defs.h:54
@ NO_SQ
Definition defs.h:54
@ G8
Definition defs.h:54
@ G1
Definition defs.h:47
@ E1
Definition defs.h:47
@ F8
Definition defs.h:54
@ B1
Definition defs.h:47
@ C1
Definition defs.h:47
@ D8
Definition defs.h:54
@ FALSE
Definition defs.h:57
@ TRUE
Definition defs.h:57
int makeMove(S_BOARD *board, int move)
Make a move; returns non-zero if legal (king not left in check).
void takeMove(S_BOARD *board)
Undo the last made move.
const int VictimScore[13]
Victim scoring table for MVV-LVA.
static void AddEnPassantMove(const S_BOARD *board, int move, S_MOVELIST *moveList)
static void AddBlackPawnCapMove(const S_BOARD *board, int fromSq, int toSq, int captured, S_MOVELIST *moveList)
void InitMvvLva()
Initialize the MVV-LVA capture scoring table.
static void AddQuietMove(const S_BOARD *board, int move, S_MOVELIST *moveList)
void generateAllMoves(const S_BOARD *board, S_MOVELIST *moveList)
Generate all pseudo-legal moves for the side to move.
int moveExists(S_BOARD *board, const int move)
Check if a given move exists in the current position.
const int pieceDirection[13][8]
Direction offsets for each piece type.
static void AddBlackPawnMove(const S_BOARD *board, int fromSq, int toSq, S_MOVELIST *moveList)
static void AddWhitePawnMove(const S_BOARD *board, int fromSq, int toSq, S_MOVELIST *moveList)
static int MvvLvaScores[13][13]
const int LoopNonSlideIndex[2]
Indices into LoopNonSlidePce for white and black.
const int LoopNonSlidePce[6]
Non-sliding piece loop order for move generation.
static void AddWhitePawnCapMove(const S_BOARD *board, int fromSq, int toSq, int captured, S_MOVELIST *moveList)
const int numberDirections[13]
Number of valid directions for each piece type.
const int LoopSlidePce[8]
Sliding piece loop order for move generation.
static void AddCaptureMove(const S_BOARD *board, int move, S_MOVELIST *moveList)
void generateAllCaptures(const S_BOARD *board, S_MOVELIST *moveList)
Generate all pseudo-legal capture moves (including en passant).
const int LoopSlideIndex[2]
Indices into LoopSlidePce for white and black.
#define SQOFFBOARD(sq)
Macro to check if a square index is off the board.
#define MOVE(f, t, ca, pro, fl)
Macro to encode a move into an integer.
int rankIndex120[BRD_SQ_NUM]
Definition setup.cpp:27
int pList[13][10]
Definition defs.h:127
int pieces[BRD_SQ_NUM]
Definition defs.h:102
int castlePerm
Definition defs.h:114
int pceNum[13]
Definition defs.h:118
int enPas
Definition defs.h:108
int side
Definition defs.h:107
int searchKillers[2][MAXDEPTH]
Definition defs.h:133
int ply
Definition defs.h:111
int searchHistory[13][BRD_SQ_NUM]
Definition defs.h:132
int move
Definition defs.h:62
int count
Definition defs.h:68
S_MOVE moves[MAXPOSITIONMOVES]
Definition defs.h:67
int MoveListOk(const S_MOVELIST *moves, const S_BOARD *board)
Validates that a move list is within bounds and references valid moves.
Definition validate.cpp:7
int pieceValueidEmpty(const int pce)
Checks if the given piece code is either empty or a valid piece.
Definition validate.cpp:42
int pieceValueid(const int pce)
Checks if the given piece code is a valid piece (non-empty).
Definition validate.cpp:46
int SqOnBoard(const int sq)
Checks if a given square index refers to a valid on-board square.
Definition validate.cpp:29