Beispiel #1
0
        /// generate<QUIET_CHECKS> generates all pseudo-legal non-captures and knight
        /// underpromotions that give check. Returns a pointer to the end of the move list.
        public static int generate_quiet_checks(Position pos, ExtMove[] mlist, int mPos)
        {
            Debug.Assert(0 == pos.checkers());

            Color     us = pos.side_to_move();
            CheckInfo ci = new CheckInfo(pos);
            Bitboard  dc = ci.dcCandidates;

            while (dc != 0)
            {
                Square    from = BitBoard.pop_lsb(ref dc);
                PieceType pt   = Types.type_of_piece(pos.piece_on(from));

                if (pt == PieceTypeS.PAWN)
                {
                    continue; // Will be generated togheter with direct checks
                }
                Bitboard b = pos.attacks_from_piece_square((Piece)pt, from) & ~pos.pieces();

                if (pt == PieceTypeS.KING)
                {
                    b &= ~BitBoard.PseudoAttacks[PieceTypeS.QUEEN][ci.ksq];
                }

                while (b != 0)
                {
                    mlist[mPos++].move = Types.make_move(from, BitBoard.pop_lsb(ref b));
                }
            }

            return(us == ColorS.WHITE ? generate_all(pos, mlist, mPos, ~pos.pieces(), ColorS.WHITE, GenTypeS.QUIET_CHECKS, ci) :
                   generate_all(pos, mlist, mPos, ~pos.pieces(), ColorS.BLACK, GenTypeS.QUIET_CHECKS, ci));
        }
Beispiel #2
0
        // polyglot_key() returns the PolyGlot hash key of the given position
        public static Key polyglot_key(Position pos)
        {
            Key      key = 0;
            Bitboard b   = pos.pieces();

            while (b != 0)
            {
                Square s  = BitBoard.pop_lsb(ref b);
                Piece  pc = pos.piece_on(s);
                // PolyGlot pieces are: BP = 0, WP = 1, BN = 2, ... BK = 10, WK = 11
                int pieceOfs = 2 * (Types.type_of_piece(pc) - 1) + ((Types.color_of(pc) == ColorS.WHITE) ? 1 : 0);
                key ^= PG[psq + (64 * pieceOfs + s)];
            }

            b = (ulong)pos.can_castle_castleright(CastlingRightS.ANY_CASTLING);

            while (b != 0)
            {
                key ^= PG[castle + BitBoard.pop_lsb(ref b)];
            }

            if (pos.ep_square() != SquareS.SQ_NONE)
            {
                key ^= PG[enpassant + Types.file_of(pos.ep_square())];
            }

            if (pos.side_to_move() == ColorS.WHITE)
            {
                key ^= PG[turn + 0];
            }

            return(key);
        }
        public void score_evasions()
        {
            // Try good captures ordered by MVV/LVA, then non-captures if destination square
            // is not under attack, ordered by history value, then bad-captures and quiet
            // moves with a negative SEE. This last group is ordered by the SEE value.
            Move m;
            int  see;

            for (int it = 0; it != end; ++it)
            {
                m = moves[it].move;
                if ((see = pos.see_sign(m)) < ValueS.VALUE_ZERO)
                {
                    moves[it].value = see - HistoryStats.Max; // At the bottom
                }
                else if (pos.capture(m))
                {
                    moves[it].value = Position.PieceValue[PhaseS.MG][pos.piece_on(Types.to_sq(m))]
                                      - Types.type_of_piece(pos.moved_piece(m)) + HistoryStats.Max;
                }
                else
                {
                    moves[it].value = history[pos.moved_piece(m)][Types.to_sq(m)];
                }
            }
        }
        /// score() assign a numerical value to each move in a move list. The moves with
        /// highest values will be picked first.
        public void score_captures()
        {
            // Winning and equal captures in the main search are ordered by MVV/LVA.
            // Suprisingly, this appears to perform slightly better than SEE based
            // move ordering. The reason is probably that in a position with a winning
            // capture, capturing a more valuable (but sufficiently defended) piece
            // first usually doesn't hurt. The opponent will have to recapture, and
            // the hanging piece will still be hanging (except in the unusual cases
            // where it is possible to recapture with the hanging piece). Exchanging
            // big pieces before capturing a hanging piece probably helps to reduce
            // the subtree size.
            // In main search we want to push captures with negative SEE values to the
            // badCaptures[] array, but instead of doing it now we delay until the move
            // has been picked up in pick_move_from_list(). This way we save some SEE
            // calls in case we get a cutoff.
            Move m;

            for (int it = 0; it != end; ++it)
            {
                m = moves[it].move;
                moves[it].value = Position.PieceValue[PhaseS.MG][pos.piece_on(Types.to_sq(m))]
                                  - Types.type_of_piece(pos.moved_piece(m));

                if (Types.type_of_move(m) == MoveTypeS.ENPASSANT)
                {
                    moves[it].value += Position.PieceValue[PhaseS.MG][PieceTypeS.PAWN];
                }

                else if (Types.type_of_move(m) == MoveTypeS.PROMOTION)
                {
                    moves[it].value += Position.PieceValue[PhaseS.MG][Types.promotion_type(m)] - Position.PieceValue[PhaseS.MG][PieceTypeS.PAWN];
                }
            }
        }
        public static Bitboard attacks_bb_PSBB(Piece pc, Square s, Bitboard occ)
        {
            switch (Types.type_of_piece(pc))
            {
            case PieceTypeS.BISHOP: return(attacks_bb_SBBPT(s, occ, PieceTypeS.BISHOP));

            case PieceTypeS.ROOK: return(attacks_bb_SBBPT(s, occ, PieceTypeS.ROOK));

            case PieceTypeS.QUEEN: return(attacks_bb_SBBPT(s, occ, PieceTypeS.BISHOP) | attacks_bb_SBBPT(s, occ, PieceTypeS.ROOK));

            default: return(StepAttacksBB[pc][s]);
            }
        }
Beispiel #6
0
        // evaluate_threats() assigns bonuses according to the type of attacking piece
        // and the type of attacked one.
        public static Score evaluate_threats(Position pos, EvalInfo ei, Color Us, bool Trace)
        {
            Color Them = (Us == ColorS.WHITE ? ColorS.BLACK : ColorS.WHITE);

            Bitboard b, weakEnemies;
            Score    score = ScoreS.SCORE_ZERO;

            // Enemies not defended by a pawn and under our attack
            weakEnemies = pos.pieces_color(Them)
                          & ~ei.attackedBy[Them][PieceTypeS.PAWN]
                          & ei.attackedBy[Us][PieceTypeS.ALL_PIECES];

            // Add a bonus according if the attacking pieces are minor or major
            if (weakEnemies != 0)
            {
                b = weakEnemies & (ei.attackedBy[Us][PieceTypeS.PAWN] | ei.attackedBy[Us][PieceTypeS.KNIGHT] | ei.attackedBy[Us][PieceTypeS.BISHOP]);
                if (b != 0)
                {
                    score += Threat[0][Types.type_of_piece(pos.piece_on(BitBoard.lsb(b)))];
                }

                b = weakEnemies & (ei.attackedBy[Us][PieceTypeS.ROOK] | ei.attackedBy[Us][PieceTypeS.QUEEN]);
                if (b != 0)
                {
                    score += Threat[1][Types.type_of_piece(pos.piece_on(BitBoard.lsb(b)))];
                }

                b = weakEnemies & ~ei.attackedBy[Them][PieceTypeS.ALL_PIECES];
                if (b != 0)
                {
                    score += BitBoard.more_than_one(b) ? Hanging[Us != pos.side_to_move()?1:0] * Bitcount.popcount_Max15(b)
                        : Hanging[Us == pos.side_to_move()?1:0];
                }
            }

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

            return(score);
        }
Beispiel #7
0
        /// move_to_san() takes a position and a legal Move as input and returns its
        /// short algebraic notation representation.
        public static string move_to_san(Position pos, Move m)
        {
            if (m == MoveS.MOVE_NONE)
            {
                return("(none)");
            }

            if (m == MoveS.MOVE_NULL)
            {
                return("(null)");
            }

            Debug.Assert((new MoveList(pos, GenTypeS.LEGAL).contains(m)));

            Bitboard  others, b;
            string    san  = "";
            Color     us   = pos.side_to_move();
            Square    from = Types.from_sq(m);
            Square    to   = Types.to_sq(m);
            Piece     pc   = pos.piece_on(from);
            PieceType pt   = Types.type_of_piece(pc);

            if (Types.type_of_move(m) == MoveTypeS.CASTLING)
            {
                san = to > from ? "O-O" : "O-O-O";
            }
            else
            {
                if (pt != PieceTypeS.PAWN)
                {
                    san = "" + PieceToChar[ColorS.WHITE][pt]; // Upper case

                    // A disambiguation occurs if we have more then one piece of type 'pt'
                    // that can reach 'to' with a legal move.
                    others = b = (pos.attacks_from_piece_square(pc, to) & pos.pieces_color_piecetype(us, pt)) ^ BitBoard.SquareBB[from];

                    while (b != 0)
                    {
                        Square s = BitBoard.pop_lsb(ref b);
                        if (!pos.legal(Types.make_move(s, to), pos.pinned_pieces(us)))
                        {
                            others ^= BitBoard.SquareBB[s];
                        }
                    }

                    if (0 == others)
                    { /* Disambiguation is not needed */
                    }

                    else if (0 == (others & BitBoard.file_bb_square(from)))
                    {
                        san += Types.file_to_char(Types.file_of(from));
                    }

                    else if (0 == (others & BitBoard.rank_bb_square(from)))
                    {
                        san += Types.rank_to_char(Types.rank_of(from));
                    }

                    else
                    {
                        san += Types.square_to_string(from);
                    }
                }
                else if (pos.capture(m))
                {
                    san = "" + Types.file_to_char(Types.file_of(from));
                }

                if (pos.capture(m))
                {
                    san += 'x';
                }

                san += Types.square_to_string(to);

                if (Types.type_of_move(m) == MoveTypeS.PROMOTION)
                {
                    san += "=" + PieceToChar[ColorS.WHITE][Types.promotion_type(m)];
                }
            }

            if (pos.gives_check(m, new CheckInfo(pos)))
            {
                StateInfo st = new StateInfo();
                pos.do_move(m, st);
                san += (new MoveList(pos, GenTypeS.LEGAL)).size() > 0 ? "+" : "#";
                pos.undo_move(m);
            }

            return(san);
        }