コード例 #1
0
 public void Next()
 {
     if (index < moveList.Count)
     {
         BoardGround.MakeMove(moveList [index], true);
         index++;
     }
 }
コード例 #2
0
 public void Previous()
 {
     if (index > 0)
     {
         index--;
         BoardGround.UnmakeMove(moveList [index], true);
     }
 }
コード例 #3
0
 void Update()
 {
     Debug.LogError("Test");
     BoardGround.MakeMove(new MoveGeneratorGround().GetMoves(false, false).GetMove(0), true);
     if (Input.GetKeyDown(KeyCode.Space))
     {
         MoveGeneratorGround.Debug();
     }
 }
コード例 #4
0
 // draw requested by player
 public void Draw()
 {
     if (BoardGround.ThreefoldRepetition())
     {
         GameOver(0, DefinitionsGround.ResultType.Repetition);
     }
     else if (BoardGround.halfmoveCountSinceLastPawnMoveOrCap >= 100)
     {
         GameOver(0, DefinitionsGround.ResultType.FiftyMoveRule);
     }
 }
コード例 #5
0
    public void HighlightMove(int fromIndex, int toIndex)
    {
        int fromX = GetIndex(BoardGround.FileFrom128(fromIndex) - 1);
        int fromY = GetIndex(BoardGround.RankFrom128(fromIndex) - 1);
        int toX   = GetIndex(BoardGround.FileFrom128(toIndex) - 1);
        int toY   = GetIndex(BoardGround.RankFrom128(toIndex) - 1);

        // highlight move squares;
        squares [fromX, fromY].material.color = themes[themeIndex].moveFromHighlightColour;
        squares [toX, toY].material.color     = themes[themeIndex].moveToHighlightColour;
    }
コード例 #6
0
    public static void DebugGameState(ushort state)
    {
        UnityEngine.Debug.Log("state " + state);
        bool whiteToMove       = (state & 1) != 0;
        bool w00               = (state & 1 << 1) != 0;
        bool w000              = (state & 1 << 2) != 0;
        bool b00               = (state & 1 << 3) != 0;
        bool b000              = (state & 1 << 4) != 0;
        int  epFile            = (state >> 5) & 15;
        int  capturedPieceCode = (state >> 9) & 15;

        UnityEngine.Debug.Log("white to move: " + whiteToMove);
        UnityEngine.Debug.Log("white 0-0 " + w00 + " 0-0-0 " + w000 + " black 0-0 " + b00 + " 0-0-0 " + b000);
        UnityEngine.Debug.Log("ep file: " + epFile);
        string boardString  = "";
        string colourString = "";

        if (capturedPieceCode != 0)
        {
            UnityEngine.Debug.Log("Captured piece: " + pieceNameDictionary [capturedPieceCode]);
        }

        for (int y = 7; y >= 0; y--)
        {
            for (int x = 0; x < 8; x++)
            {
                int i = BoardGround.Convert64to128(y * 8 + x);
                // pieces
                int code = boardArray [i];
                if (code == 0)
                {
                    boardString += " # ";
                }
                else
                {
                    boardString += " " + pieceNameDictionary [code] + " ";
                }

                // colour
                string colString = (boardColourArray[i] == 0)?" B ":" W ";
                if (boardColourArray[i] == -1)
                {
                    colString = " # ";
                }
                colourString += colString;
            }
            boardString  += "\n";
            colourString += "\n";
        }
        UnityEngine.Debug.Log(boardString);
        UnityEngine.Debug.Log(colourString);
        UnityEngine.Debug.Log("########################### \n");
    }
コード例 #7
0
    int RunTest()
    {
        nodeSearchCount = 0;


        BoardGround.SetPositionFromFen(fen);
        TimerGround.Start("PerftGround");
        PerfTest(searchDepth);
        TimerGround.Stop("PerftGround");
        TimerGround.Print("PerftGround");
        print("Leaf nodes at depth " + searchDepth + ": " + nodeSearchCount);
        return(nodeSearchCount);
    }
コード例 #8
0
    void OnMove(ushort move)
    {
        int moveToIndex       = (move >> 7) & 127;
        int capturedPieceCode = BoardGround.boardArray [moveToIndex];         // get capture piece code

        if (capturedPieceCode == 0)
        {
            AudioSource.PlayClipAtPoint(moveAudio, Vector3.zero, 1f);
        }
        else
        {
            AudioSource.PlayClipAtPoint(captureAudio, Vector3.zero, 1f);
        }

        BoardGround.MakeMove(move, true);

        if (OnMoveMade != null)
        {
            OnMoveMade(whiteToPlay, move);
        }

        whiteToPlay = !whiteToPlay;

        // detect mate/stalemate
        if (moveGenerator.PositionIsMate())
        {
            GameOver(((whiteToPlay) ? -1 : 1), DefinitionsGround.ResultType.Checkmate);              // player is mated
        }
        else if (moveGenerator.PositionIsStaleMate())
        {
            GameOver(0, DefinitionsGround.ResultType.Stalemate);              // player is mated
        }
        else if (moveGenerator.InsuffientMatingMaterial())
        {
            GameOver(0, DefinitionsGround.ResultType.InsufficientMaterial);
        }
        else
        {
            if (whitePlayerType == PlayerType.AI && blackPlayerType == PlayerType.AI)
            {
                StartCoroutine(RequestMoveCoroutine(.15f));                   // force delay between moves when two AI are playing
            }
            else
            {
                RequestMove();
            }
        }
    }
コード例 #9
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);
    }
コード例 #10
0
    /// Updates the board UI to match the board array
    public void AutoUpdate()
    {
        ResetHighlights();
        for (int i = 0; i < 8; i++)
        {
            for (int j = 0; j < 8; j++)
            {
                int x = GetIndex(j);
                int y = GetIndex(i);

                int  index     = BoardGround.Convert64to128(i * 8 + j);
                char pieceCode = BoardGround.pieceNameDictionary[BoardGround.boardArray[index]];
                board[x, y] = pieceCode;
                pieceSquares[x, y].sprite = spriteDictionary[pieceCode];
            }
        }
    }
コード例 #11
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]);
        }
    }
コード例 #12
0
    public void StartSearch()
    {
        bestMoveSoFar = 0;
        transpositionTable.Clear();

        nodesSearched = 0;
        breakCount    = 0;

        finishedSearch = false;

        moveGenerator       = new MoveGeneratorGround();
        findingMoveForWhite = BoardGround.IsWhiteToPlay();

        Thread searchThread = new Thread(Iterate);

        searchThread.Start();
        //Iterate ();
    }
コード例 #13
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);
    }
コード例 #14
0
    public void CreatePlayers()
    {
        boardInput = GetComponent <ChessInputGround>();

        HumanPlayerGround whiteHuman = null;
        HumanPlayerGround blackHuman = null;
        AIPlayerGround    whiteAI    = null;
        AIPlayerGround    blackAI    = null;

        if (blackPlayerType == PlayerType.Human)
        {
            ChessUIGround.instance.SetBoardOrientation(false);
            blackHuman = new HumanPlayerGround();
            boardInput.AddPlayer(blackHuman);
        }
        else
        {
            blackAI = new AIPlayerGround();
        }

        if (whitePlayerType == PlayerType.Human)
        {
            ChessUIGround.instance.SetBoardOrientation(true);
            whiteHuman = new HumanPlayerGround();
            boardInput.AddPlayer(whiteHuman);
            // FindObjectOfType<NotationInput>().SetPlayer(whiteHuman);
        }
        else
        {
            whiteAI = new AIPlayerGround();
        }

        whitePlayer = (PlayerGround)whiteHuman ?? (PlayerGround)whiteAI;
        blackPlayer = (PlayerGround)blackHuman ?? (PlayerGround)blackAI;

        whitePlayer.OnMove += OnMove;
        blackPlayer.OnMove += OnMove;

        whitePlayer.Init(true);
        blackPlayer.Init(false);

        whiteToPlay = BoardGround.IsWhiteToPlay();
        RequestMove();
    }
コード例 #15
0
    void HighlightSquare(ushort move, string pieceAlgebraic)
    {
        int moveFromIndex = move & 127;
        int moveToIndex   = (move >> 7) & 127;

        int moveFromX = BoardGround.Convert128to64(moveFromIndex) % 8;
        int moveFromY = BoardGround.Convert128to64(moveFromIndex) / 8;
        int moveToX   = BoardGround.Convert128to64(moveToIndex) % 8;
        int moveToY   = BoardGround.Convert128to64(moveToIndex) / 8;


        string fromAlgebraic = DefinitionsGround.fileNames[moveFromX].ToString() + DefinitionsGround.rankNames[moveFromY].ToString();
        string toAlgebraic   = DefinitionsGround.fileNames[moveToX].ToString() + DefinitionsGround.rankNames[moveToY].ToString();

        if (fromAlgebraic == pieceHeld.algebraicCoordinate)
        {
            ChessUIGround.instance.HighlightSquare(toAlgebraic);
        }
    }
コード例 #16
0
    public static void PrintBoard(string optionalHeader = "")
    {
        string boardString  = "";
        string colourString = "";

        if (optionalHeader != "")
        {
            optionalHeader += ":\n";
        }

        for (int y = 7; y >= 0; y--)
        {
            for (int x = 0; x < 8; x++)
            {
                int i = BoardGround.Convert64to128(y * 8 + x);
                // pieces
                int code = boardArray [i];
                if (code == 0)
                {
                    boardString += " # ";
                }
                else
                {
                    boardString += " " + pieceNameDictionary [code] + " ";
                }

                // colour
                string colString = (boardColourArray[i] == 0)?" B ":" W ";
                if (boardColourArray[i] == -1)
                {
                    colString = " # ";
                }
                colourString += colString;
            }
            boardString  += "\n";
            colourString += "\n";
        }
        UnityEngine.Debug.Log(optionalHeader + boardString);
    }
コード例 #17
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);
    }
コード例 #18
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
        }
    }
コード例 #19
0
    void GenerateMove(int moveFromIndex)
    {
        int moveToIndex;

        int movePieceType = BoardGround.boardArray [moveFromIndex] & ~1;         // piece type code

        // Moving the king:
        if (movePieceType == BoardGround.kingCode)
        {
            for (int overlayIndex = 0; overlayIndex < kingOverlay.Length; overlayIndex++)
            {
                moveToIndex = moveFromIndex + kingOverlay[overlayIndex];
                if (IndexOnBoard(moveToIndex))
                {
                    if (BoardGround.boardColourArray[moveToIndex] != moveColour)                       // can't move to square occupied by friendly piece
                    {
                        CreateKingMove(moveFromIndex, moveToIndex, 0, false);
                    }
                }
            }

            // Castling:
            if (moveColour == 1 && moveFromIndex == 4)                                    // white king still on starting square
            {
                if ((BoardGround.currentGamestate >> 1 & 1) == 1)                         // has 0-0 right
                {
                    if (BoardGround.boardArray[5] == 0 && BoardGround.boardArray[6] == 0) // no pieces blocking castling
                    {
                        CreateKingMove(4, 6, 5, true);
                    }
                }
                if ((BoardGround.currentGamestate >> 2 & 1) == 1)                                                           // has 0-0-0 right
                {
                    if (BoardGround.boardArray[3] == 0 && BoardGround.boardArray[2] == 0 && BoardGround.boardArray[1] == 0) // no pieces blocking castling
                    {
                        CreateKingMove(4, 2, 3, true);
                    }
                }
            }
            else if (moveColour == 0 && moveFromIndex == 116)                                 // black king still on starting square
            {
                if ((BoardGround.currentGamestate >> 3 & 1) == 1)                             // has 0-0 right
                {
                    if (BoardGround.boardArray[117] == 0 && BoardGround.boardArray[118] == 0) // no pieces blocking castling
                    {
                        CreateKingMove(116, 118, 117, true);
                    }
                }
                if ((BoardGround.currentGamestate >> 4 & 1) == 1)                                                                 // has 0-0-0 right
                {
                    if (BoardGround.boardArray[115] == 0 && BoardGround.boardArray[114] == 0 && BoardGround.boardArray[113] == 0) // no pieces blocking castling
                    {
                        CreateKingMove(116, 114, 115, true);
                    }
                }
            }
        }

        // Moving the knight:
        else if (movePieceType == BoardGround.knightCode)
        {
            for (int overlayIndex = 0; overlayIndex < knightOverlay.Length; overlayIndex++)
            {
                moveToIndex = moveFromIndex + knightOverlay[overlayIndex];
                if (IndexOnBoard(moveToIndex))
                {
                    if (BoardGround.boardColourArray[moveToIndex] != moveColour)                       // can't move to square occupied by friendly piece
                    {
                        CreateMove(moveFromIndex, moveToIndex);
                    }
                }
            }
        }
        // Moving a pawn:
        else if (movePieceType == BoardGround.pawnCode)
        {
            int pawnDirection = (moveColour == 1)?1:-1;
            moveToIndex = moveFromIndex + pawnDirection * 16;
            if (moveToIndex < 0 || moveToIndex >= BoardGround.boardArray.Length)
            {
                BoardGround.DebugGameState(BoardGround.currentGamestate);
                UnityEngine.Debug.Log("Pawn error: move to: " + moveToIndex + "  from: " + moveFromIndex + "  dir: " + pawnDirection);
            }
            if (BoardGround.boardArray[moveToIndex] == 0)                                                 // square in front of pawn is unnocupied
            {
                CreatePawnMove(moveFromIndex, moveToIndex);                                               // regular pawn move

                if ((moveFromIndex <= 23 && moveColour == 1) || (moveFromIndex >= 96 && moveColour == 0)) // pawn on starting rank
                {
                    moveToIndex = moveFromIndex + pawnDirection * 32;
                    if (BoardGround.boardArray[moveToIndex] == 0)                       // if no pieces blocking double pawn push
                    {
                        CreatePawnMove(moveFromIndex, moveToIndex);                     // move two squares
                    }
                }
            }
            int epCaptureIndex = (BoardGround.currentGamestate >> 5 & 15) - 1 + ((opponentColour == 0)?80:32);
            // pawn captures
            moveToIndex = moveFromIndex + (16 - pawnDirection) * pawnDirection;           // capture left (from white's pov)
            if (IndexOnBoard(moveToIndex))
            {
                if (BoardGround.boardColourArray[moveToIndex] == opponentColour || moveToIndex == epCaptureIndex) // if capture square contains opponent piece or is ep capture square
                {
                    CreatePawnMove(moveFromIndex, moveToIndex, epCaptureIndex);                                   // TODO: ep capture index parameter is only for stat counting. Remove.
                }
            }
            moveToIndex = moveFromIndex + (16 + pawnDirection) * pawnDirection;           // capture right (from white's pov)
            if (IndexOnBoard(moveToIndex))
            {
                if (BoardGround.boardColourArray[moveToIndex] == opponentColour || moveToIndex == epCaptureIndex) // if capture square contains opponent piece or is ep capture square
                {
                    CreatePawnMove(moveFromIndex, moveToIndex, epCaptureIndex);                                   // TODO: ep capture index parameter is only for stat counting. Remove.
                }
            }
        }
        // Queen, rook and bishop
        else
        {
            int startIndex = 0;
            int endIndex   = 7;

            if (movePieceType == BoardGround.bishopCode)
            {
                startIndex = 4;                 // skip horizontal overlays
            }
            else if (movePieceType == BoardGround.rookCode)
            {
                endIndex = 3;                 // skip diagonal overlays
            }

            for (int overlayIndex = startIndex; overlayIndex <= endIndex; overlayIndex++)
            {
                for (int i = 1; i <= 8; i++)
                {
                    moveToIndex = moveFromIndex + kingOverlay[overlayIndex] * i;
                    bool lineOpen = IndexOnBoard(moveToIndex);
                    if (lineOpen)
                    {
                        if (BoardGround.boardArray[moveToIndex] != 0)                           // something is obstructing movement
                        {
                            lineOpen = false;
                        }
                        if (BoardGround.boardColourArray[moveToIndex] != moveColour)                           // if square is not friendly, i.e contains enemy or no piece, square can be moves to
                        {
                            CreateMove(moveFromIndex, moveToIndex);
                        }
                    }
                    if (!lineOpen)
                    {
                        break;                         // stop searching this line once it has reached obstruction/end of board
                    }
                }
            }
        }
    }
コード例 #20
0
    /// Updates the board UI to match the board array
    public void AutoUpdate()
    {
        // Debug.Log("Inside AutoUpdate()");
        ResetHighlights();
        for (int i = 0; i < 8; i++)
        {
            for (int j = 0; j < 8; j++)
            {
                int x = GetIndex(j);
                int y = GetIndex(i);

                int  index     = BoardGround.Convert64to128(i * 8 + j);
                char pieceCode = BoardGround.pieceNameDictionary[BoardGround.boardArray[index]];
                board[x, y] = pieceCode;

                // Neither black nor white. We only need a box collider here. No mesh collider.
                if (pieceCode == ' ')
                {
                    // pieceSquares[x, y].GetComponent<EventTrigger>().enabled = false;
                    pieceSquares[x, y].GetComponent <MeshCollider>().enabled = false;
                    pieceSquares[x, y].mesh = null;
                }
                // Black. We need an additional mesh collider here.
                else if (pieceCode == 'r' || pieceCode == 'n' || pieceCode == 'b' || pieceCode == 'q' || pieceCode == 'k' || pieceCode == 'p')
                {
                    // pieceSquares[x, y].GetComponent<EventTrigger>().enabled = true;
                    pieceSquares[x, y].GetComponent <MeshCollider>().enabled = true;
                    // If its a pawn then we assign the mesh(for the collider) of rook.
                    if (pieceCode == 'p')
                    {
                        pieceSquares[x, y].GetComponent <MeshCollider>().sharedMesh = filterDictionary['r'];
                    }
                    // If its anything other than pawn we assign the mesh(for the collider) of itself.
                    else
                    {
                        pieceSquares[x, y].GetComponent <MeshCollider>().sharedMesh = filterDictionary[pieceCode];
                    }

                    pieceSquares[x, y].GetComponent <MeshRenderer>().material = blackMaterial;

                    pieceSquares[x, y].mesh = filterDictionary[pieceCode];
                }
                // White. We need an additional mesh collider here.
                else
                {
                    // pieceSquares[x, y].GetComponent<EventTrigger>().enabled = true;
                    pieceSquares[x, y].GetComponent <MeshCollider>().enabled = true;
                    // If its a pawn then we assign the mesh(for the collider) of rook.
                    if (pieceCode == 'P')
                    {
                        pieceSquares[x, y].GetComponent <MeshCollider>().sharedMesh = filterDictionary['R'];
                    }
                    // If its anything other than pawn we assign the mesh(for the collider) of itself.
                    else
                    {
                        pieceSquares[x, y].GetComponent <MeshCollider>().sharedMesh = filterDictionary[pieceCode];
                    }

                    pieceSquares[x, y].GetComponent <MeshRenderer>().material = whiteMaterial;

                    pieceSquares[x, y].mesh = filterDictionary[pieceCode];
                }

                // pieceSquares[x, y].sprite = spriteDictionary[pieceCode];
            }
        }
    }
コード例 #21
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);
    }
コード例 #22
0
 public void Init()
 {
     BoardGround.SetPositionFromFen(DefinitionsGround.startFen, true);
 }
コード例 #23
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);
    }
コード例 #24
0
    public static int Evaluate()
    {
        TimerGround.Start("Eval");
        int materialEval    = 0;
        int mobilityEval    = 0;
        int developmentEval = 0;
        int kingSafetyEval  = 0;

        // piece index vars (assigned when found to be used in later calculations)
        int        whiteKingSquareIndex = -1;
        int        blackKingSquareIndex = -1;
        List <int> whiteQueenIndices    = new List <int> (2);
        List <int> whiteRookIndices     = new List <int> (2);
        List <int> whiteKnightIndices   = new List <int> (2);
        List <int> whiteBishopIndices   = new List <int> (2);
        List <int> whitePawnIndices     = new List <int> (8);

        List <int> blackQueenIndices  = new List <int> (2);
        List <int> blackRookIndices   = new List <int> (2);
        List <int> blackKnightIndices = new List <int> (2);
        List <int> blackBishopIndices = new List <int> (2);
        List <int> blackPawnIndices   = new List <int> (8);


        for (int squareIndex = 0; squareIndex <= 127; squareIndex++)
        {
            if ((squareIndex & 8) != 0)               // don't look at indices which are not on the real board
            {
                continue;
            }

            if (BoardGround.boardArray[squareIndex] != 0)
            {
                int pieceCode = BoardGround.boardArray[squareIndex];
                if (pieceCode == BoardGround.kingCode + 1)                   // found white king
                {
                    whiteKingSquareIndex = squareIndex;
                }
                else if (pieceCode == BoardGround.kingCode)                   // found black king
                {
                    blackKingSquareIndex = squareIndex;
                }
                else                                        // non-king pieces
                {
                    materialEval += pieceValues[pieceCode]; // count material (excluding kings)

                    switch (pieceCode)
                    {
                    case BoardGround.queenCode + 1:
                        whiteQueenIndices.Add(squareIndex);
                        break;

                    case BoardGround.rookCode + 1:
                        whiteRookIndices.Add(squareIndex);
                        break;

                    case BoardGround.knightCode + 1:
                        whiteKnightIndices.Add(squareIndex);
                        break;

                    case BoardGround.bishopCode + 1:
                        whiteBishopIndices.Add(squareIndex);
                        break;

                    case BoardGround.pawnCode + 1:
                        whitePawnIndices.Add(squareIndex);
                        break;

                    case BoardGround.queenCode:
                        blackQueenIndices.Add(squareIndex);
                        break;

                    case BoardGround.rookCode:
                        blackRookIndices.Add(squareIndex);
                        break;

                    case BoardGround.knightCode:
                        blackKnightIndices.Add(squareIndex);
                        break;

                    case BoardGround.bishopCode:
                        blackBishopIndices.Add(squareIndex);
                        break;

                    case BoardGround.pawnCode:
                        blackPawnIndices.Add(squareIndex);
                        break;
                    }
                }
            }
        }

        if (whiteKingSquareIndex == -1)           // return best score for black if white's king has been captured (this may sometimes be allowed during alphabeta search for faster move generation)
        //return int.MinValue;
        {
        }


        // piece mobility
        moveGenerator.SetMoveColour(1);
        mobilityEval += moveGenerator.GetMoves(false, true, false).Count;         // white piece mobility
        mobilityEval += moveGenerator.GetMoves(true, true, false).Count;          // white piece attacking black
        moveGenerator.SetMoveColour(0);
        mobilityEval -= moveGenerator.GetMoves(false, true, false).Count;         // black piece mobility
        mobilityEval -= moveGenerator.GetMoves(true, true, false).Count;          // black piece attacking white

        // piece development white
        for (int i = 0; i < whiteKnightIndices.Count; i++)
        {
            if (BoardGround.RankFrom128(whiteKnightIndices[i]) == 1)               // penalize knight remaining on first rank
            {
                developmentEval -= 50;
            }
            else if (BoardGround.RankFrom128(whiteKnightIndices[i]) == 2)               // penalize knight remaining on second rank
            {
                developmentEval -= 10;
            }
            if (BoardGround.FileFrom128(whiteKnightIndices[i]) == 1)               // knights on the rim are dim
            {
                developmentEval -= 5;
            }
            else if (BoardGround.FileFrom128(whiteKnightIndices[i]) == 8)               // knights on the rim are dim
            {
                developmentEval -= 5;
            }
        }

        for (int i = 0; i < whiteBishopIndices.Count; i++)
        {
            if (BoardGround.RankFrom128(whiteBishopIndices[i]) == 1)               // penalize bishop remaining on first rank
            {
                developmentEval -= 50;
            }
        }

        // piece development black
        for (int i = 0; i < blackKnightIndices.Count; i++)
        {
            if (BoardGround.RankFrom128(blackKnightIndices[i]) == 8)               // penalize knight remaining on eighth rank
            {
                developmentEval += 50;
            }
            else if (BoardGround.RankFrom128(blackKnightIndices[i]) == 7)               // penalize knight remaining on seventh rank
            {
                developmentEval += 10;
            }
            if (BoardGround.FileFrom128(blackKnightIndices[i]) == 1)               // knights on the rim are dim
            {
                developmentEval += 5;
            }
            else if (BoardGround.FileFrom128(blackKnightIndices[i]) == 8)               // knights on the rim are dim
            {
                developmentEval += 5;
            }
        }

        for (int i = 0; i < blackBishopIndices.Count; i++)
        {
            if (BoardGround.RankFrom128(blackBishopIndices[i]) == 8)               // penalize bishop remaining on eighth rank
            {
                developmentEval += 50;
            }
        }

        // king safety white
        if (BoardGround.WhiteHasCastlingRights())
        {
            kingSafetyEval += 10;             // not safe, but at least retaining ability to castle
        }
        else
        {
            if (whiteKingSquareIndex == 6 || whiteKingSquareIndex == 7)               // generally safe kingside squares for king (g1,h1)
            {
                kingSafetyEval += 50;
                for (int i = 0; i < whiteRookIndices.Count; i++)
                {
                    if (BoardGround.FileFrom128(whiteRookIndices[i]) > 6)
                    {
                        kingSafetyEval -= 55;                         // penalize non-castling king manoeuvres where rook is boxed in by king
                    }
                }
            }
            else if (whiteKingSquareIndex == 2 || whiteKingSquareIndex == 1 || whiteKingSquareIndex == 0)               // generally safe queenside squares for king (a1,b1,c1)
            {
                kingSafetyEval += 50;
                for (int i = 0; i < whiteRookIndices.Count; i++)
                {
                    if (BoardGround.FileFrom128(whiteRookIndices[i]) < 3)
                    {
                        kingSafetyEval -= 55;                         // penalize non-castling king manoeuvres where rook is boxed in by king
                    }
                }
            }
        }
        // king safety black
        if (BoardGround.BlackHasCastlingRights())
        {
            kingSafetyEval -= 10;             // not safe, but at least retaining ability to castle
        }
        else
        {
            if (blackKingSquareIndex == 118 || blackKingSquareIndex == 119)               // generally safe kingside squares for king (g8,h8)
            {
                kingSafetyEval -= 50;
                for (int i = 0; i < blackRookIndices.Count; i++)
                {
                    if (BoardGround.FileFrom128(blackRookIndices[i]) > 6)
                    {
                        kingSafetyEval += 55;                         // penalize non-castling king manoeuvres where rook is boxed in by king
                    }
                }
            }
            else if (blackKingSquareIndex == 114 || blackKingSquareIndex == 113 || blackKingSquareIndex == 112)               // generally safe queenside squares for king (a8,b8,c8)
            {
                kingSafetyEval -= 50;
                for (int i = 0; i < blackRookIndices.Count; i++)
                {
                    if (BoardGround.FileFrom128(blackRookIndices[i]) < 3)
                    {
                        kingSafetyEval += 55;                         // penalize non-castling king manoeuvres where rook is boxed in by king
                    }
                }
            }
        }

        int openingMaterialCount = 16 * pawnValue + 4 * (rookValue + knightValue + bishopValue) + 2 * queenValue;
        int endgameMaterialCount = 2 * (rookValue + knightValue);

        //float gameStage =

        int finalEval = materialEval * 1000 + mobilityEval + kingSafetyEval + developmentEval;

        TimerGround.Stop("Eval");
        return(finalEval);
    }
コード例 #25
0
 void Start()
 {
     Debug.LogError("Test");
     BoardGround.SetPositionFromFen(DefinitionsGround.startFen, true);
 }
コード例 #26
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]);
                }
            }
        }
    }