static PrecomputedMoveData()
        {
            pawnAttacksWhite = new int[64][];
            pawnAttacksBlack = new int[64][];
            numSquaresToEdge = new int[8][];
            knightMoves      = new byte[64][];
            kingMoves        = new byte[64][];
            numSquaresToEdge = new int[64][];

            rookMoves   = new ulong[64];
            bishopMoves = new ulong[64];
            queenMoves  = new ulong[64];

            int[] allKnightJumps = { 15, 17, -17, -15, 10, -6, 6, -10 };
            knightAttackBitboards = new ulong[64];
            kingAttackBitboards   = new ulong[64];
            pawnAttackBitboards   = new ulong[64][];

            for (int squareIndex = 0; squareIndex < 64; squareIndex++)
            {
                int y = squareIndex / 8;
                int x = squareIndex - y * 8;

                int north = 7 - y;
                int south = y;
                int west  = x;
                int east  = 7 - x;
                numSquaresToEdge[squareIndex]    = new int[8];
                numSquaresToEdge[squareIndex][0] = north;
                numSquaresToEdge[squareIndex][1] = south;
                numSquaresToEdge[squareIndex][2] = west;
                numSquaresToEdge[squareIndex][3] = east;
                numSquaresToEdge[squareIndex][4] = System.Math.Min(north, west);
                numSquaresToEdge[squareIndex][5] = System.Math.Min(south, east);
                numSquaresToEdge[squareIndex][6] = System.Math.Min(north, east);
                numSquaresToEdge[squareIndex][7] = System.Math.Min(south, west);

                // Wszystkie pole na które moe skoczyć skoczek z danego pola
                var   legalKnightJumps = new List <byte> ();
                ulong knightBitboard   = 0;
                foreach (int knightJumpDelta in allKnightJumps)
                {
                    int knightJumpSquare = squareIndex + knightJumpDelta;
                    if (knightJumpSquare >= 0 && knightJumpSquare < 64)
                    {
                        int knightSquareY = knightJumpSquare / 8;
                        int knightSquareX = knightJumpSquare - knightSquareY * 8;
                        // Zapewnienie, że skoczek pokona co najmniej 2 pola (żeby uniknąć wyjścia poza mape i glitchowania)
                        int maxCoordMoveDst = System.Math.Max(System.Math.Abs(x - knightSquareX), System.Math.Abs(y - knightSquareY));
                        if (maxCoordMoveDst == 2)
                        {
                            legalKnightJumps.Add((byte)knightJumpSquare);
                            knightBitboard |= 1ul << knightJumpSquare;
                        }
                    }
                }
                knightMoves[squareIndex]           = legalKnightJumps.ToArray();
                knightAttackBitboards[squareIndex] = knightBitboard;

                // To co wyżej tylko dla króla (nie wliczając roszady)
                var legalKingMoves = new List <byte> ();
                foreach (int kingMoveDelta in directionOffsets)
                {
                    int kingMoveSquare = squareIndex + kingMoveDelta;
                    if (kingMoveSquare >= 0 && kingMoveSquare < 64)
                    {
                        int kingSquareY = kingMoveSquare / 8;
                        int kingSquareX = kingMoveSquare - kingSquareY * 8;
                        // Zapewnienie, że król pokona co najmniej 1 pole (żeby uniknąć wyjścia poza mape i glitchowania)
                        int maxCoordMoveDst = System.Math.Max(System.Math.Abs(x - kingSquareX), System.Math.Abs(y - kingSquareY));
                        if (maxCoordMoveDst == 1)
                        {
                            legalKingMoves.Add((byte)kingMoveSquare);
                            kingAttackBitboards[squareIndex] |= 1ul << kingMoveSquare;
                        }
                    }
                }
                kingMoves[squareIndex] = legalKingMoves.ToArray();

                List <int> pawnCapturesWhite = new List <int> ();
                List <int> pawnCapturesBlack = new List <int> ();
                pawnAttackBitboards[squareIndex] = new ulong[2];
                if (x > 0)
                {
                    if (y < 7)
                    {
                        pawnCapturesWhite.Add(squareIndex + 7);
                        pawnAttackBitboards[squareIndex][Board.WhiteIndex] |= 1ul << (squareIndex + 7);
                    }
                    if (y > 0)
                    {
                        pawnCapturesBlack.Add(squareIndex - 9);
                        pawnAttackBitboards[squareIndex][Board.BlackIndex] |= 1ul << (squareIndex - 9);
                    }
                }
                if (x < 7)
                {
                    if (y < 7)
                    {
                        pawnCapturesWhite.Add(squareIndex + 9);
                        pawnAttackBitboards[squareIndex][Board.WhiteIndex] |= 1ul << (squareIndex + 9);
                    }
                    if (y > 0)
                    {
                        pawnCapturesBlack.Add(squareIndex - 7);
                        pawnAttackBitboards[squareIndex][Board.BlackIndex] |= 1ul << (squareIndex - 7);
                    }
                }
                pawnAttacksWhite[squareIndex] = pawnCapturesWhite.ToArray();
                pawnAttacksBlack[squareIndex] = pawnCapturesBlack.ToArray();

                // Ruch wieży
                for (int directionIndex = 0; directionIndex < 4; directionIndex++)
                {
                    int currentDirOffset = directionOffsets[directionIndex];
                    for (int n = 0; n < numSquaresToEdge[squareIndex][directionIndex]; n++)
                    {
                        int targetSquare = squareIndex + currentDirOffset * (n + 1);
                        rookMoves[squareIndex] |= 1ul << targetSquare;
                    }
                }
                // Ruch gońca
                for (int directionIndex = 4; directionIndex < 8; directionIndex++)
                {
                    int currentDirOffset = directionOffsets[directionIndex];
                    for (int n = 0; n < numSquaresToEdge[squareIndex][directionIndex]; n++)
                    {
                        int targetSquare = squareIndex + currentDirOffset * (n + 1);
                        bishopMoves[squareIndex] |= 1ul << targetSquare;
                    }
                }
                queenMoves[squareIndex] = rookMoves[squareIndex] | bishopMoves[squareIndex];
            }

            directionLookup = new int[127];
            for (int i = 0; i < 127; i++)
            {
                int offset    = i - 63;
                int absOffset = System.Math.Abs(offset);
                int absDir    = 1;
                if (absOffset % 9 == 0)
                {
                    absDir = 9;
                }
                else if (absOffset % 8 == 0)
                {
                    absDir = 8;
                }
                else if (absOffset % 7 == 0)
                {
                    absDir = 7;
                }

                directionLookup[i] = absDir * System.Math.Sign(offset);
            }

            // Wyszukiwanie dystansu
            orthogonalDistance      = new int[64, 64];
            kingDistance            = new int[64, 64];
            centreManhattanDistance = new int[64];
            for (int squareA = 0; squareA < 64; squareA++)
            {
                Coord coordA            = BoardRepresentation.CoordFromIndex(squareA);
                int   fileDstFromCentre = Max(3 - coordA.fileIndex, coordA.fileIndex - 4);
                int   rankDstFromCentre = Max(3 - coordA.rankIndex, coordA.rankIndex - 4);
                centreManhattanDistance[squareA] = fileDstFromCentre + rankDstFromCentre;

                for (int squareB = 0; squareB < 64; squareB++)
                {
                    Coord coordB       = BoardRepresentation.CoordFromIndex(squareB);
                    int   rankDistance = Abs(coordA.rankIndex - coordB.rankIndex);
                    int   fileDistance = Abs(coordA.fileIndex - coordB.fileIndex);
                    orthogonalDistance[squareA, squareB] = fileDistance + rankDistance;
                    kingDistance[squareA, squareB]       = Max(fileDistance, rankDistance);
                }
            }
        }
Esempio n. 2
0
        static Move MoveFromAlgebraic(Board board, string algebraicMove)
        {
            MoveGenerator moveGenerator = new MoveGenerator();

            // Remove unrequired info from move string
            algebraicMove = algebraicMove.Replace("+", "").Replace("#", "").Replace("x", "").Replace("-", "");
            var allMoves = moveGenerator.GenerateMoves(board);

            Move move = new Move();

            foreach (Move moveToTest in allMoves)
            {
                move = moveToTest;

                int   moveFromIndex = move.StartSquare;
                int   moveToIndex   = move.TargetSquare;
                int   movePieceType = Piece.PieceType(board.Square[moveFromIndex]);
                Coord fromCoord     = BoardRepresentation.CoordFromIndex(moveFromIndex);
                Coord toCoord       = BoardRepresentation.CoordFromIndex(moveToIndex);
                if (algebraicMove == "OO")                   // castle kingside
                {
                    if (movePieceType == Piece.King && moveToIndex - moveFromIndex == 2)
                    {
                        return(move);
                    }
                }
                else if (algebraicMove == "OOO")                     // castle queenside
                {
                    if (movePieceType == Piece.King && moveToIndex - moveFromIndex == -2)
                    {
                        return(move);
                    }
                }
                // Is pawn move if starts with any file indicator (e.g. 'e'4. Note that uppercase B is used for bishops)
                else if (fileNames.Contains(algebraicMove[0].ToString()))
                {
                    if (movePieceType != Piece.Pawn)
                    {
                        continue;
                    }
                    if (fileNames.IndexOf(algebraicMove[0]) == fromCoord.fileIndex) // correct starting file
                    {
                        if (algebraicMove.Contains("="))                            // is promotion
                        {
                            if (toCoord.rankIndex == 0 || toCoord.rankIndex == 7)
                            {
                                if (algebraicMove.Length == 5)                                 // pawn is capturing to promote
                                {
                                    char targetFile = algebraicMove[1];
                                    if (BoardRepresentation.fileNames.IndexOf(targetFile) != toCoord.fileIndex)
                                    {
                                        // Skip if not moving to correct file
                                        continue;
                                    }
                                }
                                char promotionChar = algebraicMove[algebraicMove.Length - 1];

                                if (move.PromotionPieceType != GetPieceTypeFromSymbol(promotionChar))
                                {
                                    continue;                                     // skip this move, incorrect promotion type
                                }

                                return(move);
                            }
                        }
                        else
                        {
                            char targetFile = algebraicMove[algebraicMove.Length - 2];
                            char targetRank = algebraicMove[algebraicMove.Length - 1];

                            if (BoardRepresentation.fileNames.IndexOf(targetFile) == toCoord.fileIndex)                              // correct ending file
                            {
                                if (targetRank.ToString() == (toCoord.rankIndex + 1).ToString())                                     // correct ending rank
                                {
                                    break;
                                }
                            }
                        }
                    }
                }
                else                     // regular piece move

                {
                    char movePieceChar = algebraicMove[0];
                    if (GetPieceTypeFromSymbol(movePieceChar) != movePieceType)
                    {
                        continue;                         // skip this move, incorrect move piece type
                    }

                    char targetFile = algebraicMove[algebraicMove.Length - 2];
                    char targetRank = algebraicMove[algebraicMove.Length - 1];
                    if (BoardRepresentation.fileNames.IndexOf(targetFile) == toCoord.fileIndex)                      // correct ending file
                    {
                        if (targetRank.ToString() == (toCoord.rankIndex + 1).ToString())                             // correct ending rank

                        {
                            if (algebraicMove.Length == 4)                               // addition char present for disambiguation (e.g. Nbd7 or R7e2)
                            {
                                char disambiguationChar = algebraicMove[1];

                                if (BoardRepresentation.fileNames.Contains(disambiguationChar.ToString()))                                     // is file disambiguation
                                {
                                    if (BoardRepresentation.fileNames.IndexOf(disambiguationChar) != fromCoord.fileIndex)                      // incorrect starting file
                                    {
                                        continue;
                                    }
                                }
                                else                                                                           // is rank disambiguation
                                {
                                    if (disambiguationChar.ToString() != (fromCoord.rankIndex + 1).ToString()) // incorrect starting rank
                                    {
                                        continue;
                                    }
                                }
                            }
                            break;
                        }
                    }
                }
            }
            return(move);
        }