Several bug fixes and minor improvements/additions

This commit is contained in:
Mattia Giambirtone 2024-04-09 17:46:30 +02:00
parent 77129855df
commit 57353c0994
2 changed files with 33 additions and 28 deletions

View File

@ -723,46 +723,39 @@ proc canCastle*(self: ChessBoard, color: PieceColor = None): tuple[queen, king:
var
location = loc
otherPiece: Piece
moveKing: bool = true
while true:
location = location + kingSide
if location == color.kingSideRook():
# No need to do any extra checks: if the piece
# on this square were not a rook of the same color
# as the castling king, then we wouldn't have gotten
# here in the first place (it would've had to be either
# moved or captured, and both of those actions are detected
# and accounted for way before this point)
break
if location == loc + shortCastleKing():
moveKing = false
otherPiece = self.grid[location.row, location.col]
if otherPiece.color != None:
result.king = false
break
if moveKing and self.isAttacked(location, color.opposite()):
if self.isAttacked(location, color.opposite()):
result.king = false
break
if result.queen:
# Long castle
var
location = loc
otherPiece: Piece
moveKing: bool = true
while true:
location = location + queenSide
if location == color.queenSideRook():
break
if location == loc + longCastleKing():
moveKing = false
otherPiece = self.grid[location.row, location.col]
if otherPiece.color != None:
result.queen = false
break
if moveKing and self.isAttacked(location, color.opposite()):
if self.isAttacked(location, color.opposite()):
result.queen = false
break
@ -824,12 +817,12 @@ proc generatePawnMoves(self: ChessBoard, location: Location): seq[Move] =
if double.isValid() and self.grid[forward.row, forward.col].color == None and self.grid[double.row, double.col].color == None:
targets.add(double)
let enPassantPawn = self.getEnPassantTarget() + piece.color.opposite().topSide()
# They can also move on either diagonal one
# square, but only to capture or for en passant
# They can also move one square on either of their
# forward diagonals, but only for captures and en passant
for diagonal in [location + piece.color.topRightDiagonal(), location + piece.color.topLeftDiagonal()]:
if diagonal.isValid():
let otherPiece = self.grid[diagonal.row, diagonal.col]
if diagonal == self.position.enPassantSquare and self.grid[enPassantPawn.row, enPassantPawn.col].color == self.getActiveColor().opposite():
if diagonal == self.position.enPassantSquare and self.grid[enPassantPawn.row, enPassantPawn.col].color == piece.color.opposite():
# Ensure en passant doesn't create a check
let king = self.getKing(piece.color)
var ok = true
@ -971,7 +964,7 @@ proc generateKingMoves(self: ChessBoard, location: Location): seq[Move] =
else:
flag = Default
let otherPiece = self.grid[square.row, square.col]
if otherPiece.color == self.getActiveColor.opposite():
if otherPiece.color == piece.color.opposite():
flag = Capture
# A friendly piece is in the way, move onto the next direction
if otherPiece.color == piece.color:
@ -1326,9 +1319,9 @@ proc removePiece(self: ChessBoard, location: Location, attack: bool = true, empt
of Pawn:
self.position.pieces.white.pawns.delete(self.position.pieces.white.pawns.find(location))
of Bishop:
self.position.pieces.white.pawns.delete(self.position.pieces.white.bishops.find(location))
self.position.pieces.white.bishops.delete(self.position.pieces.white.bishops.find(location))
of Knight:
self.position.pieces.white.pawns.delete(self.position.pieces.white.knights.find(location))
self.position.pieces.white.knights.delete(self.position.pieces.white.knights.find(location))
of Rook:
self.position.pieces.white.rooks.delete(self.position.pieces.white.rooks.find(location))
of Queen:
@ -1484,7 +1477,7 @@ proc doMove(self: ChessBoard, move: Move) =
if move.isCapture():
let captured = self.grid[move.targetSquare.row, move.targetSquare.col]
if captured.kind == Rook:
case piece.color:
case captured.color:
of White:
if move.targetSquare == captured.color.queenSideRook():
# Queen side
@ -1694,7 +1687,7 @@ proc `$`*(self: ChessBoard): string =
proc toPretty*(piece: Piece): string =
case piece.color:
of Black:
of White:
case piece.kind:
of King:
return "\U2654"
@ -1710,7 +1703,7 @@ proc toPretty*(piece: Piece): string =
return "\U2659"
else:
discard
of White:
of Black:
case piece.kind:
of King:
return "\U265A"
@ -1723,7 +1716,7 @@ proc toPretty*(piece: Piece): string =
of Knight:
return "\U265E"
of Pawn:
return "\U265F"
return "\240\159\168\133"
else:
discard
else:
@ -1731,13 +1724,15 @@ proc toPretty*(piece: Piece): string =
proc pretty*(self: ChessBoard): string =
## Returns a colorized version of the
## Returns a colored version of the
## board for easier visualization
for i in 0..7:
if i > 0:
result &= "\n"
for j in 0..7:
if ((i + j) mod 2) == 0:
# Equivalent to (i + j) mod 2
# (I'm just evil)
if ((i + j) and 1) == 0:
result &= "\x1b[39;44;1m"
else:
result &= "\x1b[39;40;1m"
@ -2116,6 +2111,7 @@ const HELP_TEXT = """Nimfish help menu:
- ep: Print the current en passant target
- pretty: Shorthand for "position pretty"
- print: Shorthand for "position print"
- get <square>: Get the piece on the given square
"""
@ -2158,6 +2154,15 @@ proc main: int =
echo &"En passant target: {target.locationToAlgebraic()}"
else:
echo "En passant target: None"
of "get":
if len(cmd) != 2:
echo "get: invalid syntax"
continue
try:
echo board.getPiece(cmd[1])
except ValueError:
echo "get: invalid square"
continue
of "castle":
let canCastle = board.canCastle()
echo &"Castling rights for {($board.getActiveColor()).toLowerAscii()}:\n - King side: {(if canCastle.king: \"yes\" else: \"no\")}\n - Queen side: {(if canCastle.queen: \"yes\" else: \"no\")}"

View File

@ -86,7 +86,7 @@ def main(args: Namespace) -> int:
continue
if nodes[0] != nodes[1]:
mistakes.add(move)
mistakes = sorted(list(mistakes))
total_nodes = {"stockfish": sum(positions["stockfish"][move] for move in positions["stockfish"]),
"nimfish": sum(positions["nimfish"][move] for move in positions["nimfish"])}
total_difference = total_nodes["stockfish"] - total_nodes["nimfish"]
@ -94,7 +94,7 @@ def main(args: Namespace) -> int:
print(f"Nimfish searched {total_nodes['nimfish']} node{'' if total_nodes['nimfish'] == 1 else 's'}")
if total_difference > 0:
print(f"Nimfish searched {total_difference} less node{'' if total_difference == 1 else 's'} than Stockfish")
print(f"Nimfish searched {total_difference} fewer node{'' if total_difference == 1 else 's'} than Stockfish")
elif total_difference < 0:
total_difference = abs(total_difference)
print(f"Nimfish searched {total_difference} more node{'' if total_difference == 1 else 's'} than Stockfish")