public void UndoMove(uint count) { while (History.Count > 0 && count > 0) { var move = History.Peek(); // undo 'global' information Turn = Chess.InverseColor(move.Color); Castling = move.Castling; EnPassantCoord = move.EnPassantCoord; HalfMove = move.HalfMove; Move = move.Move; MovePiece(move.To, move.From); var flags = move.Flags; if (flags.HasFlag(ChessMoveFlag.Promotion)) { var piece = AddPiece(Turn, ChessPieceType.Pawn, move.To); piece.Guid = move.Guid; } if (flags.HasFlag(ChessMoveFlag.Capture)) { var piece = AddPiece(Turn, move.Captured, move.To); piece.Guid = move.CapturedGuid; } if (flags.HasFlag(ChessMoveFlag.EnPassantCapture)) { var enPassantFrom = new ChessPieceCoord(move.To); enPassantFrom.MoveOffset(0, move.Color == ChessColor.Black ? 1 : -1); var piece = AddPiece(Turn, ChessPieceType.Pawn, enPassantFrom); piece.Guid = move.CapturedGuid; } if ((flags & (ChessMoveFlag.KingSideCastle | ChessMoveFlag.QueenSideCastle)) != 0) { var castlingTo = new ChessPieceCoord(move.To); var castlingFrom = new ChessPieceCoord(castlingTo); if (flags.HasFlag(ChessMoveFlag.KingSideCastle)) { castlingTo.MoveOffset(1, 0); castlingFrom.MoveOffset(-1, 0); } if (flags.HasFlag(ChessMoveFlag.QueenSideCastle)) { castlingTo.MoveOffset(-2, 0); castlingFrom.MoveOffset(1, 0); } MovePiece(castlingTo, castlingFrom); } History.Pop(); count--; } }
public void BuildMove(List <ChessMove> storage, ChessMoveFlag result, ChessColor color, ChessPieceType type, ChessPieceCoord from, ChessPieceCoord to) { var fromPiece = GetPiece(from); var toPiece = GetPiece(to); // AC's Chess implementation doesn't support underpromotion var promotion = ChessPieceType.Empty; if (fromPiece.Type == ChessPieceType.Pawn && (to.Rank == 1 || to.Rank == 8)) { promotion = ChessPieceType.Queen; result |= ChessMoveFlag.Promotion; } var captured = ChessPieceType.Empty; if (toPiece != null) { captured = toPiece.Type; } else if (result.HasFlag(ChessMoveFlag.EnPassantCapture)) { captured = ChessPieceType.Pawn; var enPassantCoord = new ChessPieceCoord(to); enPassantCoord.MoveOffset(0, color == ChessColor.Black ? 1 : -1); toPiece = GetPiece(enPassantCoord); } storage.Add(new ChessMove(result, color, type, from, to, promotion, captured, Move, HalfMove, Castling, EnPassantCoord, fromPiece.Guid, captured != ChessPieceType.Empty ? toPiece.Guid : new ObjectGuid(0))); }
public bool CanAttack(ChessColor attacker, ChessPieceCoord victim) { for (uint x = 0; x < Chess.BoardSize; x++) { for (uint y = 0; y < Chess.BoardSize; y++) { var piece = Board[x + y * Chess.BoardSize]; if (piece == null) { continue; } if (piece.Color != attacker) { continue; } if (piece.CanAttack(victim)) { // the knight can jump over other pieces and the pawn can only attack a single space if (piece.Type == ChessPieceType.Knight || piece.Type == ChessPieceType.Pawn) { return(true); } var range = Chess.PieceOffsets[piece.Type]; for (var i = 0; i < range.Count; i++) { var from = piece.Coord; var to = new ChessPieceCoord(from); while (true) { to.MoveOffset(range[i]); if (!to.IsValid()) { break; } var toPiece = GetPiece(to); if (toPiece != null) { if (to.Equals(victim)) { return(true); } break; } } } } } } return(false); }
public void FinalizeWeenieMove(ChessMoveResult result) { var move = Logic.GetLastMove(); Log.Add(move); // need to use destination coordinate as Logic has already moved the piece var piece = Logic.GetPiece(move.To); if (result.HasFlag(ChessMoveResult.OKMoveToEmptySquare)) { MoveWeeniePiece(piece); var flags = move.Flags; if ((flags & (ChessMoveFlag.KingSideCastle | ChessMoveFlag.QueenSideCastle)) != 0) { var castlingTo = new ChessPieceCoord(move.To); if (flags.HasFlag(ChessMoveFlag.KingSideCastle)) { castlingTo.MoveOffset(-1, 0); } if (flags.HasFlag(ChessMoveFlag.QueenSideCastle)) { castlingTo.MoveOffset(1, 0); } var rookPiece = Logic.GetPiece(castlingTo); Debug.Assert(rookPiece != null); MoveWeeniePiece(rookPiece); } } else if (result.HasFlag(ChessMoveResult.OKMoveToOccupiedSquare)) { AttackWeeniePiece(piece, move.CapturedGuid); } }
public void InternalMove(ChessMove move) { var flags = move.Flags; var to = move.To; var from = move.From; var color = move.Color; var opColor = Chess.InverseColor(color); MovePiece(from, to); if (flags.HasFlag(ChessMoveFlag.EnPassantCapture)) { var enPassantCoord = new ChessPieceCoord(to); enPassantCoord.MoveOffset(0, color == ChessColor.Black ? 1 : -1); RemovePiece(enPassantCoord); } if (flags.HasFlag(ChessMoveFlag.Promotion)) { var pawnPiece = GetPiece(to); var guid = pawnPiece.Guid; RemovePiece(pawnPiece); var queenPiece = AddPiece(color, ChessPieceType.Queen, (uint)to.X, (uint)to.Y); queenPiece.Guid = guid; } if (move.Type == ChessPieceType.King) { // if we castled, move the rook next to our king if ((flags & (ChessMoveFlag.KingSideCastle | ChessMoveFlag.QueenSideCastle)) != 0) { var castlingTo = new ChessPieceCoord(move.To); var castlingFrom = new ChessPieceCoord(castlingTo); if (flags.HasFlag(ChessMoveFlag.KingSideCastle)) { castlingTo.MoveOffset(-1, 0); castlingFrom.MoveOffset(1, 0); } if (flags.HasFlag(ChessMoveFlag.QueenSideCastle)) { castlingTo.MoveOffset(1, 0); castlingFrom.MoveOffset(-2, 0); } MovePiece(castlingFrom, castlingTo); } // turn off castling, our king has moved Castling[(int)color] = ChessMoveFlag.None; } // turn off castling if we have moved one of our rooks if (Castling[(int)color] != ChessMoveFlag.None) { DoCastleCheck(color, from); } // turn off castling if we capture one of the opponent's rooks if (Castling[(int)opColor] != ChessMoveFlag.None) { DoCastleCheck(opColor, from); } if (flags.HasFlag(ChessMoveFlag.BigPawn)) { var enPassantCoord = new ChessPieceCoord(to); //enPassantCoord.MoveOffset(0, color == ChessColor.Black ? 2 : -2); enPassantCoord.MoveOffset(0, color == ChessColor.Black ? 1 : -1); EnPassantCoord = enPassantCoord; } else { EnPassantCoord = null; } History.Push(move); if (color == ChessColor.Black) { Move++; } // reset 50 move rule counter if a pawn is moved or a piece is captured if (move.Type == ChessPieceType.Pawn || (flags & (ChessMoveFlag.Capture | ChessMoveFlag.EnPassantCapture)) != 0) { HalfMove = 0; } else { HalfMove++; } Turn = opColor; }
public void GenerateMoves(BasePiece piece, bool single, List <ChessMove> storage) { var color = piece.Color; if (piece.Type == ChessPieceType.Pawn) { // single var from = new ChessPieceCoord(piece.Coord); var to = new ChessPieceCoord(from); to.MoveOffset(Chess.PawnOffsets[(int)color, 0]); if (GetPiece(to) == null) { BuildMove(storage, ChessMoveFlag.Normal, color, piece.Type, from, to); // second to = new ChessPieceCoord(from); to.MoveOffset(Chess.PawnOffsets[(int)color, 1]); if (GetPiece(to) == null && from.Rank == (color == ChessColor.White ? 2 : 7)) { BuildMove(storage, ChessMoveFlag.BigPawn, color, piece.Type, from, to); } } // capture for (uint i = 2; i < 4; i++) { to = new ChessPieceCoord(from); to.MoveOffset(Chess.PawnOffsets[(int)color, i]); if (!to.IsValid()) { continue; } var toPiece = GetPiece(to); if (toPiece != null && toPiece.Color != color) { BuildMove(storage, ChessMoveFlag.Capture, color, piece.Type, from, to); } else if (to.Equals(EnPassantCoord)) { BuildMove(storage, ChessMoveFlag.EnPassantCapture, color, piece.Type, from, EnPassantCoord); } } } else { var range = Chess.PieceOffsets[piece.Type]; for (var i = 0; i < range.Count; i++) { var from = piece.Coord; var to = new ChessPieceCoord(from); while (true) { to.MoveOffset(range[i]); if (!to.IsValid()) { break; } var toPiece = GetPiece(to); if (toPiece != null) { if (toPiece.Color != color) { BuildMove(storage, ChessMoveFlag.Capture, color, piece.Type, from, to); } break; } BuildMove(storage, ChessMoveFlag.Normal, color, piece.Type, from, to); // Knights and Kings can't move more than once if (piece.Type == ChessPieceType.Knight || piece.Type == ChessPieceType.King) { break; } } } } // only check for castling during full board generation or for a single king if (!single || piece.Type == ChessPieceType.King) { if ((Castling[(int)color] & ChessMoveFlag.KingSideCastle | ChessMoveFlag.QueenSideCastle) != 0) { var king = GetPiece(color, ChessPieceType.King); var kingCoord = king.Coord; var opColor = Chess.InverseColor(color); if ((Castling[(int)color] & ChessMoveFlag.KingSideCastle) != 0) { var castlingToK = new ChessPieceCoord(kingCoord); // destination king castlingToK.MoveOffset(2, 0); var castlingToR = new ChessPieceCoord(kingCoord); // destination rook castlingToR.MoveOffset(1, 0); if (GetPiece(castlingToR) == null && GetPiece(castlingToK) == null && !CanAttack(opColor, kingCoord) && !CanAttack(opColor, castlingToR) && !CanAttack(opColor, castlingToK)) { BuildMove(storage, ChessMoveFlag.KingSideCastle, color, ChessPieceType.King, kingCoord, castlingToK); } } if ((Castling[(int)color] & ChessMoveFlag.QueenSideCastle) != 0) { var castlingToK = new ChessPieceCoord(kingCoord); // destination king castlingToK.MoveOffset(-2, 0); var castlingToR = new ChessPieceCoord(kingCoord); // destination rook castlingToR.MoveOffset(-1, 0); var castlingToI = new ChessPieceCoord(kingCoord); // intermediate castlingToI.MoveOffset(-3, 0); if (GetPiece(castlingToR) == null && GetPiece(castlingToK) == null && GetPiece(castlingToI) == null && !CanAttack(opColor, kingCoord) && !CanAttack(opColor, castlingToR) && !CanAttack(opColor, castlingToK)) { BuildMove(storage, ChessMoveFlag.QueenSideCastle, color, ChessPieceType.King, kingCoord, castlingToK); } } } } }