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 pretty*(self: ChessBoard): string
|
||||||
proc spawnPiece(self: ChessBoard, location: Location, piece: Piece)
|
proc spawnPiece(self: ChessBoard, location: Location, piece: Piece)
|
||||||
proc updateAttackedSquares(self: ChessBoard)
|
proc updateAttackedSquares(self: ChessBoard)
|
||||||
|
proc updateSlidingAttacks(self: ChessBoard)
|
||||||
proc getPinnedDirections(self: ChessBoard, loc: Location): seq[Location]
|
proc getPinnedDirections(self: ChessBoard, loc: Location): seq[Location]
|
||||||
proc getAttacks*(self: ChessBoard, loc: Location): Attacked
|
proc getAttacks*(self: ChessBoard, loc: Location): Attacked
|
||||||
proc getSlidingAttacks(self: ChessBoard, loc: Location): tuple[attacks: Attacked, pins: Attacked]
|
proc getSlidingAttacks(self: ChessBoard, loc: Location): tuple[attacks: Attacked, pins: Attacked]
|
||||||
proc inCheck*(self: ChessBoard, color: PieceColor = None): bool
|
proc inCheck*(self: ChessBoard, color: PieceColor = None): bool
|
||||||
proc toFEN*(self: ChessBoard): string
|
proc toFEN*(self: ChessBoard): string
|
||||||
proc undoLastMove*(self: ChessBoard)
|
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.} =
|
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():
|
if target.isValid():
|
||||||
let otherPiece = self.grid[target]
|
let otherPiece = self.grid[target]
|
||||||
if target == self.position.enPassantSquare and self.grid[enPassantPawn].color == piece.color.opposite():
|
if target == self.position.enPassantSquare and self.grid[enPassantPawn].color == piece.color.opposite():
|
||||||
# Ensure en passant doesn't create a check
|
# En passant may be possible
|
||||||
let king = self.getKing(piece.color)
|
let targetPawn = self.grid[enPassantPawn]
|
||||||
var ok = true
|
# Remove both pieces and see if the king ends up in check
|
||||||
if king.row == location.row:
|
self.removePiece(enPassantPawn, attack=false)
|
||||||
var current = location
|
self.removePiece(location, attack=false)
|
||||||
while true:
|
self.updateAttackedSquares()
|
||||||
current = current + piece.color.rightSide()
|
if not self.inCheck(piece.color):
|
||||||
if not current.isValid():
|
# King is not in check after en passant: move is legal
|
||||||
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:
|
|
||||||
directions.add(diagonal)
|
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!
|
elif otherPiece.color == piece.color.opposite() and otherPiece.kind != King: # Can't capture the king!
|
||||||
|
# A capture may be possible
|
||||||
directions.add(diagonal)
|
directions.add(diagonal)
|
||||||
# Check for pins
|
# Check for pins
|
||||||
let pinned = self.getPinnedDirections(location)
|
let pinned = self.getPinnedDirections(location)
|
||||||
|
@ -924,8 +921,9 @@ proc generateSlidingMoves(self: ChessBoard, location: Location): seq[Move] =
|
||||||
if direction in pinned:
|
if direction in pinned:
|
||||||
newDirections.add(direction)
|
newDirections.add(direction)
|
||||||
directions = newDirections
|
directions = newDirections
|
||||||
let checked = self.inCheck()
|
let
|
||||||
let resolutions = if not checked: @[] else: self.getCheckResolutions(piece.color)
|
checked = self.inCheck()
|
||||||
|
resolutions = if not checked: @[] else: self.getCheckResolutions(piece.color)
|
||||||
for direction in directions:
|
for direction in directions:
|
||||||
# Slide in this direction as long as it's possible
|
# Slide in this direction as long as it's possible
|
||||||
var
|
var
|
||||||
|
@ -1333,9 +1331,10 @@ proc updateSlidingAttacks(self: ChessBoard) =
|
||||||
proc updateAttackedSquares(self: ChessBoard) =
|
proc updateAttackedSquares(self: ChessBoard) =
|
||||||
## Updates internal metadata about which squares
|
## Updates internal metadata about which squares
|
||||||
## are attacked
|
## are attacked
|
||||||
|
|
||||||
self.position.attacked.white.setLen(0)
|
self.position.attacked.white.setLen(0)
|
||||||
self.position.attacked.black.setLen(0)
|
self.position.attacked.black.setLen(0)
|
||||||
|
self.position.pinned.white.setLen(0)
|
||||||
|
self.position.pinned.black.setLen(0)
|
||||||
# Pawns
|
# Pawns
|
||||||
self.updatePawnAttacks()
|
self.updatePawnAttacks()
|
||||||
# Sliding pieces
|
# Sliding pieces
|
||||||
|
@ -1687,8 +1686,6 @@ proc undoLastMove*(self: ChessBoard) =
|
||||||
|
|
||||||
proc isLegal(self: ChessBoard, move: Move): bool {.inline.} =
|
proc isLegal(self: ChessBoard, move: Move): bool {.inline.} =
|
||||||
## Returns whether the given move is legal
|
## 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)
|
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
|
move.flags = move.flags or CastleLong.uint16
|
||||||
elif move.targetSquare == move.startSquare + shortCastleKing():
|
elif move.targetSquare == move.startSquare + shortCastleKing():
|
||||||
move.flags = move.flags or CastleShort.uint16
|
move.flags = move.flags or CastleShort.uint16
|
||||||
|
if move.targetSquare == board.getEnPassantTarget():
|
||||||
|
move.flags = move.flags or EnPassant.uint16
|
||||||
result = board.makeMove(move)
|
result = board.makeMove(move)
|
||||||
if result == emptyMove():
|
if result == emptyMove():
|
||||||
echo &"Error: move: {moveString} is illegal"
|
echo &"Error: move: {moveString} is illegal"
|
||||||
|
@ -2095,7 +2094,7 @@ proc handlePositionCommand(board: var ChessBoard, command: seq[string]) =
|
||||||
try:
|
try:
|
||||||
tempBoard = newChessboardFromFEN(fenString)
|
tempBoard = newChessboardFromFEN(fenString)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
echo &"Error: position: {getCurrentExceptionMsg()}"
|
echo &"error: position: {getCurrentExceptionMsg()}"
|
||||||
return
|
return
|
||||||
if args.len() > 0:
|
if args.len() > 0:
|
||||||
var i = 0
|
var i = 0
|
||||||
|
@ -2113,6 +2112,9 @@ proc handlePositionCommand(board: var ChessBoard, command: seq[string]) =
|
||||||
echo board
|
echo board
|
||||||
of "pretty":
|
of "pretty":
|
||||||
echo board.pretty()
|
echo board.pretty()
|
||||||
|
else:
|
||||||
|
echo &"error: position: unknown subcommand '{command[1]}'"
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
proc handleUCICommand(board: var ChessBoard, command: seq[string]) =
|
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
|
- ep: Print the current en passant target
|
||||||
- pretty: Shorthand for "position pretty"
|
- pretty: Shorthand for "position pretty"
|
||||||
- print: Shorthand for "position print"
|
- 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
|
- get <square>: Get the piece on the given square
|
||||||
- uci: enter UCI mode (WIP)
|
- uci: enter UCI mode (WIP)
|
||||||
"""
|
"""
|
||||||
|
@ -2189,7 +2192,7 @@ proc main: int =
|
||||||
echo HELP_TEXT
|
echo HELP_TEXT
|
||||||
of "go":
|
of "go":
|
||||||
handleGoCommand(board, cmd)
|
handleGoCommand(board, cmd)
|
||||||
of "position":
|
of "position", "pos":
|
||||||
handlePositionCommand(board, cmd)
|
handlePositionCommand(board, cmd)
|
||||||
of "move":
|
of "move":
|
||||||
handleMoveCommand(board, cmd)
|
handleMoveCommand(board, cmd)
|
||||||
|
|
Loading…
Reference in New Issue