Exemple #1
0
 /*
  * Remove EPSquare from position if it is not legal
  */
 private static void fixupEPSquare(Position position)
 {
     int epSquare = position.getEpSquare();
     if (epSquare >= 0)
     {
         ArrayList moves = MoveGenerator.mgInstance.legalMoves(position);
         Boolean epValid = false;
         foreach (Move move in moves)
         {
             if (move.destination == epSquare)
             {
                 if (position.getPiece(move.origin) == (position.whiteMove ? PieceType.P : PieceType.p))
                 {
                     epValid = true;
                     break;
                 }
             }
         }
         if (!epValid)
         {
             position.setEpSquare(-1);
         }
     }
 }
Exemple #2
0
        /*
         * Parse a FEN string and return a position object
         */
        public static Position convertFENToPosition(String fen)
        {
            Position position = new Position();
            String[] terms = fen.Split(' ');
            if (terms.Length < 2)
            {
                System.Console.WriteLine("Too few terms");
            }
            for (int i = 0; i < terms.Length; i++)
            {
                terms[i] = terms[i].Trim();
            }

            //Piece placement
            int rank = 7;
            int file = 0;
            for (int i = 0; i < terms[0].Length; i++)
            {
                char c = (char)terms[0].ToCharArray().GetValue(i);
                switch (c)
                {
                    case '1': file += 1; break;
                    case '2': file += 2; break;
                    case '3': file += 3; break;
                    case '4': file += 4; break;
                    case '5': file += 5; break;
                    case '6': file += 6; break;
                    case '7': file += 7; break;
                    case '8': file += 8; break;
                    case '/': rank--; file = 0; break;
                    case 'P': setPieceSafely(position, file, rank, PieceType.P); file++; break;
                    case 'N': setPieceSafely(position, file, rank, PieceType.N); file++; break;
                    case 'B': setPieceSafely(position, file, rank, PieceType.B); file++; break;
                    case 'R': setPieceSafely(position, file, rank, PieceType.R); file++; break;
                    case 'Q': setPieceSafely(position, file, rank, PieceType.Q); file++; break;
                    case 'K': setPieceSafely(position, file, rank, PieceType.K); file++; break;
                    case 'p': setPieceSafely(position, file, rank, PieceType.p); file++; break;
                    case 'n': setPieceSafely(position, file, rank, PieceType.n); file++; break;
                    case 'b': setPieceSafely(position, file, rank, PieceType.b); file++; break;
                    case 'r': setPieceSafely(position, file, rank, PieceType.r); file++; break;
                    case 'q': setPieceSafely(position, file, rank, PieceType.q); file++; break;
                    case 'k': setPieceSafely(position, file, rank, PieceType.k); file++; break;
                    default: throw new ParserError("Invalid Piece", position);
                }
            }

            //Active Colour
            if (terms[1].Length > 0)
            {
                Boolean whiteToMove;
                char c = (char)terms[1].ToCharArray().GetValue(0);
                switch (c)
                {
                    case 'w': whiteToMove = true; break;
                    case 'b': whiteToMove = false; break;
                    default: throw new ParserError("Invalid Active Colour", position);
                }
                position.setWhiteMove(whiteToMove);
            }
            else
            {
                throw new ParserError("Invalid Active Colour", position);
            }

            //Castling Rights
            int castleMask = 0;
            if (terms.Length > 2)
            {
                for (int i = 0; i < terms[2].Length; i++)
                {
                    char c = (char)terms[2].ToCharArray().GetValue(i);
                    switch (c)
                    {
                        case 'K':
                            castleMask |= (1 << Position.H1_CASTLE);
                            break;
                        case 'Q':
                            castleMask |= (1 << Position.A1_CASTLE);
                            break;
                        case 'k':
                            castleMask |= (1 << Position.H8_CASTLE);
                            break;
                        case 'q':
                            castleMask |= (1 << Position.A8_CASTLE);
                            break;
                        case '-':
                            break;
                        default:
                            throw new ParserError("Invalid castling flags", position);
                    }

                }
            }
            position.setCastleMask(castleMask);
            removeInvalidCastleFlags(position);

            //En Passant Target Square
            if (terms.Length > 3)
            {
                String epString = terms[3];
                if (!epString.Equals("-"))
                {
                    if (epString.Length < 2)
                    {
                        throw new ParserError("Invalid En Passent Square", position);
                    }
                    position.setEpSquare(getSquare(epString));
                }
            }

            try
            {
                //Halfmove Clock
                if (terms.Length > 4)
                {
                    position.halfMoveClock = Convert.ToInt32(terms[4]);
                }
                //Full Move Counter
                if (terms.Length > 5)
                {
                    position.fullMoveCounter = Convert.ToInt32(terms[5]);
                }
            }
            catch (ArgumentException ae)
            {
                //Ignore errors here since fields are optional
            }

            //Each side must have exactly one king
            int maxNumber = (int)PieceType.Empty + 1;
            int[] numPieces = new int[maxNumber];
            for (int i = 0; i < maxNumber; i++)
            {
                numPieces[i] = 0;
            }
            for (file = 0; file < 8; file++)
            {
                for (rank = 0; rank < 8; rank++)
                {
                    numPieces[(int)position.getPiece(Position.getSquare(file, rank))]++;
                }
            }
            if (numPieces[(int)PieceType.K] != 1)
            {
                throw new ParserError("Too many white kings", position);
            }
            if (numPieces[(int)PieceType.k] != 1)
            {
                throw new ParserError("Too many black kings", position);
            }

            //White must not have too many pieces
            int maxWPawns = 8;
            maxWPawns -= Math.Max(0, numPieces[(int)PieceType.N] - 2);
            maxWPawns -= Math.Max(0, numPieces[(int)PieceType.B] - 2);
            maxWPawns -= Math.Max(0, numPieces[(int)PieceType.R] - 2);
            maxWPawns -= Math.Max(0, numPieces[(int)PieceType.Q] - 1);
            if (numPieces[(int)PieceType.P] > maxWPawns)
            {
                throw new ParserError("Too many white pieces", position);
            }

            //Black must not have too many pieces
            int maxBPawns = 8;
            maxBPawns -= Math.Max(0, numPieces[(int)PieceType.n] - 2);
            maxBPawns -= Math.Max(0, numPieces[(int)PieceType.b] - 2);
            maxBPawns -= Math.Max(0, numPieces[(int)PieceType.r] - 2);
            maxBPawns -= Math.Max(0, numPieces[(int)PieceType.q] - 1);

            //Make sure king can not be captured
            Position pos2 = new Position(position);
            pos2.setWhiteMove(!position.whiteMove);
            if (MoveGenerator.inCheck(pos2))
            {
                throw new ParserError("King capture possible", position);
            }

            fixupEPSquare(position);

            return position;
        }
Exemple #3
0
        /*
         * Convert a piece placement string to a position object
         * This does not have to adhere to the strict rules of how
         * many pieces a player must have. i.e.(player may have no king)
         * This is primarily used for testing purposes, as well as tutorial
         * scenarios.
         */
        public static Position convertPiecePlacementToPosition(String fen)
        {
            Position position = new Position();
            String[] terms = fen.Split(' ');
            if (terms.Length < 2)
            {
                System.Console.WriteLine("Too few terms");
            }
            for (int i = 0; i < terms.Length; i++)
            {
                terms[i] = terms[i].Trim();
            }

            //Piece placement
            int rank = 7;
            int file = 0;
            for (int i = 0; i < terms[0].Length; i++)
            {
                char c = (char)terms[0].ToCharArray().GetValue(i);
                switch (c)
                {
                    case '1': file += 1; break;
                    case '2': file += 2; break;
                    case '3': file += 3; break;
                    case '4': file += 4; break;
                    case '5': file += 5; break;
                    case '6': file += 6; break;
                    case '7': file += 7; break;
                    case '8': file += 8; break;
                    case '/': rank--; file = 0; break;
                    case 'P': position.setPiece(Position.getSquare(file, rank), PieceType.P); file++; break;
                    case 'N': position.setPiece(Position.getSquare(file, rank), PieceType.N); file++; break;
                    case 'B': position.setPiece(Position.getSquare(file, rank), PieceType.B); file++; break;
                    case 'R': position.setPiece(Position.getSquare(file, rank), PieceType.R); file++; break;
                    case 'Q': position.setPiece(Position.getSquare(file, rank), PieceType.Q); file++; break;
                    case 'K': position.setPiece(Position.getSquare(file, rank), PieceType.K); file++; break;
                    case 'p': position.setPiece(Position.getSquare(file, rank), PieceType.p); file++; break;
                    case 'n': position.setPiece(Position.getSquare(file, rank), PieceType.n); file++; break;
                    case 'b': position.setPiece(Position.getSquare(file, rank), PieceType.b); file++; break;
                    case 'r': position.setPiece(Position.getSquare(file, rank), PieceType.r); file++; break;
                    case 'q': position.setPiece(Position.getSquare(file, rank), PieceType.q); file++; break;
                    case 'k': position.setPiece(Position.getSquare(file, rank), PieceType.k); file++; break;
                    default: throw new ParserError("Invalid Piece", position);
                }
            }

            //Active Colour
            if (terms[1].Length > 0)
            {
                Boolean whiteToMove;
                char c = (char)terms[1].ToCharArray().GetValue(0);
                switch (c)
                {
                    case 'w': whiteToMove = true; break;
                    case 'b': whiteToMove = false; break;
                    default: throw new ParserError("Invalid Active Colour", position);
                }
                position.setWhiteMove(whiteToMove);
            }
            else
            {
                throw new ParserError("Invalid Active Colour", position);
            }

            //Castling Rights
            int castleMask = 0;
            if (terms.Length > 2)
            {
                for (int i = 0; i < terms[2].Length; i++)
                {
                    char c = (char)terms[2].ToCharArray().GetValue(i);
                    switch (c)
                    {
                        case 'K':
                            castleMask |= (1 << Position.H1_CASTLE);
                            break;
                        case 'Q':
                            castleMask |= (1 << Position.A1_CASTLE);
                            break;
                        case 'k':
                            castleMask |= (1 << Position.H8_CASTLE);
                            break;
                        case 'q':
                            castleMask |= (1 << Position.A8_CASTLE);
                            break;
                        case '-':
                            break;
                        default:
                            throw new ParserError("Invalid castling flags", position);
                    }

                }
            }
            position.setCastleMask(castleMask);
            removeInvalidCastleFlags(position);

            //En Passant Target Square
            if (terms.Length > 3)
            {
                String epString = terms[3];
                if (!epString.Equals("-"))
                {
                    if (epString.Length < 2)
                    {
                        throw new ParserError("Invalid En Passent Square", position);
                    }
                    position.setEpSquare(getSquare(epString));
                }
            }

            try
            {
                //Halfmove Clock
                if (terms.Length > 4)
                {
                    position.halfMoveClock = Convert.ToInt32(terms[4]);
                }
                //Full Move Counter
                if (terms.Length > 5)
                {
                    position.fullMoveCounter = Convert.ToInt32(terms[5]);
                }
            }
            catch (ArgumentException ae)
            {
                //Ignore errors here since fields are optional
                Console.WriteLine(ae.ToString());
            }

            fixupEPSquare(position);

            return position;
        }