Ejemplo n.º 1
0
        /// move_to_uci() converts a move to a string in coordinate notation
        /// (g1f3, a7a8q, etc.). The only special case is castling moves, where we print
        /// in the e1g1 notation in normal chess mode, and in e1h1 notation in chess960
        /// mode. Internally castling moves are always encoded as "king captures rook".
        public static string move_to_uci(Move m, bool chess960)
        {
            Square from = Types.from_sq(m);
            Square to   = Types.to_sq(m);

            if (m == MoveS.MOVE_NONE)
            {
                return("(none)");
            }

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

            if (Types.type_of_move(m) == MoveTypeS.CASTLING && !chess960)
            {
                to = Types.make_square((to > from ? FileS.FILE_G : FileS.FILE_C), Types.rank_of(from));
            }

            string move = Types.square_to_string(from) + Types.square_to_string(to);

            if (Types.type_of_move(m) == MoveTypeS.PROMOTION)
            {
                move += PieceToChar[ColorS.BLACK][Types.promotion_type(m)]; // Lower case
            }
            return(move);
        }
Ejemplo n.º 2
0
        /// 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];
                }
            }
        }
Ejemplo n.º 3
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);
        }