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); } } }
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); }