unsigned int bitbaseIndexFull(File pawnFile, Rank pawnRank, Sq wKingSq, Colour stm, Sq bKingSq) { assert(pawnFile>=FileA && pawnFile<=FileD); assert(rankIsValid(pawnRank)); assert(sqIsValid(wKingSq)); assert(colourIsValid(stm)); assert(sqIsValid(bKingSq)); return (((pawnFile*RankNB+pawnRank)*SqNB+wKingSq)*ColourNB+stm)*SqNB+bKingSq; }
BitBaseResultFull bitbaseComputeStaticResult(Sq pawnSq, Sq wKingSq, Colour stm, Sq bKingSq) { // Sanity checks. assert(sqIsValid(pawnSq) && sqFile(pawnSq)<=FileD); assert(sqIsValid(wKingSq)); assert(colourIsValid(stm)); assert(sqIsValid(bKingSq)); // Init. BB wKingAtks=attacksKing(wKingSq); BB bKingAtks=attacksKing(bKingSq); BB pawnAtks=attacksPawn(pawnSq, ColourWhite); BB wKingBB=bbSq(wKingSq); BB bKingBB=bbSq(bKingSq); BB pawnBB=bbSq(pawnSq); BB occ=(pawnBB | wKingBB | bKingBB); // If any pieces occupy the same square, or the side not on move is in check, invalid position. if (pawnSq==wKingSq || pawnSq==bKingSq || wKingSq==bKingSq || // Pieces overlap. sqRank(pawnSq)==Rank1 || // Pawn on rank 1. (wKingAtks & bKingBB)!=BBNone || // Kings are adjacent. (stm==ColourWhite && (pawnAtks & bKingBB)!=BBNone)) // White to move, black king attacked by pawn. return BitBaseResultFullInvalid; // If pawn can promote without capture, win. if (sqRank(pawnSq)==Rank7 && stm==ColourWhite) { Sq promoSq=sqNorth(pawnSq,1); if (promoSq!=wKingSq && promoSq!=bKingSq && // Promotion square empty. ((bbSq(promoSq) & bKingAtks)==BBNone || (bbSq(promoSq) & wKingAtks)!=BBNone)) // Promotion square is safe. return BitBaseResultFullWin; } // If black can capture pawn, draw. bool pawnAttacked=((bKingAtks & pawnBB)!=BBNone); bool pawnDefended=((wKingAtks & pawnBB)!=BBNone); if (stm==ColourBlack && pawnAttacked && !pawnDefended) return BitBaseResultFullDraw; // If 'pawn' is on 8th rank, win (we have already shown that it cannot be captured). if (sqRank(pawnSq)==Rank8) return BitBaseResultFullWin; // If no moves available for stm, draw (stalemate). if (stm==ColourWhite) { BB safe=~(bKingAtks | occ); if ((wKingAtks & safe)==BBNone && // No king moves. (sqNorth(pawnSq,1)==wKingSq || sqNorth(pawnSq,1)==bKingSq)) // No pawn moves. return BitBaseResultFullDraw; } else { BB safe=~(wKingAtks | pawnAtks | occ); // We already check if black can capture pawn, hence assume defended. if ((bKingAtks & safe)==BBNone) return BitBaseResultFullDraw; } // Unable to statically evaluate the position. return BitBaseResultFullUnknown; }
unsigned int bitbaseIndex(File pawnFile, Rank pawnRank, Sq wKingSq, Colour stm) { assert(pawnFile>=FileA && pawnFile<=FileD); assert(pawnRank>=Rank2 && pawnRank<=Rank7); assert(sqIsValid(wKingSq)); assert(colourIsValid(stm)); return ((pawnFile*RankNB+pawnRank)*SqNB+wKingSq)*ColourNB+stm; }
bool posIsSqAttackedByColour(const Pos *pos, Sq sq, Colour colour) { assert(sqIsValid(sq)); assert(colourIsValid(colour)); BB occ=posGetBBAll(pos); // Pawns. if (bbForwardOne(bbWingify(posGetBBPiece(pos, pieceMake(PieceTypePawn, colour))), colour) & bbSq(sq)) return true; // Knights. if (attacksKnight(sq) & posGetBBPiece(pos, pieceMake(PieceTypeKnight, colour))) return true; // Bishops. BB bishopSet=attacksBishop(sq, occ); if (bishopSet & (posGetBBPiece(pos, pieceMake(PieceTypeBishopL, colour)) | posGetBBPiece(pos, pieceMake(PieceTypeBishopD, colour)))) return true; // Rooks. BB rookSet=attacksRook(sq, occ); if (rookSet & posGetBBPiece(pos, pieceMake(PieceTypeRook, colour))) return true; // Queens. if ((bishopSet | rookSet) & posGetBBPiece(pos, pieceMake(PieceTypeQueen, colour))) return true; // King. if (attacksKing(sq) & posGetBBPiece(pos, pieceMake(PieceTypeKing, colour))) return true; return false; }
BitBaseResult bitbaseProbeRaw(Sq pawnSq, Sq wKingSq, Sq bKingSq, Colour stm) { // Sanity checks. assert(sqIsValid(pawnSq)); assert(sqIsValid(wKingSq)); assert(sqIsValid(bKingSq)); assert(colourIsValid(stm)); // Adjust so pawn is in left half of board (on files A, B, C or D). File pawnFile=sqFile(pawnSq); Rank pawnRank=sqRank(pawnSq); if (pawnFile>FileD) { pawnFile=fileMirror(pawnFile); wKingSq=sqMirror(wKingSq); bKingSq=sqMirror(bKingSq); } // Probe. unsigned int index=bitbaseIndex(pawnFile, pawnRank, wKingSq, stm); return (bitbase[index]>>bKingSq)&1; }
BitBaseResultFull bitbaseComputeDynamicResult(const BitBaseResultFull *array, Sq pawnSq, Sq wKingSq, Colour stm, Sq bKingSq) { // Sanity checks. assert(sqIsValid(pawnSq) && sqFile(pawnSq)<=FileD && sqRank(pawnSq)>=Rank2 && sqRank(pawnSq)<=Rank7); assert(sqIsValid(wKingSq)); assert(colourIsValid(stm)); assert(sqIsValid(bKingSq)); // If white to move and any children are wins, win. If white to move and // all children are draws, draw. // If black to move and any children are draws, draw. If black to move // and all children are wins, win. File pawnFile=sqFile(pawnSq); Rank pawnRank=sqRank(pawnSq); Colour xstm=colourSwap(stm); if (stm==ColourWhite) { bool allDraws=true; // King moves. BB set=attacksKing(wKingSq); while(set) { unsigned int newIndex=bitbaseIndexFull(pawnFile, pawnRank, bbScanReset(&set), xstm, bKingSq); switch(array[newIndex]) { case BitBaseResultFullInvalid: break; // Invalid move. case BitBaseResultFullUnknown: allDraws=false; break; case BitBaseResultFullDraw: break; case BitBaseResultFullWin: return BitBaseResultFullWin; break; } } // Standard pawn move forward. // We do not need to test for moving to 8th rank or into either of the kings as such positions will be marked already. unsigned int newIndex=bitbaseIndexFull(pawnFile, pawnRank+1, wKingSq, xstm, bKingSq); bool singlePushOk=true; switch(array[newIndex]) { case BitBaseResultFullInvalid: singlePushOk=false; break; // Invalid move. case BitBaseResultFullUnknown: allDraws=false; break; case BitBaseResultFullDraw: break; case BitBaseResultFullWin: return BitBaseResultFullWin; break; } // Double pawn move. // Again we do not need to check for moving into either of the kings. if (pawnRank==Rank2 && singlePushOk) { unsigned int newIndex=bitbaseIndexFull(pawnFile, pawnRank+2, wKingSq, xstm, bKingSq); switch(array[newIndex]) { case BitBaseResultFullInvalid: break; // Invalid move. case BitBaseResultFullUnknown: allDraws=false; break; case BitBaseResultFullDraw: break; case BitBaseResultFullWin: return BitBaseResultFullWin; break; } } return (allDraws ? BitBaseResultFullDraw : BitBaseResultFullUnknown); } else { // King moves. bool allWins=true; BB set=attacksKing(bKingSq); while(set) { unsigned int newIndex=bitbaseIndexFull(pawnFile, pawnRank, wKingSq, xstm, bbScanReset(&set)); switch(array[newIndex]) { case BitBaseResultFullInvalid: break; // Invalid move. case BitBaseResultFullUnknown: allWins=false; break; case BitBaseResultFullDraw: return BitBaseResultFullDraw; break; case BitBaseResultFullWin: break; } } return (allWins ? BitBaseResultFullWin : BitBaseResultFullUnknown); } assert(false); return BitBaseResultFullInvalid; }
Piece posGetPieceOnSq(const Pos *pos, Sq sq) { assert(sqIsValid(sq)); return (pos->array64[sq]>>4); }
Move moveMake(Sq fromSq, Sq toSq, Piece toPiece) { assert(sqIsValid(fromSq)); assert(sqIsValid(toSq)); assert(pieceIsValid(toPiece)); return (((Move)fromSq)<<MoveShiftFromSq)|(((Move)toSq)<<MoveShiftToSq)|(((Move)toPiece)<<MoveShiftToPiece); }