Fix bugs with en passant
This commit is contained in:
parent
54a6217bd3
commit
f75f7533f5
|
@ -133,12 +133,15 @@ proc doMove(self: ChessBoard, move: Move)
|
|||
proc pretty*(self: ChessBoard): string
|
||||
proc spawnPiece(self: ChessBoard, location: Location, piece: Piece)
|
||||
proc updateAttackedSquares(self: ChessBoard)
|
||||
proc updateSlidingAttacks(self: ChessBoard)
|
||||
proc getPinnedDirections(self: ChessBoard, loc: Location): seq[Location]
|
||||
proc getAttacks*(self: ChessBoard, loc: Location): Attacked
|
||||
proc getSlidingAttacks(self: ChessBoard, loc: Location): tuple[attacks: Attacked, pins: Attacked]
|
||||
proc inCheck*(self: ChessBoard, color: PieceColor = None): bool
|
||||
proc toFEN*(self: ChessBoard): string
|
||||
proc undoLastMove*(self: ChessBoard)
|
||||
proc movePiece(self: ChessBoard, move: Move, attack: bool = true)
|
||||
proc removePiece(self: ChessBoard, location: Location, attack: bool = true)
|
||||
|
||||
|
||||
proc extend[T](self: var seq[T], other: openarray[T]) {.inline.} =
|
||||
|
@ -847,27 +850,21 @@ proc generatePawnMoves(self: ChessBoard, location: Location): seq[Move] =
|
|||
if target.isValid():
|
||||
let otherPiece = self.grid[target]
|
||||
if target == self.position.enPassantSquare and self.grid[enPassantPawn].color == piece.color.opposite():
|
||||
# Ensure en passant doesn't create a check
|
||||
let king = self.getKing(piece.color)
|
||||
var ok = true
|
||||
if king.row == location.row:
|
||||
var current = location
|
||||
while true:
|
||||
current = current + piece.color.rightSide()
|
||||
if not current.isValid():
|
||||
break
|
||||
let p = self.grid[current.row, current.col]
|
||||
if p.color == piece.color:
|
||||
break
|
||||
if p.color == None:
|
||||
continue
|
||||
# Bishops can't create checks through en passant (neither can knights)
|
||||
if p.color == piece.color.opposite() and p.kind in [Queen, Rook]:
|
||||
ok = false
|
||||
break
|
||||
if ok:
|
||||
# En passant may be possible
|
||||
let targetPawn = self.grid[enPassantPawn]
|
||||
# Remove both pieces and see if the king ends up in check
|
||||
self.removePiece(enPassantPawn, attack=false)
|
||||
self.removePiece(location, attack=false)
|
||||
self.updateAttackedSquares()
|
||||
if not self.inCheck(piece.color):
|
||||
# King is not in check after en passant: move is legal
|
||||
directions.add(diagonal)
|
||||
# Reset what we just did and reupdate the attack metadata
|
||||
self.spawnPiece(location, piece)
|
||||
self.spawnPiece(enPassantPawn, targetPawn)
|
||||
self.updateAttackedSquares()
|
||||
elif otherPiece.color == piece.color.opposite() and otherPiece.kind != King: # Can't capture the king!
|
||||
# A capture may be possible
|
||||
directions.add(diagonal)
|
||||
# Check for pins
|
||||
let pinned = self.getPinnedDirections(location)
|
||||
|
@ -924,8 +921,9 @@ proc generateSlidingMoves(self: ChessBoard, location: Location): seq[Move] =
|
|||
if direction in pinned:
|
||||
newDirections.add(direction)
|
||||
directions = newDirections
|
||||
let checked = self.inCheck()
|
||||
let resolutions = if not checked: @[] else: self.getCheckResolutions(piece.color)
|
||||
let
|
||||
checked = self.inCheck()
|
||||
resolutions = if not checked: @[] else: self.getCheckResolutions(piece.color)
|
||||
for direction in directions:
|
||||
# Slide in this direction as long as it's possible
|
||||
var
|
||||
|
@ -1333,9 +1331,10 @@ proc updateSlidingAttacks(self: ChessBoard) =
|
|||
proc updateAttackedSquares(self: ChessBoard) =
|
||||
## Updates internal metadata about which squares
|
||||
## are attacked
|
||||
|
||||
self.position.attacked.white.setLen(0)
|
||||
self.position.attacked.black.setLen(0)
|
||||
self.position.pinned.white.setLen(0)
|
||||
self.position.pinned.black.setLen(0)
|
||||
# Pawns
|
||||
self.updatePawnAttacks()
|
||||
# Sliding pieces
|
||||
|
@ -1687,8 +1686,6 @@ proc undoLastMove*(self: ChessBoard) =
|
|||
|
||||
proc isLegal(self: ChessBoard, move: Move): bool {.inline.} =
|
||||
## Returns whether the given move is legal
|
||||
if self.grid[move.startSquare.row, move.startSquare.col].color != self.getActiveColor():
|
||||
return false
|
||||
return move in self.generateMoves(move.startSquare)
|
||||
|
||||
|
||||
|
@ -2047,6 +2044,8 @@ proc handleMoveCommand(board: ChessBoard, command: seq[string]): Move {.discarda
|
|||
move.flags = move.flags or CastleLong.uint16
|
||||
elif move.targetSquare == move.startSquare + shortCastleKing():
|
||||
move.flags = move.flags or CastleShort.uint16
|
||||
if move.targetSquare == board.getEnPassantTarget():
|
||||
move.flags = move.flags or EnPassant.uint16
|
||||
result = board.makeMove(move)
|
||||
if result == emptyMove():
|
||||
echo &"Error: move: {moveString} is illegal"
|
||||
|
@ -2095,7 +2094,7 @@ proc handlePositionCommand(board: var ChessBoard, command: seq[string]) =
|
|||
try:
|
||||
tempBoard = newChessboardFromFEN(fenString)
|
||||
except ValueError:
|
||||
echo &"Error: position: {getCurrentExceptionMsg()}"
|
||||
echo &"error: position: {getCurrentExceptionMsg()}"
|
||||
return
|
||||
if args.len() > 0:
|
||||
var i = 0
|
||||
|
@ -2113,6 +2112,9 @@ proc handlePositionCommand(board: var ChessBoard, command: seq[string]) =
|
|||
echo board
|
||||
of "pretty":
|
||||
echo board.pretty()
|
||||
else:
|
||||
echo &"error: position: unknown subcommand '{command[1]}'"
|
||||
return
|
||||
|
||||
|
||||
proc handleUCICommand(board: var ChessBoard, command: seq[string]) =
|
||||
|
@ -2154,7 +2156,8 @@ const HELP_TEXT = """Nimfish help menu:
|
|||
- ep: Print the current en passant target
|
||||
- pretty: Shorthand for "position pretty"
|
||||
- print: Shorthand for "position print"
|
||||
- fen: Shorthand for "position fen" (print only!)
|
||||
- fen: Shorthand for "position fen"
|
||||
- pos <args>: Shorthand for "position <args>"
|
||||
- get <square>: Get the piece on the given square
|
||||
- uci: enter UCI mode (WIP)
|
||||
"""
|
||||
|
@ -2189,7 +2192,7 @@ proc main: int =
|
|||
echo HELP_TEXT
|
||||
of "go":
|
||||
handleGoCommand(board, cmd)
|
||||
of "position":
|
||||
of "position", "pos":
|
||||
handlePositionCommand(board, cmd)
|
||||
of "move":
|
||||
handleMoveCommand(board, cmd)
|
||||
|
|
Loading…
Reference in New Issue