public static int generate_promotions(ExtMove[] mlist, int mPos, Bitboard pawnsOn7, Bitboard target, CheckInfo ci, GenType Type, Square Delta) { Bitboard b = BitBoard.shift_bb(pawnsOn7, Delta) & target; while (b != 0) { Square to = BitBoard.pop_lsb(ref b); if (Type == GenTypeS.CAPTURES || Type == GenTypeS.EVASIONS || Type == GenTypeS.NON_EVASIONS) { mlist[mPos++].move = Types.make(to - Delta, to, MoveTypeS.PROMOTION, PieceTypeS.QUEEN); } if (Type == GenTypeS.QUIETS || Type == GenTypeS.EVASIONS || Type == GenTypeS.NON_EVASIONS) { mlist[mPos++].move = Types.make(to - Delta, to, MoveTypeS.PROMOTION, PieceTypeS.ROOK); mlist[mPos++].move = Types.make(to - Delta, to, MoveTypeS.PROMOTION, PieceTypeS.BISHOP); mlist[mPos++].move = Types.make(to - Delta, to, MoveTypeS.PROMOTION, PieceTypeS.KNIGHT); } // Knight promotion is the only promotion that can give a direct check // that's not already included in the queen promotion. if (Type == GenTypeS.QUIET_CHECKS && (BitBoard.StepAttacksBB[PieceS.W_KNIGHT][to] & BitBoard.SquareBB[ci.ksq]) != 0) { mlist[mPos++].move = Types.make(to - Delta, to, MoveTypeS.PROMOTION, PieceTypeS.KNIGHT); } } return(mPos); }
public static int generate_castling(Position pos, ExtMove[] mlist, int mPos, Color us, CheckInfo ci, CastlingRight Cr, bool Checks, bool Chess960) { bool KingSide = (Cr == CastlingRightS.WHITE_OO || Cr == CastlingRightS.BLACK_OO); if (pos.castling_impeded(Cr) || 0 == pos.can_castle_castleright(Cr)) { return(mPos); } // After castling, the rook and king final positions are the same in Chess960 // as they would be in standard chess. Square kfrom = pos.king_square(us); Square rfrom = pos.castling_rook_square(Cr); Square kto = Types.relative_square(us, KingSide ? SquareS.SQ_G1 : SquareS.SQ_C1); Bitboard enemies = pos.pieces_color(Types.notColor(us)); Debug.Assert(0 == pos.checkers()); Square K = Chess960 ? kto > kfrom ? SquareS.DELTA_W : SquareS.DELTA_E : KingSide ? SquareS.DELTA_W : SquareS.DELTA_E; for (Square s = kto; s != kfrom; s += K) { if ((pos.attackers_to(s) & enemies) != 0) { return(mPos); } } // Because we generate only legal castling moves we need to verify that // when moving the castling rook we do not discover some hidden checker. // For instance an enemy queen in SQ_A1 when castling rook is in SQ_B1. if (Chess960 && (BitBoard.attacks_bb_SBBPT(kto, pos.pieces() ^ BitBoard.SquareBB[rfrom], PieceTypeS.ROOK) & pos.pieces_color_piecetype(Types.notColor(us), PieceTypeS.ROOK, PieceTypeS.QUEEN)) != 0) { return(mPos); } Move m = Types.make(kfrom, rfrom, MoveTypeS.CASTLING); if (Checks && !pos.gives_check(m, ci)) { return(mPos); } mlist[mPos++].move = m; return(mPos); }
public static int generate_pawn_moves(Position pos, ExtMove[] mlist, int mPos, Bitboard target, CheckInfo ci, Color Us, GenType Type) { // Compute our parametrized parameters at compile time, named according to // the point of view of white side. Color Them = (Us == ColorS.WHITE ? ColorS.BLACK : ColorS.WHITE); Bitboard TRank8BB = (Us == ColorS.WHITE ? BitBoard.Rank8BB : BitBoard.Rank1BB); Bitboard TRank7BB = (Us == ColorS.WHITE ? BitBoard.Rank7BB : BitBoard.Rank2BB); Bitboard TRank3BB = (Us == ColorS.WHITE ? BitBoard.Rank3BB : BitBoard.Rank6BB); Square Up = (Us == ColorS.WHITE ? SquareS.DELTA_N : SquareS.DELTA_S); Square Right = (Us == ColorS.WHITE ? SquareS.DELTA_NE : SquareS.DELTA_SW); Square Left = (Us == ColorS.WHITE ? SquareS.DELTA_NW : SquareS.DELTA_SE); Bitboard b1, b2, dc1, dc2, emptySquares = 0; Bitboard pawnsOn7 = pos.pieces_color_piecetype(Us, PieceTypeS.PAWN) & TRank7BB; Bitboard pawnsNotOn7 = pos.pieces_color_piecetype(Us, PieceTypeS.PAWN) & ~TRank7BB; Bitboard enemies = (Type == GenTypeS.EVASIONS ? pos.pieces_color(Them) & target : Type == GenTypeS.CAPTURES ? target : pos.pieces_color(Them)); // Single and double pawn pushes, no promotions if (Type != GenTypeS.CAPTURES) { emptySquares = (Type == GenTypeS.QUIETS || Type == GenTypeS.QUIET_CHECKS ? target : ~pos.pieces()); b1 = BitBoard.shift_bb(pawnsNotOn7, Up) & emptySquares; b2 = BitBoard.shift_bb(b1 & TRank3BB, Up) & emptySquares; if (Type == GenTypeS.EVASIONS) // Consider only blocking squares { b1 &= target; b2 &= target; } if (Type == GenTypeS.QUIET_CHECKS) { b1 &= pos.attacks_from_pawn(ci.ksq, Them); b2 &= pos.attacks_from_pawn(ci.ksq, Them); // Add pawn pushes which give discovered check. This is possible only // if the pawn is not on the same file as the enemy king, because we // don't generate captures. Note that a possible discovery check // promotion has been already generated among captures. if ((pawnsNotOn7 & ci.dcCandidates) != 0) { dc1 = BitBoard.shift_bb(pawnsNotOn7 & ci.dcCandidates, Up) & emptySquares & ~BitBoard.file_bb_square(ci.ksq); dc2 = BitBoard.shift_bb(dc1 & TRank3BB, Up) & emptySquares; b1 |= dc1; b2 |= dc2; } } while (b1 != 0) { Square to = BitBoard.pop_lsb(ref b1); mlist[mPos++].move = Types.make_move(to - Up, to); } while (b2 != 0) { Square to = BitBoard.pop_lsb(ref b2); mlist[mPos++].move = Types.make_move(to - Up - Up, to); } } // Promotions and underpromotions if (pawnsOn7 != 0 && (Type != GenTypeS.EVASIONS || (target & TRank8BB) != 0)) { if (Type == GenTypeS.CAPTURES) { emptySquares = ~pos.pieces(); } if (Type == GenTypeS.EVASIONS) { emptySquares &= target; } mPos = generate_promotions(mlist, mPos, pawnsOn7, enemies, ci, Type, Right); mPos = generate_promotions(mlist, mPos, pawnsOn7, enemies, ci, Type, Left); mPos = generate_promotions(mlist, mPos, pawnsOn7, emptySquares, ci, Type, Up); } // Standard and en-passant captures if (Type == GenTypeS.CAPTURES || Type == GenTypeS.EVASIONS || Type == GenTypeS.NON_EVASIONS) { b1 = BitBoard.shift_bb(pawnsNotOn7, Right) & enemies; b2 = BitBoard.shift_bb(pawnsNotOn7, Left) & enemies; while (b1 != 0) { Square to = BitBoard.pop_lsb(ref b1); mlist[mPos++].move = Types.make_move(to - Right, to); } while (b2 != 0) { Square to = BitBoard.pop_lsb(ref b2); mlist[mPos++].move = Types.make_move(to - Left, to); } if (pos.ep_square() != SquareS.SQ_NONE) { Debug.Assert(Types.rank_of(pos.ep_square()) == Types.relative_rank_rank(Us, RankS.RANK_6)); // An en passant capture can be an evasion only if the checking piece // is the double pushed pawn and so is in the target. Otherwise this // is a discovery check and we are forced to do otherwise. if (Type == GenTypeS.EVASIONS && (target & BitBoard.SquareBB[(pos.ep_square() - Up)]) == 0) { return(mPos); } b1 = pawnsNotOn7 & pos.attacks_from_pawn(pos.ep_square(), Them); Debug.Assert(b1 != 0); while (b1 != 0) { mlist[mPos++].move = Types.make(BitBoard.pop_lsb(ref b1), pos.ep_square(), MoveTypeS.ENPASSANT); } } } return(mPos); }
/// probe() tries to find a book move for the given position. If no move is /// found returns MOVE_NONE. If pickBest is true returns always the highest /// rated move, otherwise randomly chooses one, based on the move score. public Move probe(Position pos, string fName, bool pickBest) { if (fName == null || (fileName != fName && !open(fName))) { return(MoveS.MOVE_NONE); } PolyglotBook.Entry e = new PolyglotBook.Entry(); UInt16 best = 0; uint sum = 0; Move move = MoveS.MOVE_NONE; Key key = polyglot_key(pos); stream.Seek(find_first(key) * SIZE_OF_BOOKENTRY, SeekOrigin.Begin); while (read(ref e) && e.key == key) { best = Math.Max(best, e.count); sum += e.count; // Choose book move according to its score. If a move has a very // high score it has higher probability to be choosen than a move // with lower score. Note that first entry is always chosen. if ((sum != 0 && ((((uint)RKiss.rand64()) % sum) < e.count)) || (pickBest && e.count == best)) { move = (e.move); } } if (move == 0) { return(MoveS.MOVE_NONE); } // A PolyGlot book move is encoded as follows: // // bit 0- 5: destination square (from 0 to 63) // bit 6-11: origin square (from 0 to 63) // bit 12-14: promotion piece (from KNIGHT == 1 to QUEEN == 4) // // Castling moves follow "king captures rook" representation. So in case book // move is a promotion we have to convert to our representation, in all the // other cases we can directly compare with a Move after having masked out // the special Move's flags (bit 14-15) that are not supported by PolyGlot. int pt = (move >> 12) & 7; if (pt != 0) { move = Types.make(Types.from_sq(move), Types.to_sq(move), MoveTypeS.PROMOTION, (pt + 1)); } // Add 'special move' flags and verify it is legal for (MoveList ml = new MoveList(pos, GenTypeS.LEGAL); ml.mlist[ml.cur].move != MoveS.MOVE_NONE; ++ml) { if (move == (ml.move() ^ Types.type_of_move(ml.move()))) { return(ml.move()); } } return(MoveS.MOVE_NONE); }