internal CheckInfo(Position pos) { var them = Color.opposite(pos.side_to_move()); ksq = pos.square(PieceType.KING, them); pinned = pos.pinned_pieces(pos.side_to_move()); dcCandidates = pos.discovered_check_candidates(); checkSquares[PieceType.PAWN] = pos.attacks_from_PS(PieceType.PAWN, ksq, them); checkSquares[PieceType.KNIGHT] = pos.attacks_from_PtS(PieceType.KNIGHT, ksq); checkSquares[PieceType.BISHOP] = pos.attacks_from_PtS(PieceType.BISHOP, ksq); checkSquares[PieceType.ROOK] = pos.attacks_from_PtS(PieceType.ROOK, ksq); checkSquares[PieceType.QUEEN] = checkSquares[PieceType.BISHOP] | checkSquares[PieceType.ROOK]; checkSquares[PieceType.KING] = Bitboard.Create(0); }
internal override ScaleFactor GetScaleFactor(Position pos) { Debug.Assert(verify_material(pos, strongSide, Value.QueenValueMg, 0)); Debug.Assert(pos.count(PieceType.ROOK, weakSide) == 1); Debug.Assert(pos.count(PieceType.PAWN, weakSide) >= 1); var kingSq = pos.square(PieceType.KING, weakSide); var rsq = pos.square(PieceType.ROOK, weakSide); if (Rank.relative_rank_CtSt(weakSide, kingSq) <= Rank.RANK_2 && Rank.relative_rank_CtSt(weakSide, pos.square(PieceType.KING, strongSide)) >= Rank.RANK_4 && Rank.relative_rank_CtSt(weakSide, rsq) == Rank.RANK_3 && (pos.pieces_CtPt(weakSide, PieceType.PAWN) & pos.attacks_from_PtS(PieceType.KING, kingSq) & pos.attacks_from_PS(PieceType.PAWN, rsq, strongSide))!=0) { return ScaleFactor.SCALE_FACTOR_DRAW; } return ScaleFactor.SCALE_FACTOR_NONE; }
internal static ExtMoveArrayWrapper generate_pawn_moves( ColorT Us, GenType Type, Position pos, ExtMoveArrayWrapper moveList, BitboardT target, CheckInfo ci) { // Compute our parametrized parameters at compile time, named according to // the point of view of white side. var Them = (Us == Color.WHITE ? Color.BLACK : Color.WHITE); var TRank8BB = (Us == Color.WHITE ? Bitboard.Rank8BB : Bitboard.Rank1BB); var TRank7BB = (Us == Color.WHITE ? Bitboard.Rank7BB : Bitboard.Rank2BB); var TRank3BB = (Us == Color.WHITE ? Bitboard.Rank3BB : Bitboard.Rank6BB); var Up = (Us == Color.WHITE ? Square.DELTA_N : Square.DELTA_S); var Right = (Us == Color.WHITE ? Square.DELTA_NE : Square.DELTA_SW); var Left = (Us == Color.WHITE ? Square.DELTA_NW : Square.DELTA_SE); var emptySquares = Bitboard.Create(0); var pawnsOn7 = pos.pieces_CtPt(Us, PieceType.PAWN) & TRank7BB; var pawnsNotOn7 = pos.pieces_CtPt(Us, PieceType.PAWN) & ~TRank7BB; var enemies = (Type == GenType.EVASIONS ? pos.pieces_Ct(Them) & target : Type == GenType.CAPTURES ? target : pos.pieces_Ct(Them)); // Single and double pawn pushes, no promotions if (Type != GenType.CAPTURES) { emptySquares = (Type == GenType.QUIETS || Type == GenType.QUIET_CHECKS ? target : ~pos.pieces()); var b1 = Bitboard.shift_bb(Up, pawnsNotOn7) & emptySquares; var b2 = Bitboard.shift_bb(Up, b1 & TRank3BB) & emptySquares; if (Type == GenType.EVASIONS) // Consider only blocking squares { b1 &= target; b2 &= target; } if (Type == GenType.QUIET_CHECKS) { b1 &= pos.attacks_from_PS(PieceType.PAWN, ci.ksq, Them); b2 &= pos.attacks_from_PS(PieceType.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 amongst the captures. if ((pawnsNotOn7 & ci.dcCandidates) != 0) { var dc1 = Bitboard.shift_bb(Up, pawnsNotOn7 & ci.dcCandidates) & emptySquares & ~Utils.file_bb_St(ci.ksq); var dc2 = Bitboard.shift_bb(Up, dc1 & TRank3BB) & emptySquares; b1 |= dc1; b2 |= dc2; } } while (b1 != 0) { var to = Utils.pop_lsb(ref b1); (moveList).Add(Move.make_move(to - Up, to)); } while (b2 != 0) { var to = Utils.pop_lsb(ref b2); (moveList).Add(Move.make_move(to - Up - Up, to)); } } // Promotions and underpromotions if (pawnsOn7 != 0 && (Type != GenType.EVASIONS || ((target & TRank8BB) != 0))) { if (Type == GenType.CAPTURES) { emptySquares = ~pos.pieces(); } if (Type == GenType.EVASIONS) { emptySquares &= target; } var b1 = Bitboard.shift_bb(Right, pawnsOn7) & enemies; var b2 = Bitboard.shift_bb(Left, pawnsOn7) & enemies; var b3 = Bitboard.shift_bb(Up, pawnsOn7) & emptySquares; while (b1 != 0) { moveList = make_promotions(Type, Right, moveList, Utils.pop_lsb(ref b1), ci); } while (b2 != 0) { moveList = make_promotions(Type, Left, moveList, Utils.pop_lsb(ref b2), ci); } while (b3 != 0) { moveList = make_promotions(Type, Up, moveList, Utils.pop_lsb(ref b3), ci); } } // Standard and en-passant captures if (Type == GenType.CAPTURES || Type == GenType.EVASIONS || Type == GenType.NON_EVASIONS) { var b1 = Bitboard.shift_bb(Right, pawnsNotOn7) & enemies; var b2 = Bitboard.shift_bb(Left, pawnsNotOn7) & enemies; while (b1 != 0) { var to = Utils.pop_lsb(ref b1); (moveList).Add(Move.make_move(to - Right, to)); } while (b2 != 0) { var to = Utils.pop_lsb(ref b2); (moveList).Add(Move.make_move(to - Left, to)); } if (pos.ep_square() != Square.SQ_NONE) { Debug.Assert(Square.rank_of(pos.ep_square()) == Rank.relative_rank_CtRt(Us, Rank.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 == GenType.EVASIONS && Bitboard.AndWithSquare(target, (pos.ep_square() - Up))==0) { return moveList; } b1 = pawnsNotOn7 & pos.attacks_from_PS(PieceType.PAWN, pos.ep_square(), Them); Debug.Assert(b1 != 0); while (b1 != 0) { (moveList).Add(Move.make(MoveType.ENPASSANT, Utils.pop_lsb(ref b1), pos.ep_square())); } } } return moveList; }