예제 #1
0
        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);
        }
예제 #2
0
        // evaluate_pieces() assigns bonuses and penalties to the pieces of a given color
        public static Score evaluate_pieces(Position pos, EvalInfo ei, Score[] mobility, Bitboard[] mobilityArea, PieceType Pt, Color Us, bool Trace)
        {
            if (Us == ColorS.WHITE && Pt == PieceTypeS.KING)
            {
                return(ScoreS.SCORE_ZERO);
            }

            Bitboard b;
            Square   s;
            Score    score = ScoreS.SCORE_ZERO;

            PieceType NextPt = (Us == ColorS.WHITE ? Pt : (Pt + 1));
            Color     Them   = (Us == ColorS.WHITE ? ColorS.BLACK : ColorS.WHITE);

            Square[] pl    = pos.list(Us, Pt);
            int      plPos = 0;

            ei.attackedBy[Us][Pt] = 0;

            while ((s = pl[plPos++]) != SquareS.SQ_NONE)
            {
                // Find attacked squares, including x-ray attacks for bishops and rooks
                b = Pt == PieceTypeS.BISHOP ? BitBoard.attacks_bb_SBBPT(s, pos.pieces() ^ pos.pieces_color_piecetype(Us, PieceTypeS.QUEEN), PieceTypeS.BISHOP)
                  : Pt == PieceTypeS.ROOK ? BitBoard.attacks_bb_SBBPT(s, pos.pieces() ^ pos.pieces_color_piecetype(Us, PieceTypeS.ROOK, PieceTypeS.QUEEN), PieceTypeS.ROOK)
                                    : pos.attacks_from_square_piecetype(s, Pt);

                if ((ei.pinnedPieces[Us] & BitBoard.SquareBB[s]) != 0)
                {
                    b &= BitBoard.LineBB[pos.king_square(Us)][s];
                }

                ei.attackedBy[Us][PieceTypeS.ALL_PIECES] |= ei.attackedBy[Us][Pt] |= b;

                if ((b & ei.kingRing[Them]) != 0)
                {
                    ei.kingAttackersCount[Us]++;
                    ei.kingAttackersWeight[Us] += KingAttackWeights[Pt];
                    Bitboard bb = (b & ei.attackedBy[Them][PieceTypeS.KING]);
                    if (bb != 0)
                    {
                        ei.kingAdjacentZoneAttacksCount[Us] += Bitcount.popcount_Max15(bb);
                    }
                }

                if (Pt == PieceTypeS.QUEEN)
                {
                    b &= ~(ei.attackedBy[Them][PieceTypeS.KNIGHT]
                           | ei.attackedBy[Them][PieceTypeS.BISHOP]
                           | ei.attackedBy[Them][PieceTypeS.ROOK]);
                }

                int mob = (Pt != PieceTypeS.QUEEN ? Bitcount.popcount_Max15(b & mobilityArea[Us])
                                                  : Bitcount.popcount(b & mobilityArea[Us]));

                mobility[Us] += MobilityBonus[Pt][mob];

                // Decrease score if we are attacked by an enemy pawn. The remaining part
                // of threat evaluation must be done later when we have full attack info.
                if ((ei.attackedBy[Them][PieceTypeS.PAWN] & BitBoard.SquareBB[s]) != 0)
                {
                    score -= ThreatenedByPawn[Pt];
                }

                if (Pt == PieceTypeS.BISHOP || Pt == PieceTypeS.KNIGHT)
                {
                    // Penalty for bishop with same coloured pawns
                    if (Pt == PieceTypeS.BISHOP)
                    {
                        score -= BishopPawns * ei.pi.pawns_on_same_color_squares(Us, s);
                    }

                    // Bishop and knight outposts squares
                    if (0 == (pos.pieces_color_piecetype(Them, PieceTypeS.PAWN) & BitBoard.pawn_attack_span(Us, s)))
                    {
                        score += evaluate_outposts(pos, ei, s, Pt, Us);
                    }

                    // Bishop or knight behind a pawn
                    if (Types.relative_rank_square(Us, s) < RankS.RANK_5 &&
                        (pos.pieces_piecetype(PieceTypeS.PAWN) & BitBoard.SquareBB[(s + Types.pawn_push(Us))]) != 0)
                    {
                        score += MinorBehindPawn;
                    }
                }

                if (Pt == PieceTypeS.ROOK)
                {
                    // Rook piece attacking enemy pawns on the same rank/file
                    if (Types.relative_rank_square(Us, s) >= RankS.RANK_5)
                    {
                        Bitboard pawns = pos.pieces_color_piecetype(Them, PieceTypeS.PAWN) & BitBoard.PseudoAttacks[PieceTypeS.ROOK][s];
                        if (pawns != 0)
                        {
                            score += Bitcount.popcount_Max15(pawns) * RookOnPawn;
                        }
                    }

                    // Give a bonus for a rook on a open or semi-open file
                    if (ei.pi.semiopen_file(Us, Types.file_of(s)) != 0)
                    {
                        score += ei.pi.semiopen_file(Them, Types.file_of(s)) != 0 ? RookOpenFile : RookSemiopenFile;
                    }

                    if (mob > 3 || ei.pi.semiopen_file(Us, Types.file_of(s)) != 0)
                    {
                        continue;
                    }

                    Square ksq = pos.king_square(Us);

                    // Penalize rooks which are trapped by a king. Penalize more if the
                    // king has lost its castling capability.
                    if (((Types.file_of(ksq) < FileS.FILE_E) == (Types.file_of(s) < Types.file_of(ksq))) &&
                        (Types.rank_of(ksq) == Types.rank_of(s) || Types.relative_rank_square(Us, ksq) == RankS.RANK_1) &&
                        0 == ei.pi.semiopen_side(Us, Types.file_of(ksq), Types.file_of(s) < Types.file_of(ksq)))
                    {
                        score -= (TrappedRook - Types.make_score(mob * 8, 0)) * (1 + (pos.can_castle_color(Us) == 0 ? 1 : 0));
                    }
                }

                // An important Chess960 pattern: A cornered bishop blocked by a friendly
                // pawn diagonally in front of it is a very serious problem, especially
                // when that pawn is also blocked.
                if (Pt == PieceTypeS.BISHOP &&
                    pos.is_chess960() != 0 &&
                    (s == Types.relative_square(Us, SquareS.SQ_A1) || s == Types.relative_square(Us, SquareS.SQ_H1)))
                {
                    Square d = Types.pawn_push(Us) + (Types.file_of(s) == FileS.FILE_A ? SquareS.DELTA_E : SquareS.DELTA_W);
                    if (pos.piece_on(s + d) == Types.make_piece(Us, PieceTypeS.PAWN))
                    {
                        score -= !pos.empty(s + d + Types.pawn_push(Us)) ? TrappedBishopA1H1 * 4
                            : pos.piece_on(s + d + d) == Types.make_piece(Us, PieceTypeS.PAWN) ? TrappedBishopA1H1 * 2
                                                                            : TrappedBishopA1H1;
                    }
                }
            }

            if (Trace)
            {
                Tracing.terms[Us][Pt] = score;
            }

            return(score - evaluate_pieces(pos, ei, mobility, mobilityArea, NextPt, Them, Trace));
        }