Belofte version 2.1.8
A promising chess program using the UCI or Winboard interface
piece.cpp
Go to the documentation of this file.
1/*---------------------------------------------------------------------+
2 * File: piece.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/** Allow index mapper for char values of piece into int in 1-12 range
11 * to reduce space and easy initialisation
12 */
13namespace belofte {
14 static piece_t bPieceIndex[128] = {};
17 static boardbitmap_t kingmoves[64] = {};
18 static boardbitmap_t knightmoves[64] = {};
19}
20
24
26 : m_piece(p)
27{
28}
29
33
35{
49
63
77
78 for (case_t iCase = 0; iCase < 64; ++iCase) {
81 }
82}
83
85 boardbitmap_t dbits = 0L;
86 dbits |= destinationbits(iCase, -1, -1);
87 dbits |= destinationbits(iCase, -1, 0);
88 dbits |= destinationbits(iCase, -1, 1);
89 dbits |= destinationbits(iCase, 0, -1);
90 dbits |= destinationbits(iCase, 0, 1);
91 dbits |= destinationbits(iCase, 1, -1);
92 dbits |= destinationbits(iCase, 1, 0);
93 dbits |= destinationbits(iCase, 1, 1);
94 return dbits;
95}
96
98 boardbitmap_t dbits = 0L;
99 dbits |= destinationbits(iCase, -2, -1);
100 dbits |= destinationbits(iCase, -2, 1);
101 dbits |= destinationbits(iCase, -1, -2);
102 dbits |= destinationbits(iCase, -1, 2);
103 dbits |= destinationbits(iCase, 1, -2);
104 dbits |= destinationbits(iCase, 1, 2);
105 dbits |= destinationbits(iCase, 2, -1);
106 dbits |= destinationbits(iCase, 2, 1);
107 return dbits;
108}
109
110boardbitmap_t destinationbits(case_t const iCase, int8_t const ri, int8_t const ci) {
111 column_t newcol = bCase::column(iCase) + ci;
112 rank_t newrank = bCase::rank(iCase) + ri;
113
114 if (newcol < 0 || newcol > 7) return 0;
115 if (newrank < 0 || newrank > 7) return 0;
116
117 return bCase::caseToBit(bCase::coordToCase(newcol, newrank));
118}
119
121{
122 for (int i = 0; i < tPiece::P_SIZE; i++) {
123 delete belofte::pieceinstances[i];
124 }
125}
126
127//-----------------------------------------------------------------------
128
129/** static class member function */
131{
132 return belofte::pieceinstances[piece];
133}
134
135/** static class member function */
136std::string const bPiece::getPieceStrUpper(piece_t const piece)
137{
138 switch (piece) {
139 case tPiece::W_PAWN:
140 case tPiece::B_PAWN:
141 return S_P_PAWN;
142 case tPiece::W_ROOK:
143 case tPiece::B_ROOK:
144 return S_P_ROOK;
145 case tPiece::W_KNIGHT:
146 case tPiece::B_KNIGHT:
147 return S_P_KNIGHT;
148 case tPiece::W_BISHOP:
149 case tPiece::B_BISHOP:
150 return S_P_BISHOP;
151 case tPiece::W_KING:
152 case tPiece::B_KING:
153 return S_P_KING;
154 case tPiece::W_QUEEN:
155 case tPiece::B_QUEEN:
156 return S_P_QUEEN;
157 //case tPiece::P_EMPTY:
158 //case tPiece::P_SIZE:
159 // break;
160 default:
161 break;
162 }
163 return S_P_EMPTY;
164}
165
166//-----------------------------------------------------------------------
167
169{
170 if (!m_piece) return tSide::SIDE_UNDEFINED;
171 if (m_piece <= tPiece::W_QUEEN) return tSide::SIDE_WHITE;
172 return tSide::SIDE_BLACK;
173}
174
175//-----------------------------------------------------------------------
176
177/** static class member function */
182
183/** static class member function */
185{
186 return belofte::bPieceIndex[p];
187}
188
189/** static class member function */
190bool bPiece::isOpponent(side_t const s, piece_t const p)
191{
192 if (!p) return false;
193 if (p <= tPiece::W_QUEEN) return s == tSide::SIDE_BLACK ;
194 return s == tSide::SIDE_WHITE;
195}
196
197/** static class member function */
198bool bPiece::isOwnColour(side_t const s, piece_t const p)
199{
200 if (!p) return false;
201 if (p <= tPiece::W_QUEEN) return s == tSide::SIDE_WHITE;
202 return s == tSide::SIDE_BLACK;
203}
204
205/** static class member function */
207{
208 if (!p) return false;
209 return (p <= tPiece::W_QUEEN);
210}
211
212/** static class member function */
214{
215 if (!p) return false;
216 return (p > tPiece::W_QUEEN);
217}
218
219//-----------------------------------------------------------------------
220
222 : m_side{s}
223{
224}
225
229
230/**
231 * Check if piece on position is attacked, start with piece always on board
232 * and then with pieces with greatest mobility, goal is to break ou asap
233 * @param b board
234 * @param cf piece position
235 * @return true if attacked, false if not
236*/
237bool bWhitePiece::isAttacked(bBoard const& b, case_t const& cf) const
238{
239 boardbitmap_t caseBit = bCase::caseToBit(cf);
240 column_t fromcol = bCase::column(cf);
241 rank_t fromrank = bCase::rank(cf);
242
243 // king
244 if (caseBit & belofte::kingmoves[b.getBlackKingPos()]) return true;
245
246 // rook, queen
247 if (isAttackedBySlider(b, fromcol, fromrank, tPiece::B_ROOK, tPiece::B_QUEEN, -1, 0)) return true;
248 if (isAttackedBySlider(b, fromcol, fromrank, tPiece::B_ROOK, tPiece::B_QUEEN, 1, 0)) return true;
249 if (isAttackedBySlider(b, fromcol, fromrank, tPiece::B_ROOK, tPiece::B_QUEEN, 0, -1)) return true;
250 if (isAttackedBySlider(b, fromcol, fromrank, tPiece::B_ROOK, tPiece::B_QUEEN, 0, 1)) return true;
251
252 // bishop, queen
253 if (isAttackedBySlider(b, fromcol, fromrank, tPiece::B_BISHOP, tPiece::B_QUEEN, -1, -1)) return true;
254 if (isAttackedBySlider(b, fromcol, fromrank, tPiece::B_BISHOP, tPiece::B_QUEEN, 1, -1)) return true;
255 if (isAttackedBySlider(b, fromcol, fromrank, tPiece::B_BISHOP, tPiece::B_QUEEN, -1, 1)) return true;
256 if (isAttackedBySlider(b, fromcol, fromrank, tPiece::B_BISHOP, tPiece::B_QUEEN, 1, 1)) return true;
257
258 // knight
259 if (b.m_blackPieces[tStatPiece::STAT_KNIGHT].size()) {
260 // piece statistics filled, so we can use bitmasks
261 for (unsigned int i=0; i < b.m_blackPieces[STAT_KNIGHT].size(); i++) {
262 if (caseBit & belofte::knightmoves[b.m_blackPieces[STAT_KNIGHT][i]]) return true;
263 }
264 } else {
265 if (isAttackedByPiece(b, fromcol, fromrank, tPiece::B_KNIGHT, 1, -2)) return true;
266 if (isAttackedByPiece(b, fromcol, fromrank, tPiece::B_KNIGHT, 1, 2)) return true;
267 if (isAttackedByPiece(b, fromcol, fromrank, tPiece::B_KNIGHT, 2, -1)) return true;
268 if (isAttackedByPiece(b, fromcol, fromrank, tPiece::B_KNIGHT, 2, 1)) return true;
269 if (isAttackedByPiece(b, fromcol, fromrank, tPiece::B_KNIGHT, -1, -2)) return true;
270 if (isAttackedByPiece(b, fromcol, fromrank, tPiece::B_KNIGHT, -1, 2)) return true;
271 if (isAttackedByPiece(b, fromcol, fromrank, tPiece::B_KNIGHT, -2, -1)) return true;
272 if (isAttackedByPiece(b, fromcol, fromrank, tPiece::B_KNIGHT, -2, 1)) return true;
273 }
274
275 if (bCase::rank(cf) < 6) {
276 if (isAttackedByPiece(b, fromcol, fromrank, tPiece::B_PAWN, 1, -1)) return true;
277 if (isAttackedByPiece(b, fromcol, fromrank, tPiece::B_PAWN, 1, 1)) return true;
278 /// @todo TOCHECK how about ep
279 }
280
281 return false;
282}
283
284bool bBlackPiece::isAttacked(bBoard const& b, case_t const& cf) const
285{
286 boardbitmap_t caseBit = bCase::caseToBit(cf);
287 column_t fromcol = bCase::column(cf);
288 rank_t fromrank = bCase::rank(cf);
289
290 // king
291 if (caseBit & belofte::kingmoves[b.getWhiteKingPos()]) return true;
292
293 // rook, queen
294 if (isAttackedBySlider(b, fromcol, fromrank, tPiece::W_ROOK, tPiece::W_QUEEN, -1, 0)) return true;
295 if (isAttackedBySlider(b, fromcol, fromrank, tPiece::W_ROOK, tPiece::W_QUEEN, 1, 0)) return true;
296 if (isAttackedBySlider(b, fromcol, fromrank, tPiece::W_ROOK, tPiece::W_QUEEN, 0, -1)) return true;
297 if (isAttackedBySlider(b, fromcol, fromrank, tPiece::W_ROOK, tPiece::W_QUEEN, 0, 1)) return true;
298
299 // bishop, queen
300 if (isAttackedBySlider(b, fromcol, fromrank, tPiece::W_BISHOP, tPiece::W_QUEEN, -1, -1)) return true;
301 if (isAttackedBySlider(b, fromcol, fromrank, tPiece::W_BISHOP, tPiece::W_QUEEN, 1, -1)) return true;
302 if (isAttackedBySlider(b, fromcol, fromrank, tPiece::W_BISHOP, tPiece::W_QUEEN, -1, 1)) return true;
303 if (isAttackedBySlider(b, fromcol, fromrank, tPiece::W_BISHOP, tPiece::W_QUEEN, 1, 1)) return true;
304
305 // knight
306 if (b.m_whitePieces[tStatPiece::STAT_KNIGHT].size()) {
307 // piece statistics filled, so we can use bitmasks
308 for (unsigned int i=0; i < b.m_whitePieces[STAT_KNIGHT].size(); i++) {
309 if (caseBit & belofte::knightmoves[b.m_whitePieces[STAT_KNIGHT][i]]) return true;
310 }
311 } else {
312 if (isAttackedByPiece(b, fromcol, fromrank, tPiece::W_KNIGHT, 1, -2)) return true;
313 if (isAttackedByPiece(b, fromcol, fromrank, tPiece::W_KNIGHT, 1, 2)) return true;
314 if (isAttackedByPiece(b, fromcol, fromrank, tPiece::W_KNIGHT, 2, -1)) return true;
315 if (isAttackedByPiece(b, fromcol, fromrank, tPiece::W_KNIGHT, 2, 1)) return true;
316 if (isAttackedByPiece(b, fromcol, fromrank, tPiece::W_KNIGHT, -1, -2)) return true;
317 if (isAttackedByPiece(b, fromcol, fromrank, tPiece::W_KNIGHT, -1, 2)) return true;
318 if (isAttackedByPiece(b, fromcol, fromrank, tPiece::W_KNIGHT, -2, -1)) return true;
319 if (isAttackedByPiece(b, fromcol, fromrank, tPiece::W_KNIGHT, -2, 1)) return true;
320 }
321
322 if (bCase::rank(cf) > 1) {
323 if (isAttackedByPiece(b, fromcol, fromrank, tPiece::W_PAWN, -1, -1)) return true;
324 if (isAttackedByPiece(b, fromcol, fromrank, tPiece::W_PAWN, -1, 1)) return true;
325 /// @todo TOCHECK how about ep
326 }
327
328 return false;
329}
330
335
339
344
348
349/**
350 * Return true if position is attacked by opponent respecting move offsets
351 * @param b board
352 * @param fromcol field from
353 * @param fromrank field from
354 * @param cPiece attacking piece
355 * @param ri row increment
356 * @param ci col increment
357 * @return true/false
358 */
360 rank_t const fromrank,
361 piece_t const cPiece, int8_t const ri, int8_t const ci) const
362{
363 return (b.getPieceCtl(fromcol + ci, fromrank + ri) == cPiece);
364}
365
366/**
367 * Return true if position is attacked by opponent respecting move offsets
368 * @param b board
369 * @param fromcol field from
370 * @param fromrank field from
371 * @param cPiece first possible piece (rook/bishop)
372 * @param cPiece2 second possible piece (queen)
373 * @param ri row increment
374 * @param ci col increment
375 * @return true/false
376 */
378 rank_t const fromrank,
379 piece_t const cPiece, piece_t const cPiece2,
380 int8_t const ri, int8_t const ci) const
381{
382 rank_t newrank = fromrank + ri;
383 column_t newcol = fromcol + ci;
384
385 // slider move (queen, rook, bishop)
386 for (int8_t i = 0; i < 7; i++) {
387 // touch border?
388 if (newrank < 0 || newrank > 7) return false;
389 if (newcol < 0 || newcol > 7) return false;
390
391 piece_t piece = b.getPiece(newcol, newrank);
392 if (piece) {
393 if (piece == cPiece) return true;
394 if (piece == cPiece2) return true;
395 // not empty, not opponent piece, so protected
396 return false;
397 }
398 newrank += ri; newcol += ci;
399 }
400 return false;
401}
402
403/**
404 * Check if move could be added by just checking there
405 * is not check
406 * @return true if move seems valid, false if in check after move
407 */
409 int8_t const ri, int8_t const ci) const
410{
411 column_t oldcol = bCase::column(cf);
412
413 column_t newcol = oldcol + ci;
414 if (newcol < 0 || newcol > 7) return false;
415
416 rank_t oldrank = bCase::rank(cf);
417
418 rank_t newrank = oldrank + ri;
419 if (newrank < 0 || newrank > 7) return false;
420
421 if (bPiece::isWhitePiece(b.getPiece(newcol, newrank))) return false;
422
423 bool canMove = true;
424
425 u_positionFlags_t oldFlags = b.makeBoardMove(oldcol, oldrank, newcol, newrank, tPiece::P_EMPTY);
426
427 bWhiteKing const* wking = static_cast<bWhiteKing *>(bPiece::getPieceClass(tPiece::W_KING));
428 if (wking->isAttacked(b, b.getWhiteKingPos())) canMove = false;
429
430 b.unMakeBoardMove(cf, newcol, newrank, oldFlags, tPiece::P_EMPTY);
431
432 return canMove;
433}
434
435/**
436 * Check if pawn move could be added by just checking there
437 * is not check, case of possible promotion
438 * @return true if move seems valid, false if in check after move
439 */
441 int8_t const ri, int8_t const ci,
442 piece_t const cPromotion) const
443{
444 column_t oldcol = bCase::column(cf);
445
446 column_t newcol = oldcol + ci;
447 if (newcol < 0 || newcol > 7) return false;
448
449 rank_t oldrank = bCase::rank(cf);
450
451 rank_t newrank = oldrank + ri;
452 if (newrank < 0 || newrank > 7) return false;
453
454 if (bPiece::isWhitePiece(b.getPiece(newcol, newrank))) return false;
455
456 bool canMove = true;
457
458 u_positionFlags_t oldFlags = b.makeBoardMove(oldcol, oldrank, newcol, newrank, tPiece::P_EMPTY);
459
460 bWhiteKing const* wking = static_cast<bWhiteKing *>(bPiece::getPieceClass(tPiece::W_KING));
461 if (wking->isAttacked(b, b.getWhiteKingPos())) canMove = false;
462
463 b.unMakeBoardMove(cf, newcol, newrank, oldFlags, cPromotion);
464
465 return canMove;
466}
467
468/**
469 * Check if move could be added by just checking there
470 * is not check
471 * @return true if move seems valid, false if in check after move
472 */
474 int8_t const ri, int8_t const ci) const
475{
476 column_t oldcol = bCase::column(cf);
477
478 column_t newcol = oldcol + ci;
479 if (newcol < 0 || newcol > 7) return false;
480
481 rank_t oldrank = bCase::rank(cf);
482
483 rank_t newrank = oldrank + ri;
484 if (newrank < 0 || newrank > 7) return false;
485
486 if (bPiece::isBlackPiece(b.getPiece(newcol, newrank))) return false;
487
488 bool canMove = true;
489
490 u_positionFlags_t oldFlags = b.makeBoardMove(oldcol, oldrank, newcol, newrank, tPiece::P_EMPTY);
491
492 bBlackKing const* bking = static_cast<bBlackKing *>(bPiece::getPieceClass(tPiece::B_KING));
493 if (bking->isAttacked(b, b.getBlackKingPos())) canMove = false;
494
495 b.unMakeBoardMove(cf, newcol, newrank, oldFlags, tPiece::P_EMPTY);
496
497 return canMove;
498}
499
500/**
501 * Check if pawn move could be added by just checking there
502 * is not check, case of possible promotion
503 * @return true if move seems valid, false if in check after move
504 */
506 int8_t const ri, int8_t const ci,
507 piece_t const cPromotion) const
508{
509 column_t oldcol = bCase::column(cf);
510
511 column_t newcol = oldcol + ci;
512 if (newcol < 0 || newcol > 7) return false;
513
514 rank_t oldrank = bCase::rank(cf);
515
516 rank_t newrank = oldrank + ri;
517 if (newrank < 0 || newrank > 7) return false;
518
519 if (bPiece::isBlackPiece(b.getPiece(newcol, newrank))) return false;
520
521 bool canMove = true;
522
523 u_positionFlags_t oldFlags = b.makeBoardMove(oldcol, oldrank, newcol, newrank, tPiece::P_EMPTY);
524
525 bBlackKing const* bking = static_cast<bBlackKing *>(bPiece::getPieceClass(tPiece::B_KING));
526 if (bking->isAttacked(b, b.getBlackKingPos())) canMove = false;
527
528 b.unMakeBoardMove(cf, newcol, newrank, oldFlags, cPromotion);
529
530 return canMove;
531}
532
533/** Check for in-check position, single step move
534 * used for King and Knight
535 */
537 int8_t const ri, int8_t const ci, bMoveList& ml) const
538{
539 column_t newcol = bCase::column(cf) + ci;
540 if (newcol < 0 || newcol > 7) return 0;
541
542 rank_t newrank = bCase::rank(cf) + ri;
543 if (newrank < 0 || newrank > 7) return 0;
544
545 case_t to = bCase::coordToCase(newcol, newrank);
546 if (b.isFieldEmpty(to)) {
547 return ml.addWhiteMoveIfValid(b, bMove(cf, to));
548 } else if (bPiece::isBlackPiece(b.getPiece(to))) {
549 return ml.addWhiteCaptureIfValid(b, cf, to);
550 }
551 return 0;
552}
553
555 int8_t const ri, int8_t const ci, bMoveList& ml) const
556{
557 column_t newcol = bCase::column(cf) + ci;
558 if (newcol < 0 || newcol > 7) return 0;
559
560 rank_t newrank = bCase::rank(cf) + ri;
561 if (newrank < 0 || newrank > 7) return 0;
562
563 case_t to = bCase::coordToCase(newcol, newrank);
564 if (b.isFieldEmpty(to)) {
565 return ml.addBlackMoveIfValid(b, bMove(cf, to));
566 } else if (bPiece::isWhitePiece(b.getPiece(to))) {
567 return ml.addBlackCaptureIfValid(b, cf, to);
568 }
569 return 0;
570}
571
572/**
573 * Add moves for Queen, Rook and Bishop
574 * @return number of moves generated
575 */
577 int8_t const ri, int8_t const ci, bMoveList& ml) const
578{
579 int_fast8_t nMax = 7;
580 movenum_t nMoves = 0;
581 column_t newcol = bCase::column(cf) + ci;
582 rank_t newrank = bCase::rank(cf) + ri;
583
584 while (--nMax >= 0) {
585 if (newcol < 0 || newcol > 7) return nMoves;
586 if (newrank < 0 || newrank > 7) return nMoves;
587
588 case_t to = bCase::coordToCase(newcol, newrank);
589 if (b.isFieldEmpty(to)) {
590 nMoves += ml.addWhiteMoveIfValid(b, bMove(cf, to));
591 } else if (bPiece::isBlackPiece(b.getPiece(to))) {
592 nMoves += ml.addWhiteCaptureIfValid(b, cf, to);
593 break;
594 } else {
595 // own colour, cannot jump
596 break;
597 }
598 newcol += ci;
599 newrank += ri;
600 }
601 return nMoves;
602}
603
605 int8_t const ri, int8_t const ci, bMoveList& ml) const
606{
607 int_fast8_t nMax = 7;
608 movenum_t nMoves = 0;
609 column_t newcol = bCase::column(cf) + ci;
610 rank_t newrank = bCase::rank(cf) + ri;
611
612 while (--nMax >= 0) {
613 if (newcol < 0 || newcol > 7) return nMoves;
614 if (newrank < 0 || newrank > 7) return nMoves;
615
616 case_t to = bCase::coordToCase(newcol, newrank);
617 if (b.isFieldEmpty(to)) {
618 nMoves += ml.addBlackMoveIfValid(b, bMove(cf, to));
619 } else if (bPiece::isWhitePiece(b.getPiece(to))) {
620 nMoves += ml.addBlackCaptureIfValid(b, cf, to);
621 break;
622 } else {
623 // own colour, cannot jump
624 break;
625 }
626 newcol += ci;
627 newrank += ri;
628 }
629 return nMoves;
630}
631
632/** Test move is possible, single step non capture move
633 * could be promotion as well
634 */
635bool bWhitePawn::canPawnMove(bBoard& b, case_t const& cf) const
636{
637 column_t newcol = bCase::column(cf);
638 rank_t newrank = bCase::rank(cf) + 1;
639 // no test on rank, as we remain on board
640
641 if (!b.isFieldEmpty(newcol, newrank)) return false;
642
643 return canMovePreflightCheck(b, cf, 1, 0, tPiece::W_PAWN);
644}
645
646/** Test move is possible, pawn capture move
647 * could be promotion as well
648 */
649bool bWhitePawn::canPawnCapture(bBoard& b, case_t const& cf,
650 int8_t const ci) const
651{
652 column_t newcol = bCase::column(cf) + ci;
653 if (newcol < 0 || newcol > 7) return false;
654
655 rank_t newrank = bCase::rank(cf) + 1;
656 // no test on rank, as we remain on board
657
658 if (!bPiece::isBlackPiece(b.getPiece(newcol, newrank))) return false;
659
660 return canMovePreflightCheck(b, cf, 1, ci, tPiece::W_PAWN);
661}
662
663/** Test if e.p. move is possible
664 */
665bool bWhitePawn::canPawnEPMove(bBoard& b,
666 case_t const& cf, int8_t const ci) const
667{
668 column_t newcol = bCase::column(cf) + ci;
669 if (newcol < 0 || newcol > 7) return false;
670
671 // no test on rank, as we remain on board
672
673 if (bCase::column(cf) != bCase::column(b.getEp()) + ci) return false;
674
675 return canMovePreflightCheck(b, cf, 1, ci);
676}
677
678/** Test move is possible, single step move
679 * non capture move
680 */
682 bMoveList& ml) const
683{
684 // no test on rank, as we remain on board
686 if (b.isFieldEmpty(to)) {
687 bMove m(cf, to);
688 return ml.addWhiteMoveIfValid(b, m);
689 }
690 return 0;
691}
692
693/** Test move is possible, single step non capture move
694 * could be promotion as well
695 */
696bool bBlackPawn::canPawnMove(bBoard& b, case_t const& cf) const
697{
698 column_t newcol = bCase::column(cf);
699 rank_t newrank = bCase::rank(cf) - 1;
700 // no test on rank, as we remain on board
701
702 if (!b.isFieldEmpty(newcol, newrank)) return false;
703
704 return canMovePreflightCheck(b, cf, -1, 0, tPiece::B_PAWN);
705}
706
707/** Test move is possible, pawn capture move
708 * could be promotion as well
709 */
710bool bBlackPawn::canPawnCapture(bBoard& b, case_t const& cf,
711 int8_t const ci) const
712{
713 column_t newcol = bCase::column(cf) + ci;
714 if (newcol < 0 || newcol > 7) return false;
715
716 rank_t newrank = bCase::rank(cf) - 1;
717 // no test on rank, as we remain on board
718
719 if (!bPiece::isWhitePiece(b.getPiece(newcol, newrank))) return false;
720
721 return canMovePreflightCheck(b, cf, -1, ci, tPiece::B_PAWN);
722}
723
724/** Test if e.p. move is possible
725 */
726bool bBlackPawn::canPawnEPMove(bBoard& b,
727 case_t const& cf, int8_t const ci) const
728{
729 column_t newcol = bCase::column(cf) + ci;
730 if (newcol < 0 || newcol > 7) return false;
731
732 // no test on rank, as we remain on board
733
734 if (bCase::column(cf) != bCase::column(b.getEp()) + ci) return false;
735
736 return canMovePreflightCheck(b, cf, -1, ci);
737}
738
739/** Test move is possible, single step move
740 * non capture move
741 */
743 bMoveList& ml) const
744{
745 // no test on rank, as we remain on board
747 if (b.isFieldEmpty(to)) {
748 bMove m(cf, to);
749 return ml.addBlackMoveIfValid(b, m);
750 }
751 return 0;
752}
753
755 bMoveList& ml) const
756{
757 // no test on rank, as we remain on board
759 if (b.isFieldEmpty(to)) {
760 bMove m(cf, to);
761 m.setEPPossible();
762 return ml.addWhiteMoveIfValid(b, m);
763 }
764 return 0;
765}
766
768 bMoveList& ml) const
769{
770 // no test on rank, as we remain on board
772 if (b.isFieldEmpty(to)) {
773 bMove m(cf, to);
774 m.setEPPossible();
775 return ml.addBlackMoveIfValid(b, m);
776 }
777 return 0;
778}
779
781 int8_t const ci, bMoveList& ml) const
782{
783 column_t newcol = bCase::column(cf) + ci;
784 if (newcol < 0 || newcol > 7) return 0;
785
786 rank_t newrank = bCase::rank(cf) + 1;
787 // no test on rank, as we remain on board
788
789 if (bPiece::isBlackPiece(b.getPiece(newcol, newrank))) {
790 return ml.addWhiteCaptureIfValid(b, cf, bCase::coordToCase(newcol, newrank));
791 }
792 return 0;
793}
794
796 int8_t const ci, bMoveList& ml) const
797{
798 column_t newcol = bCase::column(cf) + ci;
799 if (newcol < 0 || newcol > 7) return 0;
800
801 rank_t newrank = bCase::rank(cf) - 1;
802 // no test on rank, as we remain on board
803
804 if (bPiece::isWhitePiece(b.getPiece(newcol, newrank))) {
805 return ml.addBlackCaptureIfValid(b, cf, bCase::coordToCase(newcol, newrank));
806 }
807 return 0;
808}
809
810/** Test move is possible, single step move
811 * non capture move
812 */
814 bMoveList& ml) const
815{
816 // no test on new rank, as promotion is always in good rank
818 if (b.isFieldEmpty(to)) {
819 return ml.addWhitePromotionIfValid(b, bMove(cf, to));
820 }
821 return 0;
822}
823
825 bMoveList& ml) const
826{
827 // no test on new rank, as promotion is always in good rank
829 if (b.isFieldEmpty(to)) {
830 return ml.addBlackPromotionIfValid(b, bMove(cf, to));
831 }
832 return 0;
833}
834
835/** Test move is possible, single step move
836 * capture only move
837 */
839 int8_t const ci, bMoveList& ml) const
840{
841 column_t newcol = bCase::column(cf) + ci;
842
843 if (newcol < 0 || newcol > 7) return 0;
844 // no test on new rank, as capture promotion is always in good rank
845
846 rank_t newrank = 7;
847
848 if (bPiece::isBlackPiece(b.getPiece(newcol, newrank))) {
849 bMove m(cf, bCase::coordToCase(newcol, newrank));
850 m.setCapture();
851 return ml.addWhitePromotionIfValid(b, m);
852 }
853 return 0;
854}
855
857 int8_t const ci, bMoveList& ml) const
858{
859 column_t newcol = bCase::column(cf) + ci;
860
861 if (newcol < 0 || newcol > 7) return 0;
862 // no test on new rank, as capture promotion is always in good rank
863
864 rank_t newrank = 0;
865
866 if (bPiece::isWhitePiece(b.getPiece(newcol, newrank))) {
867 bMove m(cf, bCase::coordToCase(newcol, newrank));
868 m.setCapture();
869 return ml.addBlackPromotionIfValid(b, m);
870 }
871 return 0;
872}
873
874/** Test move is possible, e.p. move
875 * capture only move, no test if pawn is present
876 * only board e.p. flag is used in calling function
877 */
879 int8_t const ci, bMoveList& ml) const
880{
881 // no test on column, as e.p. move is pre-calculated
882 // no test on new rank, as e.p. is always in good rank
883 case_t to = bCase::coordToCase(bCase::column(cf) + ci, bCase::rank(cf) + 1);
884 bMove m(cf, to);
885 m.setCapture();
886 m.setEPMove();
887 return ml.addWhiteMoveIfValid(b, m);
888}
889
890/** Test move is possible, e.p. move
891 * capture only move, no test if pawn is present
892 * only board e.p. flag is used in calling function
893 */
895 int8_t const ci, bMoveList& ml) const
896{
897 // no test on column, as e.p. move is pre-calculated
898 // no test on new rank, as e.p. is always in good rank
899 case_t to = bCase::coordToCase(bCase::column(cf) + ci, bCase::rank(cf) - 1);
900 bMove m(cf, to);
901 m.setCapture();
902 m.setEPMove();
903 return ml.addBlackMoveIfValid(b, m);
904}
905
906/** check if there is at least one move possible
907 * currently, relies on full move generation for pawn
908 * @todo full preflight implementation to speed-up
909 */
911{
912 if (canPawnMove(b, cf)) return true;
913 if (canPawnCapture(b, cf, -1)) return true;
914 if (canPawnCapture(b, cf, 1)) return true;
915 if (bCase::rank(cf) == 4 && b.getEp()) {
916 if (canPawnEPMove(b, cf, -1)) return true;
917 if (canPawnEPMove(b, cf, 1)) return true;
918 }
919 return false;
920}
921
923{
924 movenum_t nMoves = 0;
925
926 if (bCase::rank(cf) == 6) {
927 nMoves += addNonCapturePromotionMove(b, cf, ml);
928 nMoves += addCapturePromotionMove(b, cf, -1, ml);
929 nMoves += addCapturePromotionMove(b, cf, 1, ml);
930 } else {
931 nMoves += addNonCapturePawnMove(b, cf, ml);
932 if ((bCase::rank(cf) == 1) && b.isFieldEmpty(bCase::column(cf),2))
933 nMoves += addNonCaptureDoublePawnMove(b, cf, ml);
934 nMoves += addCapturePawnMove(b, cf, -1, ml);
935 nMoves += addCapturePawnMove(b, cf, 1, ml);
936 if (bCase::rank(cf) == 4 && b.getEp()) {
937 if (bCase::column(cf) == bCase::column(b.getEp()) + 1) {
938 nMoves += addEPMove(b, cf, -1, ml);
939 } else if (bCase::column(cf) == bCase::column(b.getEp()) - 1) {
940 nMoves += addEPMove(b, cf, 1, ml);
941 }
942 }
943 }
944 return nMoves;
945}
946
947/** check if there is at least one move possible
948 * currently, relies on full move generation for pawn
949 */
951{
952 if (canPawnMove(b, cf)) return true;
953 if (canPawnCapture(b, cf, -1)) return true;
954 if (canPawnCapture(b, cf, 1)) return true;
955 if (bCase::rank(cf) == 3 && b.getEp()) {
956 if (canPawnEPMove(b, cf, -1)) return true;
957 if (canPawnEPMove(b, cf, 1)) return true;
958 }
959 return false;
960}
961
963{
964 movenum_t nMoves = 0;
965
966 if (bCase::rank(cf) == 1) {
967 nMoves += addNonCapturePromotionMove(b, cf, ml);
968 nMoves += addCapturePromotionMove(b, cf, -1, ml);
969 nMoves += addCapturePromotionMove(b, cf, 1, ml);
970 } else {
971 nMoves += addNonCapturePawnMove(b, cf, ml);
972 if ((bCase::rank(cf) == 6) && b.isFieldEmpty(bCase::column(cf), 5))
973 nMoves += addNonCaptureDoublePawnMove(b, cf, ml);
974 nMoves += addCapturePawnMove(b, cf, -1, ml);
975 nMoves += addCapturePawnMove(b, cf, 1, ml);
976 if (bCase::rank(cf) == 3 && b.getEp()) {
977 if (bCase::column(cf) == bCase::column(b.getEp()) + 1) {
978 nMoves += addEPMove(b, cf, -1, ml);
979 } else if (bCase::column(cf) == bCase::column(b.getEp()) - 1) {
980 nMoves += addEPMove(b, cf, 1, ml);
981 }
982 }
983 }
984 return nMoves;
985}
986
988{
989 if (canMovePreflightCheck(b, cf, -1, 0)
990 || canMovePreflightCheck(b, cf, 1, 0)
991 || canMovePreflightCheck(b, cf, 0, 1)
992 || canMovePreflightCheck(b, cf, 0, -1)) return true;
993 return false;
994}
995
997{
998 if (canMovePreflightCheck(b, cf, -1, 0)
999 || canMovePreflightCheck(b, cf, 1, 0)
1000 || canMovePreflightCheck(b, cf, 0, -1)
1001 || canMovePreflightCheck(b, cf, 0, 1)) return true;
1002 return false;
1003}
1004
1006{
1007 movenum_t nMoves = 0;
1008
1009 nMoves += addMoves(b, cf, -1, 0, ml);
1010 nMoves += addMoves(b, cf, 1, 0, ml);
1011 nMoves += addMoves(b, cf, 0, -1, ml);
1012 nMoves += addMoves(b, cf, 0, 1, ml);
1013
1014 return nMoves;
1015}
1016
1018{
1019 movenum_t nMoves = 0;
1020
1021 nMoves += addMoves(b, cf, -1, 0, ml);
1022 nMoves += addMoves(b, cf, 1, 0, ml);
1023 nMoves += addMoves(b, cf, 0, -1, ml);
1024 nMoves += addMoves(b, cf, 0, 1, ml);
1025
1026 return nMoves;
1027}
1028
1030{
1031 if (canMovePreflightCheck(b, cf, 1, 2)
1032 || canMovePreflightCheck(b, cf, 1, -2)
1033 || canMovePreflightCheck(b, cf, 2, 1)
1034 || canMovePreflightCheck(b, cf, 2, -1)
1035 || canMovePreflightCheck(b, cf, -1, 2)
1036 || canMovePreflightCheck(b, cf, -1, -2)
1037 || canMovePreflightCheck(b, cf, -2, 1)
1038 || canMovePreflightCheck(b, cf, -2, -1)) return true;
1039 return false;
1040}
1041
1043{
1044 if (canMovePreflightCheck(b, cf, -1, 2)
1045 || canMovePreflightCheck(b, cf, -1, -2)
1046 || canMovePreflightCheck(b, cf, 2, 1)
1047 || canMovePreflightCheck(b, cf, 2, -1)
1048 || canMovePreflightCheck(b, cf, 1, 2)
1049 || canMovePreflightCheck(b, cf, 1, -2)
1050 || canMovePreflightCheck(b, cf, -2, 1)
1051 || canMovePreflightCheck(b, cf, -2, -1)) return true;
1052 return false;
1053}
1054
1056{
1057 movenum_t nMoves = 0;
1058
1059 nMoves += addMove(b, cf, 1, 2, ml);
1060 nMoves += addMove(b, cf, 1, -2, ml);
1061 nMoves += addMove(b, cf, 2, 1, ml);
1062 nMoves += addMove(b, cf, -2, 1, ml);
1063 nMoves += addMove(b, cf, -1, 2, ml);
1064 nMoves += addMove(b, cf, -1, -2, ml);
1065 nMoves += addMove(b, cf, 2, -1, ml);
1066 nMoves += addMove(b, cf, -2, -1, ml);
1067
1068 return nMoves;
1069}
1070
1072{
1073 movenum_t nMoves = 0;
1074
1075 nMoves += addMove(b, cf, 1, 2, ml);
1076 nMoves += addMove(b, cf, 1, -2, ml);
1077 nMoves += addMove(b, cf, 2, 1, ml);
1078 nMoves += addMove(b, cf, -2, 1, ml);
1079 nMoves += addMove(b, cf, -1, 2, ml);
1080 nMoves += addMove(b, cf, -1, -2, ml);
1081 nMoves += addMove(b, cf, 2, -1, ml);
1082 nMoves += addMove(b, cf, -2, -1, ml);
1083
1084 return nMoves;
1085}
1086
1088{
1089 if (canMovePreflightCheck(b, cf, 1, -1)
1090 || canMovePreflightCheck(b, cf, 1, 1)
1091 || canMovePreflightCheck(b, cf, -1, 1)
1092 || canMovePreflightCheck(b, cf, -1, -1)) return true;
1093 return false;
1094}
1095
1097{
1098 if (canMovePreflightCheck(b, cf, -1, -1)
1099 || canMovePreflightCheck(b, cf, 1, -1)
1100 || canMovePreflightCheck(b, cf, -1, 1)
1101 || canMovePreflightCheck(b, cf, 1, 1)) return true;
1102 return false;
1103}
1104
1106{
1107 movenum_t nMoves = 0;
1108
1109 nMoves += addMoves(b, cf, -1, -1, ml);
1110 nMoves += addMoves(b, cf, 1, -1, ml);
1111 nMoves += addMoves(b, cf, -1, 1, ml);
1112 nMoves += addMoves(b, cf, 1, 1, ml);
1113
1114 return nMoves;
1115}
1116
1118{
1119 movenum_t nMoves = 0;
1120
1121 nMoves += addMoves(b, cf, -1, -1, ml);
1122 nMoves += addMoves(b, cf, 1, -1, ml);
1123 nMoves += addMoves(b, cf, -1, 1, ml);
1124 nMoves += addMoves(b, cf, 1, 1, ml);
1125
1126 return nMoves;
1127}
1128
1130{
1131 if (canMovePreflightCheck(b, cf, 0, -1)
1132 || canMovePreflightCheck(b, cf, 0, 1)
1133 || canMovePreflightCheck(b, cf, 1, -1)
1134 || canMovePreflightCheck(b, cf, 1, 0)
1135 || canMovePreflightCheck(b, cf, 1, 1)
1136 || canMovePreflightCheck(b, cf, -1, -1)
1137 || canMovePreflightCheck(b, cf, -1, 0)
1138 || canMovePreflightCheck(b, cf, -1, 1)) return true;
1139 return false;
1140}
1141
1143{
1144 if (canMovePreflightCheck(b, cf, 0, -1)
1145 || canMovePreflightCheck(b, cf, 0, 1)
1146 || canMovePreflightCheck(b, cf, 1, -1)
1147 || canMovePreflightCheck(b, cf, 1, 0)
1148 || canMovePreflightCheck(b, cf, 1, 1)
1149 || canMovePreflightCheck(b, cf, -1, -1)
1150 || canMovePreflightCheck(b, cf, -1, 0)
1151 || canMovePreflightCheck(b, cf, -1, 1)) return true;
1152 return false;
1153}
1154
1156{
1157 movenum_t nMoves = 0;
1158
1159 nMoves += addMoves(b, cf, 0, -1, ml);
1160 nMoves += addMoves(b, cf, 0, 1, ml);
1161 nMoves += addMoves(b, cf, 1, -1, ml);
1162 nMoves += addMoves(b, cf, 1, 0, ml);
1163 nMoves += addMoves(b, cf, 1, 1, ml);
1164 nMoves += addMoves(b, cf, -1, -1, ml);
1165 nMoves += addMoves(b, cf, -1, 0, ml);
1166 nMoves += addMoves(b, cf, -1, 1, ml);
1167
1168 return nMoves;
1169}
1170
1172{
1173 movenum_t nMoves = 0;
1174
1175 nMoves += addMoves(b, cf, 0, -1, ml);
1176 nMoves += addMoves(b, cf, 0, 1, ml);
1177 nMoves += addMoves(b, cf, 1, -1, ml);
1178 nMoves += addMoves(b, cf, 1, 0, ml);
1179 nMoves += addMoves(b, cf, 1, 1, ml);
1180 nMoves += addMoves(b, cf, -1, -1, ml);
1181 nMoves += addMoves(b, cf, -1, 0, ml);
1182 nMoves += addMoves(b, cf, -1, 1, ml);
1183
1184 return nMoves;
1185}
1186
1188{
1189 if (canMovePreflightCheck(b, cf, 0, -1)
1190 || canMovePreflightCheck(b, cf, 0, 1)
1191 || canMovePreflightCheck(b, cf, 1, -1)
1192 || canMovePreflightCheck(b, cf, 1, 0)
1193 || canMovePreflightCheck(b, cf, 1, 1)
1194 || canMovePreflightCheck(b, cf, -1, -1)
1195 || canMovePreflightCheck(b, cf, -1, 0)
1196 || canMovePreflightCheck(b, cf, -1, 1)) return true;
1197 return false;
1198}
1199
1201{
1202 if (canMovePreflightCheck(b, cf, 0, -1)
1203 || canMovePreflightCheck(b, cf, 0, 1)
1204 || canMovePreflightCheck(b, cf, -1, -1)
1205 || canMovePreflightCheck(b, cf, -1, 0)
1206 || canMovePreflightCheck(b, cf, -1, 1)
1207 || canMovePreflightCheck(b, cf, 1, -1)
1208 || canMovePreflightCheck(b, cf, 1, 0)
1209 || canMovePreflightCheck(b, cf, 1, 1)) return true;
1210 return false;
1211}
1212
1214{
1215 movenum_t nMoves = 0;
1216
1217 nMoves += addMove(b, cf, 0, -1, ml);
1218 nMoves += addMove(b, cf, 0, 1, ml);
1219 nMoves += addMove(b, cf, 1, -1, ml);
1220 nMoves += addMove(b, cf, 1, 0, ml);
1221 nMoves += addMove(b, cf, 1, 1, ml);
1222 nMoves += addMove(b, cf, -1, -1, ml);
1223 nMoves += addMove(b, cf, -1, 0, ml);
1224 nMoves += addMove(b, cf, -1, 1, ml);
1225
1226 // king not on original position, TODO: use absolute index
1227 if ((bCase::column(cf) != 4) || (bCase::rank(cf) != 0)) return nMoves;
1228
1229 // king in check
1230 bWhiteKing const* wking = static_cast<bWhiteKing *>(bPiece::getPieceClass(tPiece::W_KING));
1231 if (wking->isAttacked(b, cf)) return nMoves;
1232
1234 // short castle, test if row is empty
1235 if (b.isFieldEmpty(bCase::coordToCase(5, 0))
1237 && !wking->isAttacked(b, bCase::coordToCase(5, 0))) {
1238 // king is not going over attacked field
1239 bMove m(cf, bCase::coordToCase(6, 0));
1241 nMoves += ml.addWhiteMoveIfValid(b, m);
1242 }
1243 }
1244
1246 // long castle, test if row is empty
1247 if (b.isFieldEmpty(bCase::coordToCase(3, 0))
1250 && !wking->isAttacked(b, bCase::coordToCase(3, 0))) {
1251 // king is not going over attacked field
1252 bMove m(cf, bCase::coordToCase(2, 0));
1254 nMoves += ml.addWhiteMoveIfValid(b, m);
1255 }
1256 }
1257
1258 return nMoves;
1259}
1260
1262{
1263 movenum_t nMoves = 0;
1264
1265 nMoves += addMove(b, cf, 0, -1, ml);
1266 nMoves += addMove(b, cf, 0, 1, ml);
1267 nMoves += addMove(b, cf, 1, -1, ml);
1268 nMoves += addMove(b, cf, 1, 0, ml);
1269 nMoves += addMove(b, cf, 1, 1, ml);
1270 nMoves += addMove(b, cf, -1, -1, ml);
1271 nMoves += addMove(b, cf, -1, 0, ml);
1272 nMoves += addMove(b, cf, -1, 1, ml);
1273
1274 // king not on original position, TODO: use absolute index
1275 if ((bCase::column(cf) != 4) || (bCase::rank(cf) != 7)) return nMoves;
1276
1277 // king in check
1278 bBlackKing const* bking = static_cast<bBlackKing *>(bPiece::getPieceClass(tPiece::B_KING));
1279 if (bking->isAttacked(b, cf)) return nMoves;
1280
1282 // short castle, test if row is empty
1283 if (b.isFieldEmpty(bCase::coordToCase(5, 7))
1285 && !bking->isAttacked(b, bCase::coordToCase(5, 7))) {
1286 // king is not going over attacked field
1287 bMove m(cf, bCase::coordToCase(6, 7));
1289 nMoves += ml.addBlackMoveIfValid(b, m);
1290 }
1291 }
1292
1294 // long castle, test if row is empty
1295 if (b.isFieldEmpty(bCase::coordToCase(3, 7))
1298 && !bking->isAttacked(b, bCase::coordToCase(3, 7))) {
1299 // king is not going over attacked field
1300 bMove m(cf, bCase::coordToCase(2, 7));
1302 nMoves += ml.addBlackMoveIfValid(b, m);
1303 }
1304 }
1305
1306 return nMoves;
1307}
1308
1309//-----------------------------------------------------------------------
1310// eof
This is the main include file, needs to be included before any other include.
int8_t rank_t
Definition belofte.h:104
int8_t column_t
Definition belofte.h:105
uint_fast8_t movenum_t
Definition belofte.h:109
uint8_t case_t
Definition belofte.h:106
uint64_t boardbitmap_t
Definition belofte.h:111
@ BCASTLE_L
Definition board.h:11
@ BCASTLE_S
Definition board.h:11
@ WCASTLE_S
Definition board.h:11
@ WCASTLE_L
Definition board.h:11
piece_t getPiece(case_t const bc) const
1 for white, 2 for black
Definition board.cpp:157
u_positionFlags_t makeBoardMove(column_t const oldcol, rank_t const oldrank, column_t const newcol, rank_t const newrank, piece_t const promotion)
apply move to check if in check only, board to be discarded as it will be in incomplete state,...
Definition board.cpp:400
case_t getBlackKingPos() const
Definition board.h:103
void unMakeBoardMove(case_t const &cf, column_t const newcol, rank_t const newrank, u_positionFlags_t const oldFlags, piece_t const promotion)
undo makeBoardMove, restoring previous situation
Definition board.cpp:481
case_t getWhiteKingPos() const
Definition board.h:102
case_t getEp() const
Definition board.h:58
bool canCastle() const
Definition board.cpp:243
piece_t getPieceCtl(column_t const iColumn, rank_t const iRank) const
retrieve piece with bounds checking, return field empty in case of out of bounds
Definition board.cpp:171
bool isFieldEmpty(case_t const bc) const
Definition board.cpp:178
bool hasValidMovePreflightCheck(bBoard &b, case_t const &cf) final
Definition piece.cpp:1096
movenum_t GenerateMoves(bBoard const &b, case_t const &cf, bMoveList &ml) final
Definition piece.cpp:1117
bool hasValidMovePreflightCheck(bBoard &b, case_t const &cf) final
Definition piece.cpp:1200
movenum_t GenerateMoves(bBoard const &b, case_t const &cf, bMoveList &ml) final
Definition piece.cpp:1261
movenum_t GenerateMoves(bBoard const &b, case_t const &cf, bMoveList &ml) final
Definition piece.cpp:1071
bool hasValidMovePreflightCheck(bBoard &b, case_t const &cf) final
Definition piece.cpp:1042
movenum_t addEPMove(bBoard const &b, case_t const &cf, int8_t const ci, bMoveList &ml) const
Test move is possible, e.p.
Definition piece.cpp:894
bool hasValidMovePreflightCheck(bBoard &b, case_t const &cf) final
check if there is at least one move possible currently, relies on full move generation for pawn
Definition piece.cpp:950
movenum_t addNonCapturePawnMove(bBoard const &b, case_t const &cf, bMoveList &ml) const
Test move is possible, single step move non capture move.
Definition piece.cpp:742
movenum_t addCapturePromotionMove(bBoard const &b, case_t const &cf, int8_t const ci, bMoveList &ml) const
Definition piece.cpp:856
movenum_t addCapturePawnMove(bBoard const &b, case_t const &cf, int8_t const ci, bMoveList &ml) const
Definition piece.cpp:795
movenum_t GenerateMoves(bBoard const &b, case_t const &cf, bMoveList &ml) final
Definition piece.cpp:962
movenum_t addNonCaptureDoublePawnMove(bBoard const &b, case_t const &cf, bMoveList &ml) const
Definition piece.cpp:767
movenum_t addNonCapturePromotionMove(bBoard const &b, case_t const &cf, bMoveList &ml) const
Definition piece.cpp:824
movenum_t addMove(bBoard const &b, case_t const &cf, int8_t const ri, int8_t const ci, bMoveList &ml) const final
Definition piece.cpp:554
~bBlackPiece() override
Definition piece.cpp:345
movenum_t addMoves(bBoard const &b, case_t const &cf, int8_t const ri, int8_t const ci, bMoveList &ml) const final
Definition piece.cpp:604
bool canMovePreflightCheck(bBoard &b, case_t const &cf, int8_t const ri, int8_t const ci) const override
Check if move could be added by just checking there is not check.
Definition piece.cpp:473
bool isAttacked(bBoard const &b, case_t const &cf) const override
Definition piece.cpp:284
bool hasValidMovePreflightCheck(bBoard &b, case_t const &cf) final
Definition piece.cpp:1142
movenum_t GenerateMoves(bBoard const &b, case_t const &cf, bMoveList &ml) final
Definition piece.cpp:1171
bool hasValidMovePreflightCheck(bBoard &b, case_t const &cf) final
Definition piece.cpp:996
movenum_t GenerateMoves(bBoard const &b, case_t const &cf, bMoveList &ml) final
Definition piece.cpp:1017
board
Definition board.h:147
column_t column() const
Definition case.h:37
static constexpr case_t coordToCase(column_t const c, rank_t const r)
Definition case.h:42
static constexpr boardbitmap_t caseToBit(case_t const c)
Definition case.h:58
rank_t rank() const
Definition case.h:38
Definition move.h:69
void setEPMove()
Definition move.h:103
void setCapture()
Definition move.h:88
void setShortCastleMove()
Definition move.h:92
void setLongCastleMove()
Definition move.h:93
void setEPPossible()
Definition move.h:101
movenum_t addWhiteCaptureIfValid(bBoard const &b, case_t const &cf, case_t const &to)
Definition movelist.cpp:89
movenum_t addBlackPromotionIfValid(bBoard const &b, bMove const &m)
Only add move to movelist if valid.
Definition movelist.cpp:165
movenum_t addWhitePromotionIfValid(bBoard const &b, bMove const &m)
Only add move to movelist if valid.
Definition movelist.cpp:125
movenum_t addBlackCaptureIfValid(bBoard const &b, case_t const &cf, case_t const &to)
Definition movelist.cpp:112
movenum_t addBlackMoveIfValid(bBoard const &b, bMove const &m)
Only add move to movelist if valid.
Definition movelist.cpp:102
movenum_t addWhiteMoveIfValid(bBoard const &b, bMove const &m)
Only add move to movelist if valid.
Definition movelist.cpp:79
virtual ~bPieceColour()
Definition piece.cpp:226
bPieceColour(side_t s)
Definition piece.cpp:221
bool isAttackedByPiece(bBoard const &b, column_t const fromcol, rank_t const fromrank, piece_t const cPiece, int8_t const ri, int8_t const ci) const
Return true if position is attacked by opponent respecting move offsets.
Definition piece.cpp:359
bool isAttackedBySlider(bBoard const &b, column_t const fromcol, rank_t const fromrank, piece_t const cPiece, piece_t const cPiece2, int8_t const ri, int8_t const ci) const
Return true if position is attacked by opponent respecting move offsets.
Definition piece.cpp:377
piece representation
Definition piece.h:85
static bool isOwnColour(side_t const s, piece_t const p)
static class member function
Definition piece.cpp:198
side_t toMove() const
Definition piece.cpp:168
static bPiece * getPieceClass(piece_t const piece)
static class member function
Definition piece.cpp:130
static cpiece_t getPieceChar(piece_t const p)
static class member function
Definition piece.cpp:178
static bool isBlackPiece(piece_t const p)
static class member function
Definition piece.cpp:213
piece_t getPiece() const
Definition piece.h:99
static bool isWhitePiece(piece_t const p)
static class member function
Definition piece.cpp:206
virtual ~bPiece()
Definition piece.cpp:30
static bool isOpponent(side_t const s, piece_t const p)
static class member function
Definition piece.cpp:190
bPiece()
Definition piece.cpp:21
static const std::string getPieceStrUpper(piece_t const piece)
static class member function
Definition piece.cpp:136
bool hasValidMovePreflightCheck(bBoard &b, case_t const &cf) final
Definition piece.cpp:1087
movenum_t GenerateMoves(bBoard const &b, case_t const &cf, bMoveList &ml) final
Definition piece.cpp:1105
bool hasValidMovePreflightCheck(bBoard &b, case_t const &cf) final
Definition piece.cpp:1187
movenum_t GenerateMoves(bBoard const &b, case_t const &cf, bMoveList &ml) final
Definition piece.cpp:1213
bool hasValidMovePreflightCheck(bBoard &b, case_t const &cf) final
Definition piece.cpp:1029
movenum_t GenerateMoves(bBoard const &b, case_t const &cf, bMoveList &ml) final
Definition piece.cpp:1055
movenum_t addCapturePromotionMove(bBoard const &b, case_t const &cf, int8_t const ci, bMoveList &ml) const
Test move is possible, single step move capture only move.
Definition piece.cpp:838
movenum_t GenerateMoves(bBoard const &b, case_t const &cf, bMoveList &ml) final
Definition piece.cpp:922
bool hasValidMovePreflightCheck(bBoard &b, case_t const &cf) final
check if there is at least one move possible currently, relies on full move generation for pawn
Definition piece.cpp:910
movenum_t addNonCapturePromotionMove(bBoard const &b, case_t const &cf, bMoveList &ml) const
Test move is possible, single step move non capture move.
Definition piece.cpp:813
movenum_t addEPMove(bBoard const &b, case_t const &cf, int8_t const ci, bMoveList &ml) const
Test move is possible, e.p.
Definition piece.cpp:878
movenum_t addCapturePawnMove(bBoard const &b, case_t const &cf, int8_t const ci, bMoveList &ml) const
Definition piece.cpp:780
movenum_t addNonCapturePawnMove(bBoard const &b, case_t const &cf, bMoveList &ml) const
Test move is possible, single step move non capture move.
Definition piece.cpp:681
movenum_t addNonCaptureDoublePawnMove(bBoard const &b, case_t const &cf, bMoveList &ml) const
Definition piece.cpp:754
~bWhitePiece() override
Definition piece.cpp:336
movenum_t addMoves(bBoard const &b, case_t const &cf, int8_t const ri, int8_t const ci, bMoveList &ml) const final
Add moves for Queen, Rook and Bishop.
Definition piece.cpp:576
bool isAttacked(bBoard const &b, case_t const &cf) const override
Check if piece on position is attacked, start with piece always on board and then with pieces with gr...
Definition piece.cpp:237
movenum_t addMove(bBoard const &b, case_t const &cf, int8_t const ri, int8_t const ci, bMoveList &ml) const final
Check for in-check position, single step move used for King and Knight.
Definition piece.cpp:536
bool canMovePreflightCheck(bBoard &b, case_t const &cf, int8_t const ri, int8_t const ci) const override
Check if move could be added by just checking there is not check.
Definition piece.cpp:408
bool hasValidMovePreflightCheck(bBoard &b, case_t const &cf) final
Definition piece.cpp:1129
movenum_t GenerateMoves(bBoard const &b, case_t const &cf, bMoveList &ml) final
Definition piece.cpp:1155
movenum_t GenerateMoves(bBoard const &b, case_t const &cf, bMoveList &ml) final
Definition piece.cpp:1005
bool hasValidMovePreflightCheck(bBoard &b, case_t const &cf) final
Definition piece.cpp:987
Allow index mapper for char values of piece into int in 1-12 range to reduce space and easy initialis...
Definition eval.h:43
static boardbitmap_t kingmoves[64]
Definition piece.cpp:17
static bPiece * pieceinstances[tPiece::P_SIZE]
Definition piece.cpp:16
static boardbitmap_t knightmoves[64]
Definition piece.cpp:18
static piece_t bPieceIndex[128]
Definition piece.cpp:14
static cpiece_t bPieceMapper[tPiece::P_SIZE]
Definition piece.cpp:15
void bPiece_dtor()
Definition piece.cpp:120
void bPiece_ctor()
Definition piece.cpp:34
boardbitmap_t destinationbits_knight(case_t const iCase)
Definition piece.cpp:97
boardbitmap_t destinationbits_king(case_t const iCase)
Definition piece.cpp:84
boardbitmap_t destinationbits(case_t const iCase, int8_t const ri, int8_t const ci)
Definition piece.cpp:110
#define S_P_EMPTY
Definition piece.h:17
#define S_P_ROOK
Definition piece.h:16
enum tSide side_t
Definition piece.h:66
@ C_W_KNIGHT
Definition piece.h:23
@ C_W_PAWN
Definition piece.h:24
@ C_B_QUEEN
Definition piece.h:31
@ C_W_ROOK
Definition piece.h:26
@ C_EMPTY
Definition piece.h:20
@ C_B_BISHOP
Definition piece.h:27
@ C_W_QUEEN
Definition piece.h:25
@ C_B_KNIGHT
Definition piece.h:29
@ C_B_PAWN
Definition piece.h:30
@ C_W_BISHOP
Definition piece.h:21
@ C_B_ROOK
Definition piece.h:32
@ C_B_KING
Definition piece.h:28
@ C_W_KING
Definition piece.h:22
@ W_PAWN
Definition piece.h:39
@ W_KNIGHT
Definition piece.h:39
@ P_SIZE
Definition piece.h:41
@ 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
@ P_EMPTY
Definition piece.h:38
@ B_KNIGHT
Definition piece.h:40
@ W_KING
Definition piece.h:39
@ B_PAWN
Definition piece.h:40
@ B_QUEEN
Definition piece.h:40
@ W_BISHOP
Definition piece.h:39
enum tPiece piece_t
Definition piece.h:44
#define S_P_PAWN
Definition piece.h:14
#define S_P_QUEEN
Definition piece.h:15
enum tCPiece cpiece_t
Definition piece.h:35
#define S_P_BISHOP
Definition piece.h:11
#define S_P_KNIGHT
Definition piece.h:13
#define S_P_KING
Definition piece.h:12
@ STAT_KNIGHT
Definition piece.h:56
tSide
Definition piece.h:60
@ SIDE_BLACK
@ SIDE_WHITE
@ SIDE_UNDEFINED