Пример #1
0
        /// move_to_san() takes a position and a legal Move as input and returns its
        /// short algebraic notation representation.
        internal static string move_to_san(Position pos, int m)
        {
            if (m == MoveC.MOVE_NONE)
            {
                return "(none)";
            }

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

            Debug.Assert(pos.move_is_legal(m));

            Bitboard others, b;
            Color us = pos.sideToMove;
            var san = new StringBuilder();

            Square from = from_sq(m);
            Square to = to_sq(m);
            Piece pc = pos.piece_on(from);
            PieceType pt = type_of(pc);

            if (type_of_move(m) == MoveTypeC.CASTLING)
            {
                san.Append(to > from ? "O-O" : "O-O-O");
            }
            else
            {
                if (pt != PieceTypeC.PAWN)
                {
                    san.Append(PieceToChar[ColorC.WHITE][pt]); // Upper case

                    // Disambiguation if we have more then one piece of type 'pt' that can
                    // reach 'to' with a legal move.
                    others = b = (pos.attacks_from_PS(pc, to) & pos.pieces_PTC(pt, us)) ^ (ulong)from;
                    while (others != 0)
                    {
                        Move move = make_move(pop_lsb(ref b), to);
                        if (!pos.pl_move_is_legal(move, pos.pinned_pieces()))
                        {
                            others ^= (ulong)from_sq(move);
                        }
                    }

                    if (others != 0)
                    {
                        if ((others & file_bb_S(from)) == 0)
                        {
                            san.Append(file_to_char(file_of(from)));
                        }
                        else if ((others & rank_bb_S(from)) == 0)
                        {
                            san.Append(rank_to_char(rank_of(from)));
                        }
                        else
                        {
                            san.Append(square_to_string(from));
                        }
                    }
                }
                else if (pos.is_capture(m))
                {
                    san.Append(file_to_char(file_of(from)));
                }

                if (pos.is_capture(m))
                {
                    san.Append('x');
                }

                san.Append(square_to_string(to));

                if (type_of_move(m) == MoveTypeC.PROMOTION)
                {
                    san.Append('=');
                    san.Append(PieceToChar[ColorC.WHITE][promotion_type(m)]);
                }
            }

            var ci = CheckInfoBroker.GetObject();
            ci.CreateCheckInfo(pos);
            if (pos.move_gives_check(m, ci))
            {
                var st = new StateInfo();
                pos.do_move(m, st);
                var mlist = MListBroker.GetObject();
                mlist.pos = 0;
                Movegen.generate_legal(pos, mlist.moves, ref mlist.pos);
                san.Append(mlist.pos > 0 ? "+" : "#");
                MListBroker.Free();
                pos.undo_move(m);
            }
            CheckInfoBroker.Free();

            return san.ToString();
        }
Пример #2
0
        // connected_moves() tests whether two moves are 'connected' in the sense
        // that the first move somehow made the second move possible (for instance
        // if the moving piece is the same in both moves). The first move is assumed
        // to be the move that was made to reach the current position, while the
        // second move is assumed to be a move from the current position.
        internal static bool connected_moves(Position pos, Move m1, Move m2)
        {
            Square f1, t1, f2, t2;
            Piece p1, p2;
            Square ksq;

            Debug.Assert(Utils.is_ok_M(m1));
            Debug.Assert(Utils.is_ok_M(m2));

            // Case 1: The moving piece is the same in both moves
            f2 = Utils.from_sq(m2);
            t1 = Utils.to_sq(m1);
            if (f2 == t1)
                return true;

            // Case 2: The destination square for m2 was vacated by m1
            t2 = Utils.to_sq(m2);
            f1 = Utils.from_sq(m1);
            if (t2 == f1)
                return true;

            // Case 3: Moving through the vacated square
            p2 = pos.piece_on(f2);
            if (piece_is_slider(p2)
                && (Utils.bit_is_set(Utils.between_bb(f2, t2), f1) != 0))
                return true;

            // Case 4: The destination square for m2 is defended by the moving piece in m1
            p1 = pos.piece_on(t1);
            if ((Utils.bit_is_set(pos.attacks_from_PS(p1, t1), t2)) != 0)
                return true;

            // Case 5: Discovered check, checking piece is the piece moved in m1
            ksq = pos.king_square(pos.sideToMove);
            if (
                piece_is_slider(p1)
                &&
                (Utils.bit_is_set(Utils.between_bb(t1, ksq), f2) != 0)
                &&
                (Utils.bit_is_set(Position.attacks_from(p1, t1, Utils.xor_bit(pos.occupied_squares, f2)), ksq) != 0)
                )
                return true;

            return false;
        }