int Blind (smove move) { int sq_to = move.to; int sq_fr = move.from; int pc_fr = b.pieces[sq_fr]; int pc_to = b.pieces[sq_to]; int val = e.SORT_VALUE[pc_to]; /* captures by pawn do not lose material */ if (pc_fr == PAWN) return 1; /* Captures "lower takes higher" (as well as BxN) are good by definition. */ if (e.SORT_VALUE[pc_to] >= e.SORT_VALUE[pc_fr] - 50) return 1; /* Make the first capture, so that X-ray defender show up*/ clearSq(sq_fr); /* Captures of undefended pieces are good by definition */ if (!isAttacked(!b.stm, sq_to)) { fillSq(b.stm, pc_fr, sq_fr); return 1; } fillSq(b.stm, pc_fr, sq_fr); return 0; // of other captures we know nothing, Jon Snow! }
bool Board::isCheck(int checked_side) { int king_square = -1; for (int sq = 0; sq < 64; sq++) { if (color[sq] == checked_side && pieces[sq] == K) { king_square = sq; break; } } int checking_side = (checked_side == WHITE) ? BLACK : WHITE; return isAttacked(king_square, checking_side); }
bool Board::invalidate() { Figure::Color ocolor = Figure::otherColor(color_); int ki_pos = kingPos(color_); int oki_pos = kingPos(ocolor); state_ = Ok; if ( isAttacked(color_, oki_pos) ) { state_ = Invalid; return false; } if ( isAttacked(ocolor, ki_pos) ) state_ |= UnderCheck; verifyChessDraw(); if ( drawState() ) return true; int cnum = findCheckingFigures(ocolor, ki_pos); if ( cnum > 2 ) { state_ = Invalid; return false; } else if ( cnum > 0 ) { state_ |= UnderCheck; } verifyState(); return true; }
std::vector<move_t> Board::generateMoves() { std::vector<move_t> moves; int piece; int from, to; move_t move; for (int sq = 0; sq < 64; sq++) { if (color[sq] != side) continue; from = sq; piece = pieces[sq]; // Pawns if (piece == P) { // move one square forward to = mailbox[mailbox64[sq] - 10]; if (to != -1 && color[to] == EMPTY) { // promotes on back rank if (sq/8 == 1) { for (Piece piece : {N, B, R, Q}) { move = {from, to, piece, 4}; moves.push_back(move); } } else { move = {from, to, _, 0}; moves.push_back(move); } // moves two squares from second rank if (sq/8 == 6) { to = mailbox[mailbox64[sq] - 20]; if (to != -1 && color[to] == EMPTY) { move = {from, to, _, 16}; moves.push_back(move); } } } // capture diagonally for (int offset : {-9, -11}) { to = mailbox[mailbox64[sq] + offset]; if (to == -1 || color[to] != xside) continue; // promotes on back rank if (sq/8 == 1) { for (Piece piece : {N, B, R, Q}) { move = {from, to, piece, 5}; moves.push_back(move); } } else if (to == ep) { move = {from, to, _, 8}; moves.push_back(move); } else { move = {from, to, _, 1}; moves.push_back(move); } } } // other pieces else { for (int offset : offsets[piece]) { for (int i = 1;; i++) { to = mailbox[mailbox64[sq] + i*offset]; if (to == -1) break; // can't move off board if (color[to] == side) break; // can't capture own piece if (color[to] == xside) { move = {from, to, _, 1}; moves.push_back(move); break; // can't slide past a capture } move = {from, to, _, 0}; moves.push_back(move); if (!slide[piece]) break; // stop if piece can't slide } } } // castling if (piece == K && side_castle) { if (side == WHITE) { // kingside if ((side_castle & 1) && color[61] == EMPTY && color[62] == EMPTY && !isAttacked(60, xside) && !isAttacked(61, xside) && !isAttacked(62, xside)) { to = 62; // g1 move = {from, to, _, 2}; moves.push_back(move); } // queenside if ((side_castle & 2) && color[57] == EMPTY && color[58] == EMPTY && color[59] == EMPTY && !isAttacked(58, xside) && !isAttacked(59, xside) && !isAttacked(60, xside)) { to = 58; // c1 move = {from, to, _, 2}; moves.push_back(move); } } else { // queenside if ((side_castle & 2) && color[60] == EMPTY && color[61] == EMPTY && color[62] == EMPTY && !isAttacked(59, xside) && !isAttacked(60, xside) && !isAttacked(61, xside)) { to = 61; // c8 move = {from, to, _, 2}; moves.push_back(move); } // kingside if ((side_castle & 1) && color[57] == EMPTY && color[58] == EMPTY && !isAttacked(57, xside) && !isAttacked(58, xside) && !isAttacked(59, xside)) { to = 57; // g8 move = {from, to, _, 2}; moves.push_back(move); } } } } return moves; }
bool Position::inCheck() { int kingSquare; if (toMove == WHITE) kingSquare = whiteKing; else kingSquare = blackKing; return isAttacked(kingSquare); }
int movegen(int index) { // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // This is KENNY's pseudo-legal bitmap move generator, // using magic multiplication instead of rotated bitboards. // There is no check if a move leaves the king in check // The first free location in moveBuffer[] is supplied in index, // and the new first free location is returned // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ unsigned char opponentSide; unsigned int from, to; BitMap tempPiece, tempMove; BitMap targetBitmap, freeSquares; Move move; move.clear(); opponentSide = !board.nextMove; freeSquares = ~board.occupiedSquares; // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Black to move // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ if (board.nextMove) // black to move { targetBitmap = ~board.blackPieces; // we cannot capture one of our own pieces! // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Black Pawns // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ move.setPiec(BLACK_PAWN); tempPiece = board.blackPawns; while (tempPiece) { from = firstOne(tempPiece); move.setFrom(from); tempMove = BLACK_PAWN_MOVES[from] & freeSquares; // normal moves if (RANKS[from] == 7 && tempMove) tempMove |= (BLACK_PAWN_DOUBLE_MOVES[from] & freeSquares); // add double moves tempMove |= BLACK_PAWN_ATTACKS[from] & board.whitePieces; // add captures while (tempMove) { to = firstOne(tempMove); move.setTosq(to); move.setCapt(board.square[to]); if ((RANKS[to]) == 1) // add promotions { move.setProm(BLACK_QUEEN); board.moveBuffer[index++].moveInt = move.moveInt; move.setProm(BLACK_ROOK); board.moveBuffer[index++].moveInt = move.moveInt; move.setProm(BLACK_BISHOP); board.moveBuffer[index++].moveInt = move.moveInt; move.setProm(BLACK_KNIGHT); board.moveBuffer[index++].moveInt = move.moveInt; move.setProm(EMPTY); } else { board.moveBuffer[index++].moveInt = move.moveInt; } tempMove ^= BITSET[to]; } // add en-passant captures: if (board.epSquare) // do a quick check first { if (BLACK_PAWN_ATTACKS[from] & BITSET[board.epSquare]) { if (board.whitePawns & BITSET[board.epSquare + 8]) // final check to protect against same color capture during null move { move.setProm(BLACK_PAWN); move.setCapt(WHITE_PAWN); move.setTosq(board.epSquare); board.moveBuffer[index++].moveInt = move.moveInt; } } } tempPiece ^= BITSET[from]; move.setProm(EMPTY); } // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Black Knights // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ move.setPiec(BLACK_KNIGHT); tempPiece = board.blackKnights; while (tempPiece) { from = firstOne(tempPiece); move.setFrom(from); tempMove = KNIGHT_ATTACKS[from] & targetBitmap; while (tempMove) { to = firstOne(tempMove); move.setTosq(to); move.setCapt(board.square[to]); board.moveBuffer[index++].moveInt = move.moveInt; tempMove ^= BITSET[to]; } tempPiece ^= BITSET[from]; } // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Black Bishops // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ move.setPiec(BLACK_BISHOP); tempPiece = board.blackBishops; while (tempPiece) { from = firstOne(tempPiece); move.setFrom(from); tempMove = BISHOPMOVES(from); // see Macro's while (tempMove) { to = firstOne(tempMove); move.setTosq(to); move.setCapt(board.square[to]); board.moveBuffer[index++].moveInt = move.moveInt; tempMove ^= BITSET[to]; } tempPiece ^= BITSET[from]; } // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Black Rooks // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ move.setPiec(BLACK_ROOK); tempPiece = board.blackRooks; while (tempPiece) { from = firstOne(tempPiece); move.setFrom(from); tempMove = ROOKMOVES(from); // see Macro's while (tempMove) { to = firstOne(tempMove); move.setTosq(to); move.setCapt(board.square[to]); board.moveBuffer[index++].moveInt = move.moveInt; tempMove ^= BITSET[to]; } tempPiece ^= BITSET[from]; } // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Black Queens // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ move.setPiec(BLACK_QUEEN); tempPiece = board.blackQueens; while (tempPiece) { from = firstOne(tempPiece); move.setFrom(from); tempMove = QUEENMOVES(from); // see Macro's while (tempMove) { to = firstOne(tempMove); move.setTosq(to); move.setCapt(board.square[to]); board.moveBuffer[index++].moveInt = move.moveInt; tempMove ^= BITSET[to]; } tempPiece ^= BITSET[from]; } // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Black King // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ move.setPiec(BLACK_KING); tempPiece = board.blackKing; while (tempPiece) { from = firstOne(tempPiece); move.setFrom(from); tempMove = KING_ATTACKS[from] & targetBitmap; while (tempMove) { to = firstOne(tempMove); move.setTosq(to); move.setCapt(board.square[to]); board.moveBuffer[index++].moveInt = move.moveInt; tempMove ^= BITSET[to]; } // Black 0-0 Castling: if (board.castleBlack & CANCASTLEOO) { if (!(maskFG[1] & board.occupiedSquares)) { if (!isAttacked(maskEG[BLACK_MOVE], WHITE_MOVE)) { board.moveBuffer[index++].moveInt = BLACK_OO_CASTL; // predefined unsigned int } } } // Black 0-0-0 Castling: if (board.castleBlack & CANCASTLEOOO) { if (!(maskBD[1] & board.occupiedSquares)) { if (!isAttacked(maskCE[BLACK_MOVE], WHITE_MOVE)) { board.moveBuffer[index++].moveInt = BLACK_OOO_CASTL; // predefined unsigned int } } } tempPiece ^= BITSET[from]; move.setProm(EMPTY); } } // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // White to move // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ else { targetBitmap = ~board.whitePieces; // we cannot capture one of our own pieces! // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // White Pawns // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ move.setPiec(WHITE_PAWN); tempPiece = board.whitePawns; while (tempPiece) { from = firstOne(tempPiece); move.setFrom(from); tempMove = WHITE_PAWN_MOVES[from] & freeSquares; // normal moves if (RANKS[from] == 2 && tempMove) tempMove |= (WHITE_PAWN_DOUBLE_MOVES[from] & freeSquares); // add double moves tempMove |= WHITE_PAWN_ATTACKS[from] & board.blackPieces; // add captures while (tempMove) { to = firstOne(tempMove); move.setTosq(to); move.setCapt(board.square[to]); if ((RANKS[to]) == 8) // add promotions { move.setProm(WHITE_QUEEN); board.moveBuffer[index++].moveInt = move.moveInt; move.setProm(WHITE_ROOK); board.moveBuffer[index++].moveInt = move.moveInt; move.setProm(WHITE_BISHOP); board.moveBuffer[index++].moveInt = move.moveInt; move.setProm(WHITE_KNIGHT); board.moveBuffer[index++].moveInt = move.moveInt; move.setProm(EMPTY); } else { board.moveBuffer[index++].moveInt = move.moveInt; } tempMove ^= BITSET[to]; } // add en-passant captures: if (board.epSquare) // do a quick check first { if (WHITE_PAWN_ATTACKS[from] & BITSET[board.epSquare]) { if (board.blackPawns & BITSET[board.epSquare - 8]) // final check to protect against same color capture during null move { move.setProm(WHITE_PAWN); move.setCapt(BLACK_PAWN); move.setTosq(board.epSquare); board.moveBuffer[index++].moveInt = move.moveInt; } } } tempPiece ^= BITSET[from]; move.setProm(EMPTY); } // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // White Knights // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ move.setPiec(WHITE_KNIGHT); tempPiece = board.whiteKnights; while (tempPiece) { from = firstOne(tempPiece); move.setFrom(from); tempMove = KNIGHT_ATTACKS[from] & targetBitmap; while (tempMove) { to = firstOne(tempMove); move.setTosq(to); move.setCapt(board.square[to]); board.moveBuffer[index++].moveInt = move.moveInt; tempMove ^= BITSET[to]; } tempPiece ^= BITSET[from]; } // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // White Bishops // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ move.setPiec(WHITE_BISHOP); tempPiece = board.whiteBishops; while (tempPiece) { from = firstOne(tempPiece); move.setFrom(from); tempMove = BISHOPMOVES(from); // see Macro's while (tempMove) { to = firstOne(tempMove); move.setTosq(to); move.setCapt(board.square[to]); board.moveBuffer[index++].moveInt = move.moveInt; tempMove ^= BITSET[to]; } tempPiece ^= BITSET[from]; } // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // White Rooks // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ move.setPiec(WHITE_ROOK); tempPiece = board.whiteRooks; while (tempPiece) { from = firstOne(tempPiece); move.setFrom(from); tempMove = ROOKMOVES(from); // see Macro's while (tempMove) { to = firstOne(tempMove); move.setTosq(to); move.setCapt(board.square[to]); board.moveBuffer[index++].moveInt = move.moveInt; tempMove ^= BITSET[to]; } tempPiece ^= BITSET[from]; } // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // White Queens // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ move.setPiec(WHITE_QUEEN); tempPiece = board.whiteQueens; while (tempPiece) { from = firstOne(tempPiece); move.setFrom(from); tempMove = QUEENMOVES(from); // see Macro's while (tempMove) { to = firstOne(tempMove); move.setTosq(to); move.setCapt(board.square[to]); board.moveBuffer[index++].moveInt = move.moveInt; tempMove ^= BITSET[to]; } tempPiece ^= BITSET[from]; } // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // White king // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ move.setPiec(WHITE_KING); tempPiece = board.whiteKing; while (tempPiece) { from = firstOne(tempPiece); move.setFrom(from); tempMove = KING_ATTACKS[from] & targetBitmap; while (tempMove) { to = firstOne(tempMove); move.setTosq(to); move.setCapt(board.square[to]); board.moveBuffer[index++].moveInt = move.moveInt; tempMove ^= BITSET[to]; } // White 0-0 Castling: if (board.castleWhite & CANCASTLEOO) { if (!(maskFG[0] & board.occupiedSquares)) { if (!isAttacked(maskEG[WHITE_MOVE], BLACK_MOVE)) { board.moveBuffer[index++].moveInt = WHITE_OO_CASTL; // predefined unsigned int } } } // White 0-0-0 Castling: if (board.castleWhite & CANCASTLEOOO) { if (!(maskBD[0] & board.occupiedSquares)) { if (!isAttacked(maskCE[WHITE_MOVE], BLACK_MOVE)) { board.moveBuffer[index++].moveInt = WHITE_OOO_CASTL; // predefined unsigned int } } } tempPiece ^= BITSET[from]; move.setProm(EMPTY); } } return index; }