public void Reset(PlayerPieceSet white_pieces, PlayerPieceSet black_pieces)
 {
     Debug.Assert(white_pieces != null);
     Debug.Assert(black_pieces != null);
     AddPieces(white_pieces, Players.White);
     AddPieces(black_pieces, Players.Black);
 }
Exemple #2
0
 public static ChessboardArray GetChessboardArray(PlayerPieceSet white_pieces,
     PlayerPieceSet black_pieces)
 {
     // TODO
     var result = new ChessboardArray();
     result.Reset(white_pieces, black_pieces);
     return result;
 }
 private static void MakeBishopMoves(PlayerPieceSet my_pieces,
     PlayerPieceSet other_pieces, List<Move> moves)
 {
     for (uint i = 0, e = my_pieces.BishopsCount; i < e; ++i)
     {
         uint cell_index;
         int cell = my_pieces.GetBishopCell(i, out cell_index);
         MakeDiagonalMoves(Exports.Pieces.Bishop, my_pieces, other_pieces,
             cell, cell_index, moves);
     }
 }
 private void AddPieces(PlayerPieceSet pieces, Players player)
 {
     Debug.Assert(pieces != null);
     AddPiece(player, Exports.Pieces.King, pieces.KingsCell);
     for (uint i = 0, e = pieces.QueensCount; i < e; ++i)
     {
         AddPiece(player, Exports.Pieces.Queen, pieces.GetQueenCell(i));
     }
     for (uint i = 0, e = pieces.RooksCount; i < e; ++i)
     {
         AddPiece(player, Exports.Pieces.Rook, pieces.GetRookCell(i));
     }
     for (uint i = 0, e = pieces.BishopsCount; i < e; ++i)
     {
         AddPiece(player, Exports.Pieces.Bishop, pieces.GetBishopCell(i));
     }
     for (uint i = 0, e = pieces.KnightsCount; i < e; ++i)
     {
         AddPiece(player, Exports.Pieces.Knight, pieces.GetKnightCell(i));
     }
     for (uint i = 0, e = pieces.PawnsCount; i < e; ++i)
     {
         AddPiece(player, Exports.Pieces.Pawn, pieces.GetPawnCell(i));
     }
 }
Exemple #5
0
        public void Reset(PlayerPieceSet white_pieces,
            PlayerPieceSet black_pieces,
            Players player_to_move,
            Castle white_castling_options,
            Castle black_castling_options,
            int? capture_en_passant_column,
            ushort fullmove_number,
            ushort halfmove_clock)
        {
            Debug.Assert(white_pieces != null);
            Debug.Assert(black_pieces != null);

            Debug.Assert(m_white_pieces == null);
            Debug.Assert(m_black_pieces == null);

            m_white_pieces = white_pieces;
            m_black_pieces = black_pieces;

            m_position_flags.Clear();

            if (player_to_move == Players.White)
            {
                m_position_flags.SetBit(BIT_WHITE_TO_MOVE);
            }

            // TODO - HasFlag is known to be slow, consider optimizing
            SetCanCastleShort(Players.White, white_castling_options.HasFlag(Castle.Short));
            SetCanCastleLong(Players.White, white_castling_options.HasFlag(Castle.Long));
            SetCanCastleShort(Players.Black, black_castling_options.HasFlag(Castle.Short));
            SetCanCastleLong(Players.Black, black_castling_options.HasFlag(Castle.Long));

            CaptureEnPassantColumn = capture_en_passant_column;

            FullmoveNumber = fullmove_number;
            HalfmoveClock = halfmove_clock;
        }
Exemple #6
0
        private Castle CalcNewCastlingOptions(Players player, PlayerPieceSet pieces,
            int base_row)
        {
            // We could deduce base_row value here, but let us pass it is as a
            // parameter for better(?) performance
            // Nevertheless, it is worth to check for typos
            Debug.Assert((player == Players.White && base_row == Chessboard.ROW_MIN)
                || (player == Players.Black && base_row == Chessboard.ROW_MAX));

            var result = Castle.None;
            if (pieces.KingsCell == ChessboardCell.CalculateValue(base_row,
                Chessboard.COLUMN_E))
            {
                var cell = ChessboardCell.CalculateValue(base_row, Chessboard.COLUMN_H);
                if (IsCanCastleShort(player) && pieces.IsOccupiedCell(cell)
                    && pieces.IsRookAtCell(cell))
                {
                    result |= Castle.Short;
                }

                cell = ChessboardCell.CalculateValue(base_row, Chessboard.COLUMN_A);
                if (IsCanCastleLong(player) && pieces.IsOccupiedCell(cell)
                    && pieces.IsRookAtCell(cell))
                {
                    result |= Castle.Long;
                }
            }

            return result;
        }
 public static bool IsQueenAttacks(ChessboardCell queen_cell,
     ChessboardCell cell_to_check, PlayerPieceSet my_pieces,
     PlayerPieceSet other_pieces)
 {
     return IsBishopAttacks(queen_cell, cell_to_check, my_pieces, other_pieces)
         || IsRookAttacks(queen_cell, cell_to_check, my_pieces, other_pieces);
 }
        public static bool IsCellAttackedFromDir(ChessboardCell attacked_cell,
            ChessboardCell attack_origin, PlayerPieceSet attacker_pieces,
            PlayerPieceSet defender_pieces)
        {
            Debug.Assert(!attacked_cell.IsSame(attack_origin));
            int delta_row = attack_origin.Row - attacked_cell.Row;
            int delta_column = attack_origin.Column - attacked_cell.Column;

            // Fast check if the two cells are on the same vertical or horizontal line
            // or one the same diagonal
            if (delta_row != 0 && delta_column != 0 && delta_row != delta_column
                && delta_row != -delta_column)
            {
                return false;
            }

            // Check the ray from attacked_cell towards attack_origin and possibly behind
            // attack_origin until we reach the edge of the chessboard
            bool result = false;
            int row_inc = 0;
            int column_inc = 0;
            int iter_count = int.MaxValue;
            if (delta_row < 0)
            {
                row_inc = -1;
                iter_count = attacked_cell.Row - Chessboard.ROW_MIN;
            }
            else if (delta_row > 0)
            {
                row_inc = 1;
                iter_count = Chessboard.ROW_MAX - attacked_cell.Row;
            }
            if (delta_column < 0)
            {
                column_inc = -1;
                iter_count = Math.Min(iter_count,
                    attacked_cell.Column - Chessboard.COLUMN_MIN);
            }
            else if (delta_column > 0)
            {
                column_inc = 1;
                iter_count = Math.Min(iter_count,
                    Chessboard.COLUMN_MAX - attacked_cell.Column);
            }

            int cur_row = attacked_cell.Row;
            int cur_column = attacked_cell.Column;

            for (int i = 0; i < iter_count; ++i)
            {
                cur_row += row_inc;
                cur_column += column_inc;

                Debug.Assert(cur_row >= Chessboard.ROW_MIN
                    && cur_row <= Chessboard.ROW_MAX
                    && cur_column >= Chessboard.COLUMN_MIN
                    && cur_column <= Chessboard.COLUMN_MAX);
                int cur_cell = ChessboardCell.CalculateValue(cur_row, cur_column);
                if (defender_pieces.IsOccupiedCell(cur_cell))
                {
                    result = false;
                    break;
                }
                if (attacker_pieces.IsOccupiedCell(cur_cell))
                {
                    if (attacker_pieces.IsQueenAtCell(cur_cell))
                    {
                        result = true;
                    }
                    else if (row_inc == 0 || column_inc == 0)
                    {
                        result = attacker_pieces.IsRookAtCell(cur_cell);
                    }
                    else
                    {
                        result = attacker_pieces.IsBishopAtCell(cur_cell);
                    }
                    break;
                }
            }

            return result;
        }
        private static void MakeHorizVertMoves(Exports.Pieces piece, PlayerPieceSet my_pieces,
            PlayerPieceSet other_pieces, int from_cell, List<Move> moves)
        {
            Debug.Assert(piece == Exports.Pieces.Rook
                || piece == Exports.Pieces.Queen);

            var from_cell_obj = new ChessboardCell(from_cell);
            // Left
            MakeMovesAlongLine(piece, my_pieces, other_pieces, from_cell, 0, -1,
                from_cell_obj.Column, moves);
            // Right
            MakeMovesAlongLine(piece, my_pieces, other_pieces, from_cell, 0, 1,
                Chessboard.COLUMN_MAX - from_cell_obj.Column, moves);
            // Down
            MakeMovesAlongLine(piece, my_pieces, other_pieces, from_cell, -1, 0,
                from_cell_obj.Row, moves);
            // Up
            MakeMovesAlongLine(piece, my_pieces, other_pieces, from_cell, 1, 0,
                Chessboard.ROW_MAX - from_cell_obj.Row, moves);
        }
 public static bool IsRookAttacks(ChessboardCell rook_cell,
     ChessboardCell cell_to_check, PlayerPieceSet my_pieces,
     PlayerPieceSet other_pieces)
 {
     return (rook_cell.Row == cell_to_check.Row
         || rook_cell.Column == cell_to_check.Column)
         && IsCellAttackedFromDir(cell_to_check, rook_cell,
             my_pieces, other_pieces);
 }
        private static void MakeKingMoves(PlayerPieceSet my_pieces,
            PlayerPieceSet other_pieces, List<Move> moves)
        {
            var king_cell = new ChessboardCell(my_pieces.KingsCell);
            int row_min = Math.Max(Chessboard.ROW_MIN, king_cell.Row - 1);
            int row_max = Math.Min(Chessboard.ROW_MAX, king_cell.Row + 1);
            int column_min = Math.Max(Chessboard.COLUMN_MIN, king_cell.Column - 1);
            int column_max = Math.Min(Chessboard.COLUMN_MAX, king_cell.Column + 1);

            for (int row = row_min; row <= row_max; ++row)
            {
                for (int column = column_min; column <= column_max; ++column)
                {
                    int new_cell = ChessboardCell.CalculateValue(row, column);
                    if (!my_pieces.IsOccupiedCell(new_cell))
                    {
                        bool is_capture = other_pieces.IsOccupiedCell(new_cell);
                        moves.Add(new Move(Exports.Pieces.King, king_cell.Value,
                            new_cell, 0, is_capture ? Move.Flags.Capture : 0));
                    }
                }
            }
        }
        public static PlayerPieceSet MovePiece(PlayerPieceSet base_obj,
            Exports.Pieces piece, int remove_at_cell, int new_cell)
        {
            Debug.Assert(base_obj != null);
            Debug.Assert(piece != Exports.Pieces.NoPiece);
            Debug.Assert(remove_at_cell >= 0 && remove_at_cell < 64);
            Debug.Assert(new_cell >= 0 && new_cell < 64);
            Debug.Assert(remove_at_cell != new_cell);
            Debug.Assert(base_obj.IsOccupiedCell(remove_at_cell));
            Debug.Assert(!base_obj.IsOccupiedCell(new_cell));
            var result = (PlayerPieceSet)base_obj.MemberwiseClone();
            result.m_bitboard.UnsetBit(remove_at_cell);
            result.m_bitboard.SetBit(new_cell);

            // Insert new_cell first. Easier to do it now, because we know
            // the sorted ranges
            uint range_begin = 0;
            uint range_length = 0;
            switch (piece)
            {
                case Exports.Pieces.Pawn:
                    range_begin = result.PawnsStartIndex;
                    range_length = result.PawnsCount;
                    break;
                case Exports.Pieces.Knight:
                    range_begin = result.KnightsStartIndex;
                    range_length = result.KnightsCount;
                    break;
                case Exports.Pieces.Bishop:
                    range_begin = result.BishopsStartIndex;
                    range_length = result.BishopsCount;
                    break;
                case Exports.Pieces.Rook:
                    range_begin = result.RooksStartIndex;
                    range_length = result.RooksCount;
                    break;
                case Exports.Pieces.Queen:
                    range_begin = result.QueensStartIndex;
                    range_length = result.QueensCount;
                    break;
                case Exports.Pieces.King:
                    range_begin = 0;
                    range_length = 1;
                    break;
            }

            bool is_inserted = false;
            for (uint i = range_begin, e = range_begin + range_length; i < e; ++i)
            {
                if (new_cell < result.m_pieces_cells.GetCell(i))
                {
                    result.m_pieces_cells.InsertAt(i, new_cell);
                    is_inserted = true;
                    break;
                }
            }
            if (!is_inserted)
            {
                result.m_pieces_cells.InsertAt(range_begin + range_length, new_cell);
            }

            result.m_pieces_cells.EraseAt(
                (uint)result.m_pieces_cells.FindIndex(remove_at_cell));

            return result;
        }
 private static void MakeRookMoves(PlayerPieceSet my_pieces,
     PlayerPieceSet other_pieces, List<Move> moves)
 {
     for (uint i = 0, e = my_pieces.RooksCount; i < e; ++i)
     {
         MakeHorizVertMoves(Exports.Pieces.Rook, my_pieces, other_pieces,
             my_pieces.GetRookCell(i), moves);
     }
 }
 private static void MakeQueeenMoves(PlayerPieceSet my_pieces,
     PlayerPieceSet other_pieces, List<Move> moves)
 {
     for (uint i = 0, e = my_pieces.QueensCount; i < e; ++i)
     {
         uint cell_index;
         int queen_cell = my_pieces.GetQueenCell(i, out cell_index);
         MakeHorizVertMoves(Exports.Pieces.Queen, my_pieces, other_pieces,
             queen_cell, moves);
         MakeDiagonalMoves(Exports.Pieces.Queen, my_pieces, other_pieces,
             queen_cell, cell_index, moves);
     }
 }
        private static void MakePawnMoves(PlayerPieceSet my_pieces, PlayerPieceSet other_pieces,
            bool is_white_to_move, int? en_passant_capture_column, List<Move> moves)
        {
            int move_row_diff = is_white_to_move ? 1 : -1;
            for (uint i = 0, e = my_pieces.PawnsCount; i < e; ++i)
            {
                uint cell_index;
                var pawn_cell = new ChessboardCell(my_pieces.GetPawnCell(i,
                    out cell_index));
                var new_cell_value = ChessboardCell.CalculateValue(
                    pawn_cell.Row + move_row_diff, pawn_cell.Column);

                // Moves without captures
                if (!my_pieces.IsOccupiedCell(new_cell_value)
                    && !other_pieces.IsOccupiedCell(new_cell_value))
                {
                    WritePawnMove(pawn_cell.Value, new_cell_value, cell_index, 0,
                        moves);
                    // Two-rows move from the initial rank
                    int initial_row = is_white_to_move ? Chessboard.ROW_MIN + 1
                        : Chessboard.ROW_MAX - 1;
                    if (pawn_cell.Row == initial_row)
                    {
                        new_cell_value = ChessboardCell.CalculateValue(
                            pawn_cell.Row + 2 * move_row_diff, pawn_cell.Column);
                        if (!my_pieces.IsOccupiedCell(new_cell_value)
                            && !other_pieces.IsOccupiedCell(new_cell_value))
                        {
                            WritePawnMove(pawn_cell.Value, new_cell_value, cell_index,
                                0, moves);
                        }
                    }
                }

                // Captures except en passant captures
                // delta_column can be -1 or 1
                for (int delta_column = -1; delta_column <= 1; delta_column += 2)
                {
                    int new_column = pawn_cell.Column + delta_column;
                    if (new_column >= Chessboard.COLUMN_MIN
                        && new_column <= Chessboard.COLUMN_MAX)
                    {
                        new_cell_value = ChessboardCell.CalculateValue(pawn_cell.Row
                            + move_row_diff, new_column);
                        if (other_pieces.IsOccupiedCell(new_cell_value))
                        {
                            WritePawnMove(pawn_cell.Value, new_cell_value, cell_index,
                                Move.Flags.Capture, moves);
                        }
                    }
                }

                // En passant capture
                if (en_passant_capture_column.HasValue
                    && ((is_white_to_move && pawn_cell.Row == 4)
                        || (!is_white_to_move && pawn_cell.Row == 3))
                    && Math.Abs(pawn_cell.Column - en_passant_capture_column.Value) == 1)
                {
                    new_cell_value = ChessboardCell.CalculateValue(pawn_cell.Row
                        + move_row_diff, en_passant_capture_column.Value);
                    // Since en passant capture is allowed, we know that the destination
                    // cell is not occupied
                    WritePawnMove(pawn_cell.Value, new_cell_value, cell_index,
                        Move.Flags.Capture | Move.Flags.EnPassantCapture, moves);
                }

                // TODO - add en passant captures
                // TODO - uncomment
                //throw new NotImplementedException();
            }
        }
        private static void MakeMovesAlongLine(Exports.Pieces piece, PlayerPieceSet my_pieces,
            PlayerPieceSet other_pieces, int from_cell, int delta_row, int delta_column,
            int count, List<Move> moves)
        {
            var from_cell_obj = new ChessboardCell(from_cell);
            // count must be such that we hit the border of the chessboard at the end
            // of the loop
            Debug.Assert(
                from_cell_obj.Row + count * delta_row == Chessboard.ROW_MIN
                || from_cell_obj.Row + count * delta_row == Chessboard.ROW_MAX
                || from_cell_obj.Column + count * delta_column == Chessboard.COLUMN_MIN
                || from_cell_obj.Column + count * delta_column == Chessboard.COLUMN_MAX);

            int cur_row = from_cell_obj.Row;
            int cur_column = from_cell_obj.Column;
            for (int i = 0; i < count; ++i)
            {
                cur_row += delta_row;
                cur_column += delta_column;
                Debug.Assert(cur_row >= Chessboard.ROW_MIN
                    && cur_row <= Chessboard.ROW_MAX
                    && cur_column >= Chessboard.COLUMN_MIN
                    && cur_column <= Chessboard.COLUMN_MAX);
                var cur_cell = ChessboardCell.CalculateValue(cur_row, cur_column);
                if (my_pieces.IsOccupiedCell(cur_cell))
                {
                    break;
                }
                bool is_capture = other_pieces.IsOccupiedCell(cur_cell);
                moves.Add(new Move(piece, from_cell, cur_cell,
                    0 /* TODO - FIXME */, is_capture ? Move.Flags.Capture : 0));
                if (is_capture)
                {
                    break;
                }
            }
        }
 private static void MakeKnightMoves(PlayerPieceSet my_pieces,
     PlayerPieceSet other_pieces, List<Move> moves)
 {
     for (uint i = 0, e = my_pieces.KnightsCount; i < e; ++i)
     {
         uint cell_index;
         var knight_cell = new ChessboardCell(my_pieces.GetKnightCell(i,
             out cell_index));
         if (knight_cell.Row - 2 >= Chessboard.ROW_MIN &&
             knight_cell.Row + 2 <= Chessboard.ROW_MAX &&
             knight_cell.Column - 2 >= Chessboard.COLUMN_MIN &&
             knight_cell.Column + 2 <= Chessboard.COLUMN_MAX)
         {
             // In this case we do not need to check that new cells are within
             // the chessboard
             foreach (var move_delta in m_knight_moves)
             {
                 var new_cell = ChessboardCell.CalculateValue(
                     knight_cell.Row + move_delta.m_delta_row,
                     knight_cell.Column + move_delta.m_delta_column);
                 if (!my_pieces.IsOccupiedCell(new_cell))
                 {
                     bool is_capture = other_pieces.IsOccupiedCell(new_cell);
                     moves.Add(new Move(Exports.Pieces.Knight, knight_cell.Value,
                         new_cell, cell_index,
                         is_capture ? Move.Flags.Capture : 0));
                 }
             }
         }
         else
         {
             // Do range check for every new cell
             foreach (var move_delta in m_knight_moves)
             {
                 int new_row = knight_cell.Row + move_delta.m_delta_row;
                 if (new_row < Chessboard.ROW_MIN || new_row > Chessboard.ROW_MAX)
                 {
                     continue;
                 }
                 int new_column = knight_cell.Column + move_delta.m_delta_column;
                 if (new_column < Chessboard.COLUMN_MIN
                     || new_column > Chessboard.COLUMN_MAX)
                 {
                     continue;
                 }
                 var new_cell = ChessboardCell.CalculateValue(new_row, new_column);
                 if (!my_pieces.IsOccupiedCell(new_cell))
                 {
                     bool is_capture = other_pieces.IsOccupiedCell(new_cell);
                     moves.Add(new Move(Exports.Pieces.Knight, knight_cell.Value,
                         new_cell, cell_index,
                         is_capture ? Move.Flags.Capture : 0));
                 }
             }
         }
     }
 }
 public static PlayerPieceSet InsertPiece(PlayerPieceSet base_obj,
     Exports.Pieces piece_to_insert, int insert_at_cell)
 {
     Debug.Assert(base_obj != null);
     Debug.Assert(piece_to_insert != Exports.Pieces.NoPiece
         && piece_to_insert != Exports.Pieces.King);
     Debug.Assert(insert_at_cell >= 0 && insert_at_cell < 64);
     Debug.Assert(!base_obj.IsOccupiedCell(insert_at_cell));
     var result = (PlayerPieceSet)base_obj.MemberwiseClone();
     result.m_bitboard.SetBit(insert_at_cell);
     uint start_index = 0;
     uint cur_piece_count = 0;
     switch (piece_to_insert)
     {
         // TODO - add checks like PawnsCount < MAX_PAWN_COUNT
         case Exports.Pieces.Pawn:
             start_index = result.PawnsStartIndex;
             cur_piece_count = result.PawnsCount;
             ++result.PawnsCount;
             break;
         case Exports.Pieces.Knight:
             start_index = result.KnightsStartIndex;
             cur_piece_count = result.KnightsCount;
             // Increment result.KnightsCount
             ++result.PawnsStartIndex;
             break;
         case Exports.Pieces.Bishop:
             start_index = result.BishopsStartIndex;
             cur_piece_count = result.BishopsCount;
             // Increment result.BishopsCount
             ++result.PawnsStartIndex;
             ++result.KnightsStartIndex;
             break;
         case Exports.Pieces.Rook:
             start_index = result.RooksStartIndex;
             cur_piece_count = result.RooksCount;
             // Increment result.RooksCount
             ++result.PawnsStartIndex;
             ++result.KnightsStartIndex;
             ++result.BishopsStartIndex;
             break;
         case Exports.Pieces.Queen:
             start_index = result.QueensStartIndex;
             cur_piece_count = result.QueensCount;
             // Increment result.QueensCount
             ++result.PawnsStartIndex;
             ++result.KnightsStartIndex;
             ++result.BishopsStartIndex;
             ++result.RooksStartIndex;
             break;
     }
     result.m_pieces_cells.InsertAt(result.m_pieces_cells
         .GetInsertionIndex(start_index, cur_piece_count, insert_at_cell),
         insert_at_cell);
     return result;
 }
 public static bool IsBishopAttacks(ChessboardCell bishop_cell,
     ChessboardCell cell_to_check, PlayerPieceSet my_pieces,
     PlayerPieceSet other_pieces)
 {
     return bishop_cell.IsSameDiagonal(cell_to_check)
         && IsCellAttackedFromDir(cell_to_check, bishop_cell,
         my_pieces, other_pieces);
 }
 public static PlayerPieceSet RemovePiece(PlayerPieceSet base_obj,
     Exports.Pieces piece_to_remove, int remove_at_cell)
 {
     Debug.Assert(base_obj != null);
     Debug.Assert(piece_to_remove != Exports.Pieces.NoPiece
         && piece_to_remove != Exports.Pieces.King);
     Debug.Assert(remove_at_cell >= 0 && remove_at_cell < 64);
     Debug.Assert(base_obj.IsOccupiedCell(remove_at_cell));
     var result = (PlayerPieceSet)base_obj.MemberwiseClone();
     result.m_bitboard.UnsetBit(remove_at_cell);
     uint start_index = 0;
     switch (piece_to_remove)
     {
         case Exports.Pieces.Pawn:
             start_index = result.PawnsStartIndex;
             Debug.Assert(result.PawnsCount > 0);
             --result.PawnsCount;
             break;
         case Exports.Pieces.Knight:
             start_index = result.KnightsStartIndex;
             Debug.Assert(result.KnightsCount > 0);
             // Decrement result.KnightsCount
             --result.PawnsStartIndex;
             break;
         case Exports.Pieces.Bishop:
             start_index = result.BishopsStartIndex;
             Debug.Assert(result.BishopsCount > 0);
             // Decrement result.BishopsCount
             --result.PawnsStartIndex;
             --result.KnightsStartIndex;
             break;
         case Exports.Pieces.Rook:
             start_index = result.RooksStartIndex;
             Debug.Assert(result.RooksCount > 0);
             // Decrement result.RooksCount
             --result.PawnsStartIndex;
             --result.KnightsStartIndex;
             --result.BishopsStartIndex;
             break;
         case Exports.Pieces.Queen:
             start_index = result.QueensStartIndex;
             Debug.Assert(result.QueensCount > 0);
             // Decrement result.QueensCount
             --result.PawnsStartIndex;
             --result.KnightsStartIndex;
             --result.BishopsStartIndex;
             --result.RooksStartIndex;
             break;
     }
     result.m_pieces_cells.EraseAt((uint)result.m_pieces_cells
         .FindNextIndex(start_index, remove_at_cell));
     return result;
 }
        private static void MakeDiagonalMoves(Exports.Pieces piece,
            PlayerPieceSet my_pieces, PlayerPieceSet other_pieces, int from_cell,
            uint cell_index, List<Move> moves)
        {
            Debug.Assert(piece == Exports.Pieces.Bishop
                || piece == Exports.Pieces.Queen);

            var from_cell_obj = new ChessboardCell(from_cell);
            // Down-left diagonal
            MakeMovesAlongLine(piece, my_pieces, other_pieces, from_cell, -1, -1,
                Math.Min(from_cell_obj.Row, from_cell_obj.Column),
                moves);
            // Down-right diagonal
            MakeMovesAlongLine(piece, my_pieces, other_pieces, from_cell, 1, -1,
                Math.Min(Chessboard.ROW_MAX - from_cell_obj.Row, from_cell_obj.Column),
                moves);
            // Up-right diagonal
            MakeMovesAlongLine(piece, my_pieces, other_pieces, from_cell, 1, 1,
                Math.Min(Chessboard.ROW_MAX - from_cell_obj.Row,
                Chessboard.COLUMN_MAX - from_cell_obj.Column),
                moves);
            // Up-left diagonal
            MakeMovesAlongLine(piece, my_pieces, other_pieces, from_cell, -1, 1,
                Math.Min(from_cell_obj.Row, Chessboard.COLUMN_MAX - from_cell_obj.Column),
                moves);
        }