Beispiel #1
0
 public ChessMove(Square fromSq, Square toSq, Piece promotedTo)
 {
     this.fromSq = fromSq;
     this.toSq = toSq;
     this.special = SpecialMoveType.Promotion;
     this.promotedTo = promotedTo;
 }
Beispiel #2
0
 public ToMoveData(PieceColour colour, Piece pawn, Piece knight, Piece bishop, Piece rook, Piece queen, Piece king, int pawnStartRank, int pawnPromRank, int pawnYDir,
     CastleFlags canCastleKS, CastleFlags canCastleQS, Square kingStartSq, Square kingRookSq, Square queenRookSq)
 {
     Colour = colour;
     Pawn = pawn;
     Knight = knight;
     Bishop = bishop;
     Rook = rook;
     Queen = queen;
     King = king;
     PawnStartRank = pawnStartRank;
     PawnPromRank = pawnPromRank;
     PawnYDir = pawnYDir;
     CanCastleKS = canCastleKS;
     CanCastleQS = canCastleQS;
     KingStartSq = kingStartSq;
     KingRookSq = kingRookSq;
     QueenRookSq = queenRookSq;
     KingKCastleSq = new Square(kingStartSq.File + 2, kingStartSq.Rank);
     KingQCastleSq = new Square(kingStartSq.File - 2, kingStartSq.Rank);
     RookKCastleSq = new Square(kingStartSq.File + 1, kingStartSq.Rank);
     RookQCastleSq = new Square(kingStartSq.File - 1, kingStartSq.Rank);
 }
Beispiel #3
0
 public SquareInfo(Piece piece, Square location)
 {
     this.piece = piece;
     this.location = location;
 }
Beispiel #4
0
 /// <summary>
 /// Moves the piece on the current square to the specified square.
 /// </summary>
 /// <param name="t">The location.</param>
 /// <returns>Whether or not the move was successful.</returns>
 public bool To(Square t)
 {
     return this.Board.Move(this, t);
 }
Beispiel #5
0
 void undoMove()
 {
     ToMove = toMove == PieceColour.White ? PieceColour.Black : PieceColour.White;   // Make ToMove the side of the move being undone
     ChessMove lastMove = undoStack.Pop();
     HalfMovesSinceLastPawnMoveOrCapture = lastMove.HalfMovesSinceLastPawnMoveOrCapture;
     SquareInfo capturedSqInfo = lastMove.CapturedSqInfo;
     Square from = lastMove.FromSq;
     Square to = lastMove.ToSq;
     EpSquare = lastMove.OldEpSq;
     CastleFlags = lastMove.OldCastleFlags;
     HashKey = lastMove.OldHashKey;
     Board[from] = Board[to];
     Board[from].Location = from;
     switch (lastMove.Special)
     {
         case SpecialMoveType.Promotion:
             Board[from].Piece = thisSide.Pawn;
             break;
         case SpecialMoveType.EnPassant:
             Board[to] = emptyBoard[to];
             to.Rank -= thisSide.PawnYDir;
             break;
         case SpecialMoveType.CastleKS:
             // Move the rook back
             from = thisSide.KingRookSq;
             Square cto = thisSide.RookKCastleSq;
             Board[from] = Board[cto];
             Board[cto] = emptyBoard[cto];
             Board[from].Location = from;
             break;
         case SpecialMoveType.CastleQS:
             from = thisSide.QueenRookSq;
             cto = thisSide.RookQCastleSq;
             Board[from] = Board[cto];
             Board[cto] = emptyBoard[cto];
             Board[from].Location = from;
             break;
     }
     // Have to do this bit last because case SpecialMoveType.EnPassant changes the to square
     Board[to] = capturedSqInfo;
     if (capturedSqInfo.Piece != Pieces.None)
     {
         // Link in the restored capturedSqInfo
         capturedSqInfo.Prev.Next = capturedSqInfo;
         capturedSqInfo.Next.Prev = capturedSqInfo;
     }
 }
Beispiel #6
0
 void makeMove(ChessMove move)
 {
     Square from = move.FromSq;
     Square to = move.ToSq;
     SquareInfo CapturedSqInfo = Board[to];
     Board[to] = Board[from];                    // Move the piece
     Board[from] = emptyBoard[from];             // Replace from SquareInfo with the empty SquareInfo from emptyBoard
     Board[to].Location = to;                    // Update SqInfo location
     move.OldHashKey = HashKey;
     move.OldEpSq = EpSquare;
     EpSquare = new Square(0, 0);
     move.OldCastleFlags = CastleFlags;
     HashKey ^= pieceKeys[move.Piece.ToInt(), from] ^ pieceKeys[move.Piece.ToInt(), to];
     bool pawnMoveOrCapture = false;
     switch (move.Special)
     {
         case SpecialMoveType.PawnMove:
             pawnMoveOrCapture = true;
             break;
         case SpecialMoveType.DoublePawnMove:
             EpSquare = new Square(from.File, from.Rank + thisSide.PawnYDir);
             pawnMoveOrCapture = true;
             break;
         case SpecialMoveType.Promotion:
             Board[to].Piece = move.PromotedTo;
             pawnMoveOrCapture = true;
             HashKey ^= pieceKeys[move.Piece.ToInt(), to] ^ pieceKeys[move.PromotedTo.ToInt(), to];
             break;
         case SpecialMoveType.EnPassant:
             // After the piece has been moved make to = the square of the captured ep pawn
             to.Rank -= thisSide.PawnYDir;
             CapturedSqInfo = Board[to];                 // CapturedSqInfo is the enemy pawn not the square moved into
             Board[to] = emptyBoard[to];
             break;
         case SpecialMoveType.CastleKS:
             // Move the rook
             to = thisSide.RookKCastleSq;
             from = thisSide.KingRookSq;
             Board[to] = Board[from];                    // Move the piece
             Board[from] = emptyBoard[from];             // Replace from SquareInfo with the empty SquareInfo from emptyBoard
             Board[to].Location = to;                    // Update SqInfo location
             HashKey ^= pieceKeys[Board[to].Piece.ToInt(), from] ^ pieceKeys[Board[to].Piece.ToInt(), to];
             break;
         case SpecialMoveType.CastleQS:
             to = thisSide.RookQCastleSq;
             from = thisSide.QueenRookSq;
             Board[to] = Board[from];                    // Move the piece
             Board[from] = emptyBoard[from];             // Replace from SquareInfo with the empty SquareInfo from emptyBoard
             Board[to].Location = to;                    // Update SqInfo location
             HashKey ^= pieceKeys[Board[to].Piece.ToInt(), from] ^ pieceKeys[Board[to].Piece.ToInt(), to];
             break;
     }
     if (CapturedSqInfo.Piece.PieceColour != PieceColour.None)
     {
         CapturedSqInfo.Prev.Next = CapturedSqInfo.Next;                      // Delink the captured piece
         CapturedSqInfo.Next.Prev = CapturedSqInfo.Prev;
         pawnMoveOrCapture = true;
         // Clear enemy castling rights when capturing one of their rooks on its starting square
         if (to == otherSide.KingRookSq)
             CastleFlags = CastleFlags & ~(otherSide.CanCastleKS);
         if (to == otherSide.QueenRookSq)
             CastleFlags = CastleFlags & ~(otherSide.CanCastleQS);
         HashKey ^= pieceKeys[CapturedSqInfo.Piece.ToInt(), to];
     }
     // Clear castle flag if king or rooks have moved
     if (Board[thisSide.KingStartSq].Piece == thisSide.King)
     {
         if (Board[thisSide.KingRookSq].Piece != thisSide.Rook)
             CastleFlags = CastleFlags & ~thisSide.CanCastleKS;
         if (Board[thisSide.QueenRookSq].Piece != thisSide.Rook)
             CastleFlags = CastleFlags & ~thisSide.CanCastleQS;
     }
     else
         CastleFlags = CastleFlags & ~(thisSide.CanCastleKS | thisSide.CanCastleQS);
     ToMove = toMove == PieceColour.White ? PieceColour.Black : PieceColour.White;
     HashKey ^= castleKeys[(int)move.OldCastleFlags] ^ castleKeys[(int)CastleFlags] ^ sideKey;
     move.CapturedSqInfo = CapturedSqInfo;
     move.HalfMovesSinceLastPawnMoveOrCapture = HalfMovesSinceLastPawnMoveOrCapture;
     undoStack.Push(move);
     if (pawnMoveOrCapture)
         HalfMovesSinceLastPawnMoveOrCapture = 0;
     else
         HalfMovesSinceLastPawnMoveOrCapture++;
     return;
 }
Beispiel #7
0
 bool isSquareAttacked(Square sq, ToMoveData enemySide)
 {
     int file = sq.File;
     int rank = sq.Rank;
     Piece enemyKnight = enemySide.Knight;
     if (checkForEnemyKnightAt(file + 1, rank + 2, enemyKnight) || checkForEnemyKnightAt(file + 2, rank + 1, enemyKnight) || checkForEnemyKnightAt(file + 2, rank - 1, enemyKnight) || checkForEnemyKnightAt(file + 1, rank - 2, enemyKnight)
         || checkForEnemyKnightAt(file - 1, rank - 2, enemyKnight) || checkForEnemyKnightAt(file - 2, rank - 1, enemyKnight) || checkForEnemyKnightAt(file - 2, rank + 1, enemyKnight) || checkForEnemyKnightAt(file - 1, rank + 2, enemyKnight))
         return true;
     Piece enemyPawn = enemySide.Pawn;
     if (checkForEnemyPawnAt(file - 1, rank - enemySide.PawnYDir, enemyPawn) || checkForEnemyPawnAt(file + 1, rank - enemySide.PawnYDir, enemyPawn))
         return true;
     Piece enemyBishop = enemySide.Bishop;
     Piece enemyRook = enemySide.Rook;
     Piece enemyQueen = enemySide.Queen;
     if ((checkForSlidingAttacksFrom(file, rank, 1, 1, enemyBishop, enemyQueen)) || (checkForSlidingAttacksFrom(file, rank, 1, -1, enemyBishop, enemyQueen))
         || (checkForSlidingAttacksFrom(file, rank, -1, -1, enemyBishop, enemyQueen)) || (checkForSlidingAttacksFrom(file, rank, -1, 1, enemyBishop, enemyQueen))
         || (checkForSlidingAttacksFrom(file, rank, 0, 1, enemyRook, enemyQueen)) || (checkForSlidingAttacksFrom(file, rank, 1, 0, enemyRook, enemyQueen))
         || (checkForSlidingAttacksFrom(file, rank, 0, -1, enemyRook, enemyQueen)) || (checkForSlidingAttacksFrom(file, rank, -1, 0, enemyRook, enemyQueen)))
         return true;
     Square enemyKingSq = enemySide.KingSqInfo.Location;
     int fileDiff = file - enemyKingSq.File;
     int rankDiff = rank - enemyKingSq.Rank;
     if (fileDiff >= -1 && fileDiff <= 1 && rankDiff >= -1 && rankDiff <= 1)
         return true;
     return false;
 }
Beispiel #8
0
 void addSlidingMoves(Square from, int xDir, int yDir)
 {
     PieceColour captureColour = PieceColour.None;
     Square to = new Square(from.File + xDir, from.Rank + yDir);
     while (to.File >= 0 && to.File <= 7 && to.Rank >= 0 && to.Rank <= 7 && (captureColour = Board[to].Piece.PieceColour) == PieceColour.None)
     {
         addQuietMove(new ChessMove(from, to));
         to.File += xDir; to.Rank += yDir;              // Value type so no need to new another one
     }
     if (captureColour == otherSide.Colour)
     {
         // If Capture
         addCaptureMove(new ChessMove(from, to));
     }
 }
Beispiel #9
0
 void addKingMove(Square from, int xDir, int yDir)
 {
     PieceColour captureColour = PieceColour.None;
     Square to = new Square(from.File + xDir, from.Rank + yDir);
     if (to.File >= 0 && to.File <= 7 && to.Rank >= 0 && to.Rank <= 7 && (captureColour = Board[to].Piece.PieceColour) != toMove)
     {
         // if to is on the board and doesn't contain a piece of the side to move
         if (captureColour != otherSide.Colour)
             addQuietMove(new ChessMove(from, to));
         else
             addCaptureMove(new ChessMove(from, to));
     }
 }
Beispiel #10
0
 void addEnPassantMove(int xDir)
 {
     // xDir = X direction of the capture to the EpSq
     Square from = new Square(EpSquare.File - xDir, EpSquare.Rank - thisSide.PawnYDir);
     if (from.File >= 0 && from.File <= 7 && Board[from].Piece == thisSide.Pawn)
         addCaptureMove(new ChessMove(from, EpSquare, SpecialMoveType.EnPassant));
 }
Beispiel #11
0
 void addPawnCapture(Square from, int xDir)
 {
     Square to = new Square(from.File + xDir, from.Rank + thisSide.PawnYDir);
     if (to.File >= 0 && to.File <= 7 && Board[to].Piece.PieceColour == otherSide.Colour)
     {
         if (to.Rank == thisSide.PawnPromRank)
         {
             addCaptureMove(new ChessMove(from, to, thisSide.Queen));
             addCaptureMove(new ChessMove(from, to, thisSide.Rook));
             addCaptureMove(new ChessMove(from, to, thisSide.Bishop));
             addCaptureMove(new ChessMove(from, to, thisSide.Knight));
         }
         else
             addCaptureMove(new ChessMove(from, to));
     }
 }
Beispiel #12
0
 public ChessPosition()
 {
     initChessEval();
     Board = new SquareInfo[64];
     emptyBoard = new SquareInfo[64];
     Princ = new ChessMove[maxDepth, maxDepth];
     killers = new ChessMove[2, 1000];
     mvvLva = new int[8, 8];
     searchHistory = new int[16, 64];
     // Init the mvvLva array
     for (int v = 0; v <= 6; v++)
         for (int a = 0; a <= 6; a++)
             mvvLva[v, a] = v * 100 +6 - a;
     // Init the killers array
     for (int i = 0; i < 1000; i++)
     {
         killers[0, i] = new ChessMove(new Square(99, 99), new Square(99, 99));
         killers[1, i] = new ChessMove(new Square(99, 99), new Square(99, 99));
     }
     // Init the emptyBoard and Board arrays
     for (int i = 0; i <= 63; i++)
     {
         emptyBoard[i] = new SquareInfo(Pieces.None, new Square(i));
         Board[i] = emptyBoard[i];
     }
     // Init the hashKeys
     Random rng = new Random();
     pieceKeys = new UInt64[16, 64];
     for (int p = 0; p <= 15; p++)
         for (int sq = 0; sq <= 63; sq++)
             pieceKeys[p, sq] = (UInt64)rng.Next() + ((UInt64)rng.Next() << 15) + ((UInt64)rng.Next() << 30) + ((UInt64)rng.Next() << 45) + ((UInt64)rng.Next() << 60);
     castleKeys = new UInt64[16];
     for (int i = 0; i <= 15; i++)
         castleKeys[i] = (UInt64)rng.Next() + ((UInt64)rng.Next() << 15) + ((UInt64)rng.Next() << 30) + ((UInt64)rng.Next() << 45) + ((UInt64)rng.Next() << 60);
     sideKey = (UInt64)rng.Next() + ((UInt64)rng.Next() << 15) + ((UInt64)rng.Next() << 30) + ((UInt64)rng.Next() << 45) + ((UInt64)rng.Next() << 60);
     // Init the pvTable
     pvTable = new Dictionary<ulong, int>();
     EpSquare = new Square(0, 0);
     white = new ToMoveData(PieceColour.White, new Piece(PieceType.Pawn, PieceColour.White), new Piece(PieceType.Knight, PieceColour.White),
         new Piece(PieceType.Bishop, PieceColour.White), new Piece(PieceType.Rook, PieceColour.White), new Piece(PieceType.Queen, PieceColour.White),
         new Piece(PieceType.King, PieceColour.White), 1, 7, 1, CastleFlags.Wks, CastleFlags.Wqs, new Square("e1"), new Square("h1"), new Square("a1"));
     black = new ToMoveData(PieceColour.Black, new Piece(PieceType.Pawn, PieceColour.Black), new Piece(PieceType.Knight, PieceColour.Black),
         new Piece(PieceType.Bishop, PieceColour.Black), new Piece(PieceType.Rook, PieceColour.Black), new Piece(PieceType.Queen, PieceColour.Black),
         new Piece(PieceType.King, PieceColour.Black), 6, 0, -1, CastleFlags.Bks, CastleFlags.Bqs, new Square("e8"), new Square("h8"), new Square("a8"));
     PossibleMoves = new Collection<ChessMove>();
     MoveHistory = new Collection<ChessMove>();
     undoStack = new Stack<ChessMove>();
     NewGame();
 }
Beispiel #13
0
 void addPawnMove(Square from)
 {
     Square to = new Square(from.File, from.Rank + thisSide.PawnYDir);
     if (Board[to].Piece.PieceType == PieceType.None)
     {
         if (to.Rank == thisSide.PawnPromRank)
         {
             addQuietMove(new ChessMove(from, to, thisSide.Queen));
             addQuietMove(new ChessMove(from, to, thisSide.Rook));
             addQuietMove(new ChessMove(from, to, thisSide.Bishop));
             addQuietMove(new ChessMove(from, to, thisSide.Knight));
         }
         else
         {
             addQuietMove(new ChessMove(from, to, SpecialMoveType.PawnMove));
             if (from.Rank == thisSide.PawnStartRank)                   // Check for double pawn move
             {
                 to.Rank += thisSide.PawnYDir;
                 if (Board[to].Piece.PieceType == PieceType.None)
                 {
                     addQuietMove(new ChessMove(from, to, SpecialMoveType.DoublePawnMove));
                 }
             }
         }
     }
 }
Beispiel #14
0
 public bool Initialise(string strFen)
 {
     // returns false if position is illegal
     // No validation checks yet
     for (int i = 0; i <= 63; i++)
         Board[i] = emptyBoard[i];
     MoveHistory.Clear();
     undoStack.Clear();
     Square sq = new Square("a8");
     int p = 0;  // Position within the FEN string
     char c;
     while (p < strFen.Length && (c = strFen[p++]) != ' ')
     {
         if (c >= '1' && c <= '8')
         {
             sq.File += c - '0';
         }
         int i = pieceStr.IndexOf(Char.ToUpper(c));
         if (i >= 1)
         {
             // Replace the empty SquareInfos with new ones for the pieces
             // The original empty SquareInfos are in emptyBoard
             Board[sq] = new SquareInfo(new Piece((PieceType)i, c < 'a' ? PieceColour.White : PieceColour.Black), sq);
             sq.File++;
         }
         if (c == '/')
         {
             sq.Rank--;
             sq.File = 0;
         }
     }
     c = strFen[p++];
     if (c == 'b')
     {
         ToMove = PieceColour.Black;
     }
     else
     {
         ToMove = PieceColour.White;
     }
     CastleFlags = 0;
     p++;
     while (p < strFen.Length && (c = strFen[p++]) != ' ')
     {
         switch (c)
         {
             case 'K': CastleFlags |= CastleFlags.Wks; break;
             case 'Q': CastleFlags |= CastleFlags.Wqs; break;
             case 'k': CastleFlags |= CastleFlags.Bks; break;
             case 'q': CastleFlags |= CastleFlags.Bqs; break;
         }
     }
     c = strFen[p++];
     if (c == '-')
         EpSquare = new Square(0, 0);
     else
     {
         char d = strFen[p++];
         EpSquare = new Square(c - 'a', d - '1');
     }
     StringBuilder n = new StringBuilder();
     p++;
     while (p < strFen.Length && (c = strFen[p++]) != ' ')
         n.Append(c);
     HalfMovesSinceLastPawnMoveOrCapture = int.Parse(n.ToString());
     n.Clear();
     while (p < strFen.Length && (c = strFen[p++]) != ' ')
         n.Append(c);
     GameStartPlyNr = (int.Parse(n.ToString()) - 1) * 2 + (ToMove == PieceColour.Black ? 1 : 0);
     initializePieceLists();
     generatePossibleMoves(PossibleMoves);
     removeIllegalMoves(PossibleMoves);
     return true;
 }
Beispiel #15
0
 public ChessMove(Square fromSq, Square toSq, SpecialMoveType special)
 {
     this.fromSq = fromSq;
     this.toSq = toSq;
     this.special = special;
 }
Beispiel #16
0
 public ChessMove(Square fromSq, Square toSq)
 {
     this.fromSq = fromSq;
     this.toSq = toSq;
     this.special = SpecialMoveType.Nothing;
 }