Ejemplo n.º 1
0
 public void First()
 {
     while (index > 0)
     {
         index--;
         BoardGround.UnmakeMove(moveList [index], true);
     }
 }
Ejemplo n.º 2
0
 public void Previous()
 {
     if (index > 0)
     {
         index--;
         BoardGround.UnmakeMove(moveList [index], true);
     }
 }
Ejemplo n.º 3
0
    /// Creates and adds king move to move list. Also checks legality if not in psuedolegal mode.
    /// castleThroughIndex is the square which king passes through during castling (so that can't castle through check)
    void CreateKingMove(int fromIndex, int toIndex, int castleThroughIndex, bool isCastles)
    {
        ushort newMove           = (ushort)(fromIndex | toIndex << 7);
        int    capturedPieceType = BoardGround.boardArray[toIndex] & ~1;
        int    moveOrderEval     = 0;

        if (!pseudolegalMode)           // if not in psuedolegal mode, elimate moves that leave king in check / castling through check

        {
            BoardGround.MakeMove(newMove);
            bool inCheckAfterMove = SquareAttackedByEnemy(toIndex);
            BoardGround.UnmakeMove(newMove);
            if (inCheckAfterMove)
            {
                return;
            }
        }

        if (isCastles)
        {
            if (inCheck)
            {
                return;
            }

            if (SquareAttackedByEnemy(castleThroughIndex))               // cannot castle if castling through check
            {
                return;
            }

            if (trackStats)
            {
                castles++;
            }
        }

        if (trackStats)
        {
            if (BoardGround.boardColourArray[toIndex] == (1 - moveColour))
            {
                captures++;
            }
        }


        moves.Add(newMove, (short)moveOrderEval);
    }
Ejemplo n.º 4
0
    void PerfTest(int depth)
    {
        if (depth == 0)
        {
            nodeSearchCount++;
            return;
        }

        IList <ushort> moves = moveGenerator.GetMoves(false, false) as IList <ushort>;

        for (int i = 0; i < moves.Count; i++)
        {
            BoardGround.MakeMove(moves[i]);
            PerfTest(depth - 1);
            BoardGround.UnmakeMove(moves[i]);
        }
    }
Ejemplo n.º 5
0
    /// Creates and adds move to move list. Also checks legality if not in psuedolegal mode
    /// Note: for king moves use separate CreateKingMove method
    void CreateMove(int fromIndex, int toIndex)
    {
        ushort newMove           = (ushort)(fromIndex | toIndex << 7);
        int    capturedPieceType = BoardGround.boardArray[toIndex] & ~1;


        if (!pseudolegalMode)           // if not in psuedolegal mode, elimate moves that leave king in check
        {
            BoardGround.MakeMove(newMove);
            bool inCheckAfterMove = InCheckAfterMove(fromIndex, toIndex, capturedPieceType);
            BoardGround.UnmakeMove(newMove);
            if (inCheckAfterMove)
            {
                return;
            }
        }

        if (trackStats)
        {
            if (BoardGround.boardColourArray[toIndex] == (1 - moveColour))
            {
                captures++;
            }
        }

        int movePieceType = BoardGround.boardArray [fromIndex] & ~1;
        int moveOrderEval = 0;

        if (capturedPieceType != 0)                                                                        // capture move
        {
            moveOrderEval = PieceEvalFromType(capturedPieceType) + 100 - PieceEvalFromType(movePieceType); // prefer capturing high-value enemy piece with low-value friendly piece
        }
        else                                                                                               // non capture move
        {
            int toRank    = BoardGround.RankFrom128(toIndex);
            int direction = (moveColour == 1)?1:-1;
            if (Math.Sign(toRank - BoardGround.RankFrom128(fromIndex)) != direction)               // penalise retreating moves
            {
                moveOrderEval = -10;
            }
        }

        moves.Add(newMove, (short)moveOrderEval);
    }
Ejemplo n.º 6
0
    /// Creates and adds move to move list. Also checks legality if not in psuedolegal mode
    /// Note: for king moves use separate CreateKingMove method
    void CreatePawnMove(int fromIndex, int toIndex, int epCaptureIndex = -1)
    {
        ushort newMove           = (ushort)(fromIndex | toIndex << 7);
        int    capturedPieceType = BoardGround.boardArray[toIndex] & ~1;

        if (!pseudolegalMode)           // if not in psuedolegal mode, elimate moves that leave king in check

        {
            BoardGround.MakeMove(newMove);
            bool inCheckAfterMove = InCheckAfterMove(fromIndex, toIndex, capturedPieceType);
            //bool inCheck = SquareAttackedByPlayer(friendlyKingIndex,(1-moveColour));
            BoardGround.UnmakeMove(newMove);
            if (inCheckAfterMove)
            {
                return;
            }
        }

        if (trackStats)
        {
            if (BoardGround.boardColourArray[toIndex] == (1 - moveColour) || toIndex == epCaptureIndex)
            {
                captures++;
            }
        }



        if (toIndex >= 112 || toIndex <= 7)           // pawn is promoting
        {
            if (trackStats)
            {
                promotions += 4;
            }
            moves.Add(newMove, 100);                      //promote to queen
            moves.Add((ushort)(newMove | 1 << 14), -80);  // rook
            moves.Add((ushort)(newMove | 2 << 14), -70);  // knight
            moves.Add((ushort)(newMove | 3 << 14), -100); // bishop
        }
        else
        {
            int movePieceType = BoardGround.boardArray [fromIndex] & ~1;
            int moveOrderEval = 0;
            int toRank        = BoardGround.RankFrom128(toIndex);

            if (movePieceType == BoardGround.pawnCode)               // prefer to move pawn the further advanced it is
            {
                if (moveColour == 1)
                {
                    if (toRank > 5)
                    {
                        moveOrderEval = 10 * (toRank - 5);
                    }
                }
                else
                {
                    if (toRank < 4)
                    {
                        moveOrderEval = 10 * (4 - toRank);
                    }
                }
            }
            moves.Add(newMove, (short)moveOrderEval);              // regular pawn move
        }
    }
Ejemplo n.º 7
0
    int AlphaBetaSearch(int plyRemaining, int alpha, int beta, bool isWhite)
    {
        HeapGround moveHeap = moveGenerator.GetMoves(false, false);
        int        count    = moveHeap.Count;

        if (moveHeap.Count == 0)
        {
            return(((isWhite)?-1:1) * (10000000 + plyRemaining));          // if no moves available, side has been checkmated. Return best score for opponent. Checkmating sooner (higher depth) is rewarded.
        }


        if (plyRemaining == 0)
        {
            nodesSearched++;
            return(Evaluate());
            //QuiescenceSearch(int.MinValue,int.MaxValue,!isWhite,true);
            //return quiescenceScore;
        }
        if (isWhite)           // white is trying to attain the highest evaluation possible

        {
            for (int i = 0; i < count; i++)
            {
                ushort move = moveHeap.RemoveFirst();
                BoardGround.MakeMove(move);
                alpha = Math.Max(alpha, AlphaBetaSearch(plyRemaining - 1, alpha, beta, false));
                BoardGround.UnmakeMove(move);

                if (plyRemaining == searchDepth)                   // has searched full depth and is now looking at top layer of moves to select the best
                {
                    if (alpha > bestScoreThisIteration)
                    {
                        bestScoreThisIteration = alpha;
                        bestMoveThisIteration  = move;
                    }
                }

                if (beta <= alpha)                   // break
                {
                    breakCount++;
                    break;
                }
            }
            return(alpha);
        }
        else
        {
            // black is trying to obtain the lowest evaluation possible
            for (int i = 0; i < count; i++)
            {
                ushort move = moveHeap.RemoveFirst();
                BoardGround.MakeMove(move);
                beta = Math.Min(beta, AlphaBetaSearch(plyRemaining - 1, alpha, beta, true));
                BoardGround.UnmakeMove(move);

                if (plyRemaining == searchDepth)                   // has searched full depth and is now looking at top layer of moves to select the best
                {
                    if (beta < bestScoreThisIteration)
                    {
                        bestScoreThisIteration = beta;
                        bestMoveThisIteration  = move;
                    }
                }

                if (beta <= alpha)                   // break
                {
                    breakCount++;
                    break;
                }
            }

            return(beta);
        }

        return(0);
    }
Ejemplo n.º 8
0
    /// Returns a list of moves given a pgn string.
    /// Note that BoardGround should be set to whatever starting position of pgn is.
    public static List <ushort> MovesFromPGN(string pgn)
    {
        List <string> moveStrings = MoveStringsFromPGN(pgn);
        List <ushort> allMoves    = new List <ushort> ();

        MoveGeneratorGround moveGen = new MoveGeneratorGround();

        for (int i = 0; i < moveStrings.Count; i++)
        {
            string moveString = moveStrings[i];

            moveString = moveString.Replace("+", "");            // remove check symbol
            moveString = moveString.Replace("#", "");            // remove mate symbol
            moveString = moveString.Replace("x", "");            // remove capture symbol
            string moveStringLower = moveStrings[i].ToLower();

            ushort[] movesInPosition = moveGen.GetMoves(false, false).moves;
            ushort   move            = 0;
            for (int j = 0; j < movesInPosition.Length; j++)
            {
                move = movesInPosition[j];
                int moveFromIndex = move & 127;
                int moveToIndex   = (move >> 7) & 127;
                int movePieceType = BoardGround.boardArray[moveFromIndex] & ~1;
                int colourCode    = BoardGround.boardArray[moveFromIndex] & 1;


                if (moveStringLower == "oo")                   // castle kingside
                {
                    if (movePieceType == BoardGround.kingCode && moveToIndex - moveFromIndex == 2)
                    {
                        break;
                    }
                }
                else if (moveStringLower == "ooo")                   // castle queenside
                {
                    if (movePieceType == BoardGround.kingCode && moveToIndex - moveFromIndex == -2)
                    {
                        break;
                    }
                }
                else if (DefinitionsGround.fileNames.Contains(moveString[0] + ""))                   // pawn move if starts with any file indicator (e.g. 'e'4. Note that uppercase B is used for bishops)
                {
                    if (movePieceType != BoardGround.pawnCode)
                    {
                        continue;
                    }
                    if (DefinitionsGround.FileNumberFromAlgebraicName(moveStringLower[0]) == BoardGround.FileFrom128(moveFromIndex)) // correct starting file
                    {
                        if (moveString.Contains("="))                                                                                // is promotion
                        {
                            char promotionChar = moveStringLower[moveStringLower.Length - 1];

                            int promotionPieceIndex = move >> 14 & 3;
                            int promotionPieceCode  = BoardGround.pieceCodeArray [promotionPieceIndex];

                            if ((promotionPieceCode == BoardGround.queenCode && promotionChar != 'q') || (promotionPieceCode == BoardGround.rookCode && promotionChar != 'r') ||
                                (promotionPieceCode == BoardGround.bishopCode && promotionChar != 'b') || (promotionPieceCode == BoardGround.knightCode && promotionChar != 'n'))
                            {
                                continue;                                 // skip this move, incorrect promotion type
                            }
                            break;
                        }
                        else
                        {
                            char targetFile = moveString[moveString.Length - 2];
                            char targetRank = moveString[moveString.Length - 1];

                            if (DefinitionsGround.FileNumberFromAlgebraicName(targetFile) == BoardGround.FileFrom128(moveToIndex))                               // correct ending file
                            {
                                if (DefinitionsGround.RankNumberFromAlgebraicName(targetRank) == BoardGround.RankFrom128(moveToIndex))                           // correct ending rank
                                {
                                    break;
                                }
                            }
                        }
                    }
                }
                else                   // regular piece move

                {
                    char movePieceChar = moveString[0];
                    if (!(movePieceType == BoardGround.queenCode && movePieceChar == 'Q') && !(movePieceType == BoardGround.rookCode && movePieceChar == 'R') &&
                        !(movePieceType == BoardGround.bishopCode && movePieceChar == 'B') && !(movePieceType == BoardGround.knightCode && movePieceChar == 'N') && !(movePieceType == BoardGround.kingCode && movePieceChar == 'K'))
                    {
                        continue;                         // skip this move, incorrect move piece type
                    }

                    char targetFile = moveString[moveString.Length - 2];
                    char targetRank = moveString[moveString.Length - 1];
                    if (DefinitionsGround.FileNumberFromAlgebraicName(targetFile) == BoardGround.FileFrom128(moveToIndex))     // correct ending file
                    {
                        if (DefinitionsGround.RankNumberFromAlgebraicName(targetRank) == BoardGround.RankFrom128(moveToIndex)) // correct ending rank
                        {
                            if (moveString.Length == 4)                                                                        // addition char present for disambiguation (e.g. Nbd7 or R7e2)
                            {
                                char disambiguationChar = moveString[1];

                                if (DefinitionsGround.fileNames.Contains(disambiguationChar + ""))                                                   // is file disambiguation
                                {
                                    if (DefinitionsGround.FileNumberFromAlgebraicName(disambiguationChar) != BoardGround.FileFrom128(moveFromIndex)) // incorrect starting file
                                    {
                                        continue;
                                    }
                                }
                                else                                                                                                                 // is rank disambiguation
                                {
                                    if (DefinitionsGround.RankNumberFromAlgebraicName(disambiguationChar) != BoardGround.RankFrom128(moveFromIndex)) // incorrect starting rank
                                    {
                                        continue;
                                    }
                                }
                            }
                            break;
                        }
                    }
                }
            }
            if (move == 0)               // move is illegal; discard and return moves up to this point
            {
                UnityEngine.Debug.Log(moveString);
                break;
            }
            else
            {
                allMoves.Add(move);
            }
            BoardGround.MakeMove(move);
        }
        for (int i = allMoves.Count - 1; i >= 0; i--)
        {
            BoardGround.UnmakeMove(allMoves[i]);
        }

        return(allMoves);
    }
Ejemplo n.º 9
0
    public static string NotationFromMove(ushort move)
    {
        BoardGround.UnmakeMove(move);          // unmake move on board

        MoveGeneratorGround moveGen = new MoveGeneratorGround();
        int moveFromIndex           = move & 127;
        int moveToIndex             = (move >> 7) & 127;
        int promotionPieceIndex     = (move >> 14) & 3;     // 0 = queen, 1 = rook, 2 = knight, 3 = bishop
        int colourToMove            = BoardGround.boardColourArray[moveFromIndex];

        int movePieceCode     = BoardGround.boardArray [moveFromIndex]; // get move piece code
        int movePieceType     = movePieceCode & ~1;                     // get move piece type code (no colour info)
        int capturedPieceCode = BoardGround.boardArray [moveToIndex];   // get capture piece code

        int promotionPieceType = BoardGround.pieceCodeArray [promotionPieceIndex];

        if (movePieceType == BoardGround.kingCode)
        {
            if (moveToIndex - moveFromIndex == 2)
            {
                BoardGround.MakeMove(move);                  // remake move
                return("O-O");
            }
            else if (moveToIndex - moveFromIndex == -2)
            {
                BoardGround.MakeMove(move);                  // remake move
                return("O-O-O");
            }
        }

        string moveNotation = GetSymbolFromPieceType(movePieceType);

        // check if any ambiguity exists in notation (e.g if e2 can be reached via Nfe2 and Nbe2)
        if (movePieceType != BoardGround.pawnCode && movePieceType != BoardGround.kingCode)
        {
            HeapGround allMoves = moveGen.GetMoves(false, false);

            for (int i = 0; i < allMoves.Count; i++)
            {
                int alternateMoveFromIndex = allMoves.moves[i] & 127;
                int alternateMoveToIndex   = (allMoves.moves[i] >> 7) & 127;
                int alternateMovePieceCode = BoardGround.boardArray [alternateMoveFromIndex];

                if (alternateMoveFromIndex != moveFromIndex && alternateMoveToIndex == moveToIndex) // if moving to same square from different square
                {
                    if (alternateMovePieceCode == movePieceCode)                                    // same piece type
                    {
                        int fromFileIndex          = BoardGround.FileFrom128(moveFromIndex) - 1;
                        int alternateFromFileIndex = BoardGround.FileFrom128(alternateMoveFromIndex) - 1;
                        int fromRankIndex          = BoardGround.RankFrom128(moveFromIndex) - 1;
                        int alternateFromRankIndex = BoardGround.RankFrom128(alternateMoveFromIndex) - 1;

                        if (fromFileIndex != alternateFromFileIndex)                           // pieces on different files, thus ambiguity can be resolved by specifying file
                        {
                            moveNotation += DefinitionsGround.fileNames[fromFileIndex];
                            break;                             // ambiguity resolved
                        }
                        else if (fromRankIndex != alternateFromRankIndex)
                        {
                            moveNotation += DefinitionsGround.rankNames[fromRankIndex];
                            break;                             // ambiguity resolved
                        }
                    }
                }
            }
        }

        if (capturedPieceCode != 0)           // add 'x' to indicate capture
        {
            if (movePieceType == BoardGround.pawnCode)
            {
                moveNotation += DefinitionsGround.fileNames[BoardGround.FileFrom128(moveFromIndex) - 1];
            }
            moveNotation += "x";
        }
        else             // check if capturing ep
        {
            if (movePieceType == BoardGround.pawnCode)
            {
                if (System.Math.Abs(moveToIndex - moveFromIndex) != 16 && System.Math.Abs(moveToIndex - moveFromIndex) != 32)
                {
                    moveNotation += DefinitionsGround.fileNames[BoardGround.FileFrom128(moveFromIndex) - 1] + "x";
                }
            }
        }

        moveNotation += DefinitionsGround.fileNames [BoardGround.FileFrom128(moveToIndex) - 1];
        moveNotation += DefinitionsGround.rankNames [BoardGround.RankFrom128(moveToIndex) - 1];

        // add = piece type if promotion
        if (movePieceType == BoardGround.pawnCode)
        {
            if (moveToIndex >= 112 || moveToIndex <= 7)               // pawn has reached first/eighth rank
            {
                moveNotation += "=" + GetSymbolFromPieceType(promotionPieceType);
            }
        }

        // add check/mate symbol if applicable
        BoardGround.MakeMove(move);          // remake move
        if (moveGen.PositionIsMate())
        {
            moveNotation += "#";
        }
        else if (moveGen.PositionIsCheck())
        {
            moveNotation += "+";
        }
        return(moveNotation);
    }
Ejemplo n.º 10
0
    static void ProcessFiles(string[] files, int minGameLengthPly, int recordToPly)
    {
        BoardGround.SetPositionFromFen(DefinitionsGround.startFen);

        // Read pgns and convert to opening book dictionary
        for (int fileIndex = 0; fileIndex < files.Length; fileIndex++)
        {
            StreamReader  reader = new StreamReader(files[fileIndex]);
            List <string> pgns   = new List <string>();

            // split text into array of pgn strings
            bool readingPGN         = false;
            int  pgnIndex           = -1;
            bool finishedReadingPGN = false;
            while (reader.Peek() != -1)
            {
                string line = reader.ReadLine() + " ";
                if (line.Contains("["))                   // comment line
                {
                    finishedReadingPGN = false;
                    readingPGN         = false;
                    continue;
                }
                else if (!finishedReadingPGN)
                {
                    for (int charIndex = 0; charIndex < line.Length; charIndex++)
                    {
                        if (!readingPGN && line[charIndex] == '1')
                        {
                            readingPGN = true;
                            pgns.Add("");
                            pgnIndex++;
                        }
                        if (readingPGN)
                        {
                            pgns[pgnIndex] += line[charIndex] + "";
                            if (pgns[pgnIndex].Split('.').Length * 2 > recordToPly)                               // only record the first n moves for opening book
                            {
                                finishedReadingPGN = true;
                                break;
                            }
                        }
                    }
                }
            }

            reader.Close();

            // get moves from pgn files
            for (int i = 0; i < pgns.Count; i++)
            {
                string pgn = pgns[i];

                if (pgn.Split('.').Length * 2 < minGameLengthPly)                   // don't record games that were shorter than minGameLengthPly. This is to avoid games where an opening distaster occured
                {
                    continue;
                }

                List <string> moveStrings = PGNReaderGround.MoveStringsFromPGN(pgn);
                List <ushort> moves       = PGNReaderGround.MovesFromPGN(pgn);

                for (int j = 0; j < moves.Count; j++)
                {
                    if (!book.ContainsKey(BoardGround.zobristKey))
                    {
                        keys.Add(BoardGround.zobristKey);
                        book.Add(BoardGround.zobristKey, new List <ushort>());
                    }
                    if (!book[BoardGround.zobristKey].Contains(moves[j]))
                    {
                        book[BoardGround.zobristKey].Add(moves[j]);
                    }
                    BoardGround.MakeMove(moves[j]);
                }
                for (int k = moves.Count - 1; k >= 0; k--)
                {
                    BoardGround.UnmakeMove(moves[k]);
                }
            }
        }
    }