Belofte version 2.2.0
A promising chess program using the UCI or Winboard interface
movelist.cpp
Go to the documentation of this file.
1/*---------------------------------------------------------------------+
2 * File: movelist.cpp
3 * Project: part of belofte - A Promising Chess Program
4 * Author: yves
5 * SPDX-License-Identifier: GPL-2.0-only
6+----------------------------------------------------------------------*/
7
8#include "belofte.h"
9
10/**
11 * Allow index mapper for char values of piece into int in 1-12 range
12 * to reduce space and easy initialisation
13 */
14namespace belofte {
17}
18
19namespace belofteeval {
20 extern bScore piecevalues[];
21 extern bScore centerplayvalues[];
23}
24
25//-----------------------------------------------------------------------
26
27void bMoveList::addMoveToList(bBasicBoard const& b, bMove& m, bool const isInCheck)
28{
29 if (isInCheck) {
30 m.setCheck();
31 bBasicBoard newboard(b);
32 newboard.applyMove(m);
33 bMoveList ml;
34 if (!ml.atLeastOneMovePossible(newboard))
35 m.setGameEnd();
36 }
37
38 bScore sc;
39 if (m.getGameEnd()) {
40 sc = SCORE_MATE;
41 ++m_nQSMoves; // always consider move ending game as non-silent
42 } else if (isKeepScores()) {
43 // malus points for moving own piece, except for pawn
44 // the greater the value of the piece, the more the penalty
48 if (m.isCapture()) {
50 }
51 if (m.isPawnMove()) {
52 if (m.isPromotion()) {
53 sc += 310;
54 if (m.isMajorPromotion()) sc += 500;
55 } else if (b.pieceCount() < 12 || b.getPly() > 70) {
56 // bonus for playing pawn in endgame
57 // we do not have gamestage here, so there is an approximation
58 sc += 10;
59 }
60 } else if (m.isCastleMove()) {
61 sc += 250; // malus for king move 200, so half a pawn
62 }
63 if (m.isCheck()) sc += 80; // check is less than a pawn, we prefer captures
64 if (m.isNonSilent()) ++m_nQSMoves;
65 } else {
66 sc = 0;
67 if (m.isNonSilent()) ++m_nQSMoves;
68 }
69
70 m.setScore(sc);
71
72#if defined(INCOMPLETE_C11)
73 m_lmoves.insert(m_lmoves.end(), m);
74 if (getBestMoveId()) {
75 // there is a best move registered, so we are adding second or later move
76 if (bestMoveHasImprovedNS(sc)) {
78 }
79 // we clear sorted flag too eagerly, but testing it would cost equal cpu
81 } else {
82 // no bestmove id stored yet, so newly inserted move is best move
83 setBestMoveScore(1, sc);
84 }
85#else
86 if (isKeepScores()) {
87 if (getBestMoveId()) {
88 // there is a best move registered, so we are adding second or later move
89 if (isNeedSorted()) {
90 if (bestMoveHasImprovedNS(sc)) {
91 m_lmoves.insert(m_lmoves.begin(), m);
92 setBestMoveScore(1, sc);
93 } else {
94 // best move has not improved
95 m_lmoves.insert(m_lmoves.end(), m);
96 if (getNumberOfMoves() > 2) {
97 // we do not know if the moves beyond move 1 are in correct order
99 }
100 }
101 } else {
102 // sorting is not required, adding second move
103 m_lmoves.insert(m_lmoves.end(), m);
104 if (bestMoveHasImprovedNS(sc)) {
105 // update best move
107 }
108 }
109 } else {
110 // no bestmove id stored yet, so newly inserted move is best move
111 m_lmoves.insert(m_lmoves.end(), m);
112 setBestMoveScore(1, sc);
114 if (isNeedSorted()) setIsSorted();
115 }
116 } else {
117 // do not keep scores
118 m_lmoves.insert(m_lmoves.end(), m);
119 if (!getBestMoveId()) setBestMoveScore(1, sc);
120 }
121#endif
122}
123
124/**
125 * test if new score is better than previous best score
126 * @param score is a valid score, so no tests required
127 * @return true if new score is better than previous best score
128 */
129bool bMoveList::bestMoveHasImprovedNS(bScore const score) const
130{
131 bScore bestMoveScore = getBestMoveScore();
132
133 if (bSearchScore::isRealScore(bestMoveScore)) {
134 // bestMoveScore is not UNDEFINED/INFINITE
135 if (bSearchScore::isDrawScore(score)) {
136 return bestMoveScore < 0;
137 }
138 return score > bestMoveScore;
139 } else if (bSearchScore::isDrawScore(bestMoveScore)) {
140 if (bSearchScore::isDrawScore(score)) {
141 return false;
142 }
143 return score > bestMoveScore;
144 }
145 // bestMoveScore is either + or - UNDEFINED/INFINITE
146 // so we replace it in all cases
147
148 return true;
149}
150
151/**
152 * Store score of move and update best move
153 * @param moveid of move to be stored [1 -> max number of moves]
154 * @param score to be stored
155 * @return true if best score updated
156 */
157bool bMoveList::setScoreOfMove(movenum_t const moveid, bScore const score)
158{
159 if (getBestMoveId()) {
160 // there is a best move registered, so we are adding second or later move
161 if (bestMoveHasImproved(score)) {
162 setBestMoveScore(moveid, score);
163 // the best move is no longer the first move
165 } else {
166 setMoveScore(moveid, score);
167 return false;
168 }
169 } else {
170 // no bestmove id stored yet, so newly inserted move is best move
171 setBestMoveScore(moveid, score);
172 // list is sorted as only one member
173 if (isNeedSorted()) setIsSorted();
174 }
175 return true;
176}
177
178/**
179 * Store score of move and update best move (minimum)
180 * @param moveid of move to be stored [1 -> max number of moves]
181 * @param score to be stored
182 * @return true if best score updated
183 */
184bool bMoveList::setMinScoreOfMove(movenum_t const moveid, bScore const score)
185{
186 if (getBestMoveId()) {
187 // there is a best move registered, so we are adding second or later move
188 if (minMoveHasImproved(score)) {
189 setBestMoveScore(moveid, score);
190 // the best move is no longer the first move
192 } else {
193 setMoveScore(moveid, score);
194 return false;
195 }
196 } else {
197 // no bestmove id stored yet, so newly inserted move is best move
198 setBestMoveScore(moveid, score);
199 // list is sorted as only one member
200 setIsSorted();
201 }
202 return true;
203}
204
205/**
206 * Store score of move and update best move
207 * @param moveid of move to be stored [1 -> max number of moves]
208 * @param score to be stored
209 */
211{
212 if (getBestMoveId()) {
213 // there is a best move registered, so we are adding second or later move
214 if (bestMoveHasImproved(score)) {
215 setBestMoveScore(moveid, score);
216 } else {
217 setMoveScore(moveid, score);
218 }
219 } else {
220 // no bestmove id stored yet, so newly inserted move is best move
221 setBestMoveScore(moveid, score);
222 }
223}
224
225/**
226 * Store score of move and update best move
227 * @param moveid of move to be stored [1 -> max number of moves]
228 * @param score to be stored
229 */
231{
232 if (getBestMoveId()) {
233 // there is a best move registered, so we are adding second or later move
234 if (minMoveHasImproved(score)) {
235 setBestMoveScore(moveid, score);
236 } else {
237 setMoveScore(moveid, score);
238 }
239 } else {
240 // no bestmove id stored yet, so newly inserted move is best move
241 setBestMoveScore(moveid, score);
242 }
243}
244
245/**
246 * Only add move to movelist if valid
247 * @param b board on which move is calculated
248 * @param m move to be added
249 * @return number of moves added (1), meaning player is not in check after move
250 */
252{
253 bBasicBoard newboard(b);
254 newboard.applyWhiteMove(m);
255
256 if (belofte::cWhiteKingClass->isAttacked(newboard, newboard.getWhiteKingPos())) return 0;
257 addMoveToList(b, m, belofte::cBlackKingClass->isAttacked(newboard, newboard.getBlackKingPos()));
258 return 1;
259}
260
261/**
262 * Only add move to movelist if valid
263 * @param b board on which move is calculated
264 * @param m move to be added
265 * @return number of moves added (1), meaning player is not in check after move
266 */
268{
269 bBasicBoard newboard(b);
270 newboard.applyBlackMove(m);
271
272 if (belofte::cBlackKingClass->isAttacked(newboard, newboard.getBlackKingPos())) return 0;
273 addMoveToList(b, m, belofte::cWhiteKingClass->isAttacked(newboard, newboard.getWhiteKingPos()));
274 return 1;
275}
276
277/**
278 * Only add move to movelist if valid
279 * @param b board on which move is calculated
280 * @param m move to be added
281 * @return number of moves added (4), meaning, player is not in check after move
282 */
284{
285 m.setPawnMove();
286 bBasicBoard newboard(b);
287 newboard.applyWhiteMove(m);
288 if (belofte::cWhiteKingClass->isAttacked(newboard, newboard.getWhiteKingPos())) return 0;
289
290 // we are promoting, but did apply a dummy move on top
291 // so modify dest board with custom pieces and check for in check
292 case_t to = m.to();
293 case_t bKingPos = newboard.getBlackKingPos();
294
295 /// @todo optimize in case of uncover check just by moving pawn
296 newboard.setPiece(to, tPiece::W_QUEEN);
297 bool oppInCheckByQueen = belofte::cBlackKingClass->isAttacked(newboard, bKingPos);
298 m.setPromotion(tPPiece::N_P_QUEEN); addMoveToList(b, m, oppInCheckByQueen);
299 m.clearIsCheck();
300
301 newboard.setPiece(to, tPiece::W_KNIGHT);
302 bool oppInCheck = belofte::cBlackKingClass->isAttacked(newboard, bKingPos);
303 m.setPromotion(tPPiece::N_P_KNIGHT); addMoveToList(b, m, oppInCheck);
304 m.clearIsCheck();
305
306 newboard.setPiece(to, tPiece::W_ROOK);
307 // do not re-evaluate check by rook if queen did not give check
308 oppInCheck = oppInCheckByQueen && belofte::cBlackKingClass->isAttacked(newboard, bKingPos);
309 m.setPromotion(tPPiece::N_P_ROOK); addMoveToList(b, m, oppInCheck);
310 m.clearIsCheck();
311
312 newboard.setPiece(to, tPiece::W_BISHOP);
313 oppInCheck = oppInCheckByQueen && belofte::cBlackKingClass->isAttacked(newboard, bKingPos);
314 m.setPromotion(tPPiece::N_P_BISHOP); addMoveToList(b, m, oppInCheck);
315 return 4;
316}
317
318/**
319 * Only add move to movelist if valid
320 * @param b board on which move is calculated
321 * @param m move to be added
322 * @return number of moves added (4), meaning, player is not in check after move
323 */
325{
326 m.setPawnMove();
327 bBasicBoard newboard(b);
328 newboard.applyBlackMove(m);
329 if (belofte::cBlackKingClass->isAttacked(newboard, newboard.getBlackKingPos())) return 0;
330
331 // we are promoting, but did apply a dummy move on top
332 // so modify dest board with custom pieces and check for in check
333 case_t to = m.to();
334 case_t wKingPos = newboard.getWhiteKingPos();
335
336 /// @todo optimize in case of uncover check just by moving pawn
337 newboard.setPiece(to, tPiece::B_QUEEN);
338 bool oppInCheckByQueen = belofte::cWhiteKingClass->isAttacked(newboard, wKingPos);
339 m.setPromotion(tPPiece::N_P_QUEEN); addMoveToList(b, m, oppInCheckByQueen);
340 m.clearIsCheck();
341
342 newboard.setPiece(to, tPiece::B_KNIGHT);
343 bool oppInCheck = belofte::cWhiteKingClass->isAttacked(newboard, wKingPos);
344 m.setPromotion(tPPiece::N_P_KNIGHT); addMoveToList(b, m, oppInCheck);
345 m.clearIsCheck();
346
347 newboard.setPiece(to, tPiece::B_ROOK);
348 // do not re-evaluate check by rook if queen did not give check
349 oppInCheck = oppInCheckByQueen && belofte::cWhiteKingClass->isAttacked(newboard, wKingPos);
350 m.setPromotion(tPPiece::N_P_ROOK); addMoveToList(b, m, oppInCheck);
351 m.clearIsCheck();
352
353 newboard.setPiece(to, tPiece::B_BISHOP);
354 oppInCheck = oppInCheckByQueen && belofte::cWhiteKingClass->isAttacked(newboard, wKingPos);
355 m.setPromotion(tPPiece::N_P_BISHOP); addMoveToList(b, m, oppInCheck);
356 return 4;
357}
358
359//-----------------------------------------------------------------------
360
361/**
362 * sort moves and update bestmove id
363 * if less than 5 moves, sort all
364 * if more than 5 moves, and less than 3 qs moves, sort 3 best
365 * if more than 5 moves and at least 3 qs moves, sort qsmoves + 1
366 * @param bFastSort only do partial sorting (default)
367 * @todo allow for sorting the other way around and putting lowest score first
368 */
369void bMoveList::sortMoves(bool const bFastSort)
370{
371 size_t nMoves = m_lmoves.size();
372 if (nMoves > 1) {
374 if (isNotSorted() && isNeedSorted()) {
375 if (bFastSort && nMoves >= 5) {
376 // 5 or more moves
377 if (m_nQSMoves < 3) {
378 // only interested in 3 best scores in case of a few QS moves
379 // first 2 will be qs move, and a single non qsmove will be added
380 std::partial_sort(m_lmoves.begin(), m_lmoves.begin() + 2, m_lmoves.end(),
381 [](bMove const& a, bMove const& b) { return a > b; });
382 } else if (m_nQSMoves < nMoves) {
383 // interested in all m_nQSMoves + 1 best scores
384 std::partial_sort(m_lmoves.begin(), m_lmoves.begin() + m_nQSMoves, m_lmoves.end(),
385 [](bMove const& a, bMove const& b) { return a > b; });
386 } else {
387 // all moves are qs moves and there are 5 or more moves
388 std::sort(m_lmoves.begin(), m_lmoves.end(),
389 [](bMove const& a, bMove const& b) { return a > b; });
390 }
391 } else {
392 // sort all in case of 1 to 4 elements or full sort
393 std::sort(m_lmoves.begin(), m_lmoves.end(),
394 [](bMove const& a, bMove const& b) { return a > b; });
395 }
396 setBestMoveId(1);
397 setIsSorted();
398 }
399 } else if (nMoves == 1) {
400 setBestMoveId(1);
402 } else {
404 }
405#if defined(INCOMPLETE_C11)
406 setIsSorted();
407#endif
408}
409
410//-----------------------------------------------------------------------
411
412/**
413 * generate moves if not yet generated
414 * @param b board to generate moves
415 * @return number of moves generated
416 */
418{
419 if (!isGenerated()) {
421 side_t sidetomove = b.getColourToMove();
422 if (sidetomove == tSide::SIDE_WHITE) {
423 for (case_t iCase = 0; iCase < 64; ++iCase) {
424 piece_t p = b.getPiece(iCase);
425 if (bPiece::isWhitePiece(p)) {
426 (bPiece::getPieceClass(p))->GenerateMoves(b, iCase, *this);
427 }
428 }
429 } else {
430 for (case_t iCase = 64; iCase > 0;) {
431 --iCase;
432 piece_t p = b.getPiece(iCase);
433 if (bPiece::isBlackPiece(p)) {
434 (bPiece::getPieceClass(p))->GenerateMoves(b, iCase, *this);
435 }
436 }
437 }
438 }
439
440 if (getNumberOfMoves()) {
442 return getNumberOfMoves();
443 }
444 return 0;
445}
446
448{
449 m_lmoves.clear();
451 setIsSorted(); // if no moves or a single move is registered, sorted flag is set
453 m_nQSMoves = 0;
455}
456
457/**
458 * reduce the number of QS moves to filter out the best ones only
459 */
461{
462 if (m_bestmoveid && (m_nQSMoves > 1) && isSorted()) {
463 // there is more than 1 QS move and all moves are sorted
464 // break QS moves on move that is much worse than the best moves
465 bScore currentScore = m_lmoves[m_bestmoveid - 1].getScore();
466 for (movenum_t nMoveID = 1; nMoveID < m_nQSMoves - 1 && nMoveID < m_lmoves.size() - 1; ++nMoveID) {
467 if (m_lmoves[nMoveID].getScore() < currentScore - 200) {
468 // next move in ordered list is less than 200 points below previous one
469 m_nQSMoves = nMoveID;
470 break;
471 }
472 }
473 }
474 return m_nQSMoves;
475}
476
477/**
478 * see if at least one move can be played e.g. (stale-)mate eval
479 * called from addMoveToList, iterative search main loop and gameEndedResult
480 */
482{
483 if (isPossibleMove()) return true;
484
486 if (bPiece::getPieceClass(tPiece::W_KING)->hasValidMovePreflightCheck(b, b.getWhiteKingPos()))
487 { setIsPossibleMove(); return true; }
488 for (case_t iCase = 0; iCase < 64; ++iCase) {
489 piece_t p = b.getPiece(iCase);
490 if (bPiece::isWhitePiece(p) && p != tPiece::W_KING) {
491 if (bPiece::getPieceClass(p)->hasValidMovePreflightCheck(b, iCase))
492 { setIsPossibleMove(); return true; }
493 }
494 }
495 } else {
496 if (bPiece::getPieceClass(tPiece::B_KING)->hasValidMovePreflightCheck(b, b.getBlackKingPos()))
497 { setIsPossibleMove(); return true; }
498 for (case_t iCase = 64; iCase > 0;) {
499 --iCase;
500 piece_t p = b.getPiece(iCase);
501 if (bPiece::isBlackPiece(p) && p != tPiece::B_KING) {
502 if (bPiece::getPieceClass(p)->hasValidMovePreflightCheck(b, iCase))
503 { setIsPossibleMove(); return true; }
504 }
505 }
506 }
507 return false;
508}
509
510//-----------------------------------------------------------------------
511
512std::ostream& operator<<(std::ostream& os, bMoveList const& ml)
513{
514 os << "#" << static_cast<int>(ml.getNumberOfMoves()) << " ";
515 if (ml.getNumberOfQSMoves()) {
516 os << "QS #" << static_cast<int>(ml.getNumberOfQSMoves()) << " ";
517 }
518 for (bMove const& m: ml.m_lmoves) {
519 os << m << m.getMoveEvalStr() << " ";
520 }
521 return os;
522}
523
524// eof
This is the main include file, needs to be included before any other include.
uint_fast8_t movenum_t
Definition belofte.h:103
uint8_t case_t
Definition belofte.h:99
constexpr piece_t getPiece(case_t const cf) const
Definition basicboard.h:178
boardInfo_t applyBlackMove(bMove const &m)
boardInfo_t applyWhiteMove(bMove const &m)
constexpr case_t getBlackKingPos() const
Definition basicboard.h:214
constexpr case_t getWhiteKingPos() const
Definition basicboard.h:212
constexpr int8_t pieceCount() const
Definition basicboard.h:227
constexpr side_t getColourToMove() const
Definition basicboard.h:168
void setPiece(case_t const cf, piece_t const piece)
Definition basicboard.h:188
constexpr plynum_t getPly() const
Definition basicboard.h:81
void setCheck()
Definition basicmove.h:111
void setGameEnd()
Definition basicmove.h:117
void clearIsCheck()
Definition basicmove.h:113
constexpr bool isCastleMove() const
Definition basicmove.h:101
constexpr bool isNonSilent() const
Definition basicmove.h:133
void setPawnMove()
Definition basicmove.h:99
constexpr bool isPawnMove() const
Definition basicmove.h:97
constexpr bool isCapture() const
Definition basicmove.h:93
constexpr case_t to() const
Definition basicmove.h:58
constexpr bool isPromotion() const
Definition basicmove.h:82
constexpr bool isMajorPromotion() const
Definition basicmove.h:84
void setPromotion(const ppiece_t p)
Definition basicmove.h:86
constexpr bool getGameEnd() const
Definition basicmove.h:115
constexpr bool isCheck() const
Definition basicmove.h:109
constexpr case_t from() const
Definition basicmove.h:56
Definition move.h:13
std::string getMoveEvalStr() const
Definition move.cpp:17
void setScore(bScore const score)
Definition move.h:55
constexpr bool isGenerated() const
Definition movelist.h:107
void emptyMoveList()
Definition movelist.cpp:447
movenum_t generateMoves(bBasicBoard const &b)
generate moves if not yet generated
Definition movelist.cpp:417
void setScoreOfMoveUnsorted(movenum_t const moveid, bScore const score)
Store score of move and update best move.
Definition movelist.cpp:210
constexpr bScore getBestMoveScore() const
Definition movelist.h:78
void setMinScoreOfMoveUnsorted(movenum_t const moveid, bScore const score)
Store score of move and update best move.
Definition movelist.cpp:230
constexpr bool isKeepScores() const
Definition movelist.h:142
movenum_t addBlackMoveIfValid(bBasicBoard const &b, bMove &m)
Only add move to movelist if valid.
Definition movelist.cpp:267
void clearIsSorted()
Definition movelist.h:119
void clearBestMoveId()
Definition movelist.h:91
void setMoveScore(movenum_t const moveid, bScore const score)
Definition movelist.h:84
bool setScoreOfMove(movenum_t const moveid, bScore const score)
Store score of move and update best move.
Definition movelist.cpp:157
movenum_t addBlackPromotionIfValid(bBasicBoard const &b, bMove &m)
Only add move to movelist if valid.
Definition movelist.cpp:324
void setIsPossibleMove()
Definition movelist.h:133
void clearIsPossibleMove()
Definition movelist.h:135
void clearIsGenerated()
Definition movelist.h:111
constexpr movenum_t getBestMoveId() const
Definition movelist.h:87
void setIsGenerated()
Definition movelist.h:109
constexpr bool isPossibleMove() const
Definition movelist.h:131
void setIsSorted()
Definition movelist.h:117
bMoveList()
Definition movelist.h:17
constexpr bool isNotSorted() const
Definition movelist.h:115
movenum_t addWhiteMoveIfValid(bBasicBoard const &b, bMove &m)
Only add move to movelist if valid.
Definition movelist.cpp:251
constexpr movenum_t getNumberOfMoves() const
Definition movelist.h:49
void setIsOnlyMove()
Definition movelist.h:125
bool atLeastOneMovePossible(bBasicBoard &b)
see if at least one move can be played e.g.
Definition movelist.cpp:481
void clearIsOnlyMove()
Definition movelist.h:127
constexpr movenum_t getNumberOfQSMoves() const
Definition movelist.h:51
void setBestMoveId(movenum_t const n)
Definition movelist.h:89
movenum_t adjustQSMoves()
reduce the number of QS moves to filter out the best ones only
Definition movelist.cpp:460
constexpr bool isNeedSorted() const
Definition movelist.h:138
void setBestMoveScore(bScore const score)
Definition movelist.h:80
constexpr bool isSorted() const
Definition movelist.h:113
movenum_t addWhitePromotionIfValid(bBasicBoard const &b, bMove &m)
Only add move to movelist if valid.
Definition movelist.cpp:283
void sortMoves(bool const bFastSort)
sort moves and update bestmove id if less than 5 moves, sort all if more than 5 moves,...
Definition movelist.cpp:369
bool setMinScoreOfMove(movenum_t const moveid, bScore const score)
Store score of move and update best move (minimum)
Definition movelist.cpp:184
static bPiece * getPieceClass(piece_t const piece)
static class member function
Definition piece.cpp:160
static bool isBlackPiece(piece_t const p)
static class member function
Definition piece.cpp:254
static bool isWhitePiece(piece_t const p)
static class member function
Definition piece.cpp:247
static constexpr bool isDrawScore(bScore const score)
constexpr bool isRealScore() const
Definition searchscore.h:74
constexpr bScore SCORE_MATE
Definition eval.h:19
int16_t bScore
Definition eval.h:11
std::ostream & operator<<(std::ostream &os, bMoveList const &ml)
Definition movelist.cpp:512
Allow index mapper for char values of piece into int in 1-12 range to reduce space and easy initialis...
Definition eval.cpp:10
bBlackKing const * cBlackKingClass
Definition movelist.cpp:16
bWhiteKing const * cWhiteKingClass
Definition movelist.cpp:15
const bScore centerplayvalues[]
Definition eval.cpp:384
bScore piecevalues[]
Definition eval.cpp:231
bScore piecevalues_movepenalty[]
Definition eval.cpp:237
enum tSide side_t
Definition piece.h:65
@ W_KNIGHT
Definition piece.h:39
@ B_BISHOP
Definition piece.h:40
@ W_ROOK
Definition piece.h:39
@ B_ROOK
Definition piece.h:40
@ W_QUEEN
Definition piece.h:39
@ B_KING
Definition piece.h:40
@ B_KNIGHT
Definition piece.h:40
@ W_KING
Definition piece.h:39
@ B_QUEEN
Definition piece.h:40
@ W_BISHOP
Definition piece.h:39
enum tPiece piece_t
Definition piece.h:44
@ N_P_KNIGHT
Definition piece.h:48
@ N_P_QUEEN
Definition piece.h:48
@ N_P_ROOK
Definition piece.h:48
@ N_P_BISHOP
Definition piece.h:48
@ SIDE_WHITE
Definition piece.h:61