Ejemplo n.º 1
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;
    }
Ejemplo n.º 2
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.º 3
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);
    }
Ejemplo n.º 4
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);
    }