Ejemplo n.º 1
0
        public static void MirrorBoard(Board board)
        {
            int[] t_PiecesArray = new int[64];
            int   t_side        = board.Side ^ 1; // Changes side
            int   t_castlePerm  = 0;
            int   t_enPas       = (int)Square.NO_SQ;

            // First we reverse castlepermissions.
            if ((board.CastlePerm & (int)Castling.WKCA) != 0)
            {
                t_castlePerm |= (int)Castling.BKCA;
            }

            if ((board.CastlePerm & (int)Castling.WQCA) != 0)
            {
                t_castlePerm |= (int)Castling.BQCA;
            }

            if ((board.CastlePerm & (int)Castling.BKCA) != 0)
            {
                t_castlePerm |= (int)Castling.WKCA;
            }

            if ((board.CastlePerm & (int)Castling.BQCA) != 0)
            {
                t_castlePerm |= (int)Castling.WQCA;
            }

            // En pas
            if (board.EnPas != (int)Square.NO_SQ)
            {
                t_enPas = Conversion.getSq64ToSq120(Data.mirror64Table[Conversion.getSq120ToSq64(board.EnPas)]);
            }

            for (int i = 0; i < 64; i++)
            {
                var mirror120Sq = Conversion.getSq64ToSq120(Data.mirror64Table[i]);
                t_PiecesArray[i] = board[mirror120Sq];
            }

            // Have all info so now we reset and put information in.
            BoardOperations.ResetBoard(board);

            for (int i = 0; i < 64; i++)
            {
                int reversedPiece = (int)Data.SWAP_PIECE[t_PiecesArray[i]];
                board[Conversion.getSq64ToSq120(i)] = reversedPiece;
            }

            board.Side       = t_side;
            board.EnPas      = t_enPas;
            board.CastlePerm = t_castlePerm;
            board.PosKey     = Hashkeys.GeneratePosKey(board);

            BoardOperations.UpdateListsMaterial(board);

            Debug.Assert(BoardOperations.CheckBoard(board));
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Parses the input FEN string onto the board.
        /// </summary>
        /// <param name="fen"> The FEN-string to parse. </param>
        /// <param name="board"> The board to update. </param>
        /// <returns></returns>
        public static int ParseFen(string fen, Board board)
        {
            int rank = (int)Rank.RANK_8;
            int file = (int)File.FILE_A;

            int  fenIndex = 0;
            int  i        = 0;
            char fenChar  = ' ';

            BoardOperations.ResetBoard(board);

            while (rank >= (int)Rank.RANK_1 && fenIndex <= fen.Length)
            {
                fenChar = fen[fenIndex];
                var count = 1;
                var piece = 0;
                switch (fenChar)
                {
                case 'p': piece = (int)Piece.bP;
                    break;

                case 'r': piece = (int)Piece.bR;
                    break;

                case 'n': piece = (int)Piece.bN;
                    break;

                case 'b': piece = (int)Piece.bB;
                    break;

                case 'k': piece = (int)Piece.bK;
                    break;

                case 'q': piece = (int)Piece.bQ;
                    break;

                case 'P': piece = (int)Piece.wP;
                    break;

                case 'R': piece = (int)Piece.wR;
                    break;

                case 'N': piece = (int)Piece.wN;
                    break;

                case 'B': piece = (int)Piece.wB;
                    break;

                case 'K': piece = (int)Piece.wK;
                    break;

                case 'Q': piece = (int)Piece.wQ;
                    break;

                case '1':
                case '2':
                case '3':
                case '4':
                case '5':
                case '6':
                case '7':
                case '8':
                    piece = (int)Piece.EMPTY;
                    count = fenChar - '0';     // holds the number of empty squares.
                    break;

                case '/':
                case ' ':
                    rank--;
                    file = (int)File.FILE_A;
                    fenIndex++;
                    continue;

                default:
                    Console.Write("FEN Error default \n");
                    return(-1);
                }

                for (i = 0; i < count; i++)
                {
                    var sq64  = (int)rank * 8 + (int)file;
                    var sq120 = Conversion.getSq64ToSq120(sq64);
                    if (piece != (int)Piece.EMPTY)
                    {
                        board[sq120] = piece;
                    }

                    file++;
                }

                fenIndex++;
            }

            fenChar = fen[fenIndex];

            board.Side = (fenChar == 'w') ? (int)Colour.WHITE : (int)Colour.BLACK;
            fenIndex  += 2;    // We're now at castling permissions.

            for (i = 0; i < 4; i++)
            {
                fenChar = fen[fenIndex];
                if (fenChar == ' ')
                {
                    break;
                }

                switch (fenChar)
                {
                case 'K':
                    board.CastlePerm |= (int)Castling.WKCA;
                    break;

                case 'Q':
                    board.CastlePerm |= (int)Castling.WQCA;
                    break;

                case 'k':
                    board.CastlePerm |= (int)Castling.BKCA;
                    break;

                case 'q':
                    board.CastlePerm |= (int)Castling.BQCA;
                    break;

                default:
                    break;
                }
                fenIndex++;
            }

            fenIndex++;
            fenChar = fen[fenIndex];     // We're not at the ENPASSANT SQ.


            if (board.CastlePerm >= 0 && board.CastlePerm <= 15)
            {
                if (fenChar != '-')       // if there is an enpassant sq.
                {
                    file        = fenChar - 'a';
                    rank        = fen[fenIndex + 1] - '1';
                    board.EnPas = (int)Conversion.FR2SQ(file, rank);
                }

                BoardOperations.UpdateListsMaterial(board);

                board.PosKey = Hashkeys.GeneratePosKey(board);

                return(0);
            }
            else
            {
                Console.WriteLine("FEN CASTLEPERM ERROR");
                return(-1);
            }
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Validator for the board state. Ensures all board data structures are inorder.
        /// Will throw an exception if something is astray.
        /// </summary>
        /// <remarks>
        /// CheckBoard is a very time consuming method,
        /// why it's only called if compiled in DEBUG
        /// </remarks>
        /// <param name="board"> The board to validate </param>
        /// <returns> True, if the board is valid </returns>
        public static bool CheckBoard(Board board)
        {
            int[] t_pceNum   = new int[13];
            int[] t_bigPce   = new int[2];
            int[] t_majPce   = new int[2];
            int[] t_minPce   = new int[2];
            int[] t_material = new int[2];

            ulong[]    t_pawns          = { 0UL, 0UL, 0UL };
            BitArray[] t_pawnsBitArrray = new BitArray[3];

            for (int i = 0; i < board.Pawns.Length; ++i)
            {
                t_pawns[i] = board.Pawns[i];
            }

            // check piece lists:
            for (int t_piece = (int)Piece.wP; t_piece <= (int)Piece.bK; ++t_piece)
            {
                for (int t_pce_num = 0; t_pce_num < board.PceNum[t_piece]; ++t_pce_num)
                {
                    int sq120 = board.PList[t_piece, t_pce_num];
                    if (board[sq120] != t_piece)
                    {
                        BoardOperations.PrintBoard(board);
                        throw new Exception(String.Format(
                                                "Error in the piece lists. Expected piece {0} on square {1}, but found piece {2} on board",
                                                (Piece)t_piece, Io.SqToString(sq120), (Piece)board[sq120]));
                    }
                }
            }

            // check piece counters.
            for (int sq64 = 0; sq64 < 64; ++sq64)
            {
                int sq120   = Conversion.getSq64ToSq120(sq64);
                int t_piece = board[sq120];
                t_pceNum[t_piece]++;
                Colour pceColour = Data.PIECE_COLOURS[t_piece];
                if (Data.IS_PIECE_BIG[t_piece])
                {
                    t_bigPce[(int)pceColour]++;
                }

                if (Data.IS_PIECE_MIN[t_piece])
                {
                    t_minPce[(int)pceColour]++;
                }

                if (Data.IS_PIECE_MAJ[t_piece])
                {
                    t_majPce[(int)pceColour]++;
                }

                if (pceColour != Colour.BOTH)
                {
                    t_material[(int)pceColour] += Data.PIECE_VAL[t_piece];
                }
            }

            for (int t_piece = (int)Piece.wP; t_piece <= (int)Piece.wK; ++t_piece)
            {
                if (t_pceNum[t_piece] != board.PceNum[t_piece])
                {
                    throw new Exception("PceNum does not match board PceNum");
                }
            }

            // For ulong
            for (int i = 0; i < (int)Colour.BOTH; ++i)
            {
                int pawn_count = BitBoard.CountBits(t_pawns[i]);
                if (i == (int)Colour.WHITE)
                {
                    if (pawn_count != board.PceNum[(int)Piece.wP])
                    {
                        throw new Exception(
                                  "white pawn bit count does not match white PceNum count.");
                    }
                }
                else if (i == (int)Colour.BLACK)
                {
                    if (pawn_count != board.PceNum[(int)Piece.bP])
                    {
                        throw new Exception("Black pawn bit count does not match black PceNum count.");
                    }
                }
                else     // COLOUR.BOTH
                {
                    if (pawn_count != (board.PceNum[(int)Piece.wP] + board.PceNum[(int)Piece.bP]))
                    {
                        throw new Exception("BOTH pawn bit count does not match BOTH PceNum count.");
                    }
                }
            }

            for (int i = 0; i < (int)Colour.BOTH; ++i)
            {
                while (t_pawns[i] != 0)
                {
                    int pawn_sq64 = BitBoard.PopBit(ref t_pawns[i]);
                    int sq120     = Conversion.getSq64ToSq120(pawn_sq64);
                    int pawn      = 0;
                    if (i == (int)Colour.WHITE)
                    {
                        pawn = (int)Piece.wP;
                    }
                    else if (i == (int)Colour.BLACK)
                    {
                        pawn = (int)Piece.bP;
                    }
                    else     // Colour.BOTH
                    {
                        if (board[sq120] != (int)Piece.wP &&
                            board[sq120] != (int)Piece.bP)
                        {
                            throw new Exception(String.Format("Found {0} on {1} instead of a pawn", (Piece)board[sq120], Io.SqToString(sq120)));
                        }
                        continue;
                    }

                    if (board[sq120] != pawn)
                    {
                        throw new Exception(String.Format("Found {0} on {1} instead of a pawn", (Piece)board[sq120], Io.SqToString(sq120)));
                    }
                }
            }

            if (t_material[(int)Colour.WHITE] != board.Material[(int)Colour.WHITE] ||
                t_material[(int)Colour.BLACK] != board.Material[(int)Colour.BLACK])
            {
                Console.WriteLine("WHITE:\n\tt_material: {0}\n\tboard.material: {1}",
                                  t_material[(int)Colour.WHITE], board.Material[(int)Colour.WHITE]);
                throw new Exception("Material doesnt match with tempoary material.");
            }

            if (t_bigPce[(int)Colour.WHITE] != board.BigPieces[(int)Colour.WHITE] ||
                t_bigPce[(int)Colour.BLACK] != board.BigPieces[(int)Colour.BLACK])
            {
                throw new Exception("BigPces doesnt match with tempoary BigPces.");
            }

            if (t_minPce[(int)Colour.WHITE] != board.MinPieces[(int)Colour.WHITE] ||
                t_minPce[(int)Colour.BLACK] != board.MinPieces[(int)Colour.BLACK])
            {
                throw new Exception("minPce doesnt match with tempoary minPces.");
            }

            if (t_majPce[(int)Colour.WHITE] != board.MajPieces[(int)Colour.WHITE] ||
                t_majPce[(int)Colour.BLACK] != board.MajPieces[(int)Colour.BLACK])
            {
                throw new Exception("majPce doesnt match with tempoary majPces.");
            }

            if (board.Side != (int)Colour.WHITE && board.Side != (int)Colour.BLACK)
            {
                throw new Exception("Side to play on the board is neither black or white.");
            }

            if (board.PosKey != Hashkeys.GeneratePosKey(board))
            {
                throw new Exception("Position key doesnt match the generated poskey.");
            }

            /// Check enPas sq.
            if (board.EnPas != (int)Square.NO_SQ)
            {
                if ((board.Side == (int)Colour.WHITE) && (Conversion.getRanksBrd(board.EnPas) != (int)Rank.RANK_6))
                {
                    throw new Exception("The EnPas square is invalid");
                }
                else if ((board.Side == (int)Colour.BLACK) &&
                         (Conversion.getRanksBrd(board.EnPas) != (int)Rank.RANK_3))
                {
                    throw new Exception("The EnPas square is invalid");
                }
            }


            // Check kingsquares

            /// white king
            if (board[board.KingSq[(int)Colour.WHITE]] != (int)Piece.wK)
            {
                throw new Exception("White king square is wrong.");
            }
            /// black king
            if (board[board.KingSq[(int)Colour.BLACK]] != (int)Piece.bK)
            {
                int blackKingSq = board.KingSq[(int)Colour.BLACK];
                throw new Exception(String.Format("Expected black king on square {0}, but found pce {1} on board", Io.SqToString(blackKingSq), (Piece)board[blackKingSq]));
            }

            return(true);
        }