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 var
location = loc location = loc
otherPiece: Piece otherPiece: Piece
moveKing: bool = true
while true: while true:
location = location + kingSide location = location + kingSide
if location == color.kingSideRook(): 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 break
if location == loc + shortCastleKing():
moveKing = false
otherPiece = self.grid[location.row, location.col] otherPiece = self.grid[location.row, location.col]
if otherPiece.color != None: if otherPiece.color != None:
result.king = false result.king = false
break break
if moveKing and self.isAttacked(location, color.opposite()): if self.isAttacked(location, color.opposite()):
result.king = false result.king = false
break break
if result.queen: if result.queen:
# Long castle # Long castle
var var
location = loc location = loc
otherPiece: Piece otherPiece: Piece
moveKing: bool = true
while true: while true:
location = location + queenSide location = location + queenSide
if location == color.queenSideRook(): if location == color.queenSideRook():
break break
if location == loc + longCastleKing():
moveKing = false
otherPiece = self.grid[location.row, location.col] otherPiece = self.grid[location.row, location.col]
if otherPiece.color != None: if otherPiece.color != None:
result.queen = false result.queen = false
break break
if moveKing and self.isAttacked(location, color.opposite()): if self.isAttacked(location, color.opposite()):
result.queen = false result.queen = false
break 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: if double.isValid() and self.grid[forward.row, forward.col].color == None and self.grid[double.row, double.col].color == None:
targets.add(double) targets.add(double)
let enPassantPawn = self.getEnPassantTarget() + piece.color.opposite().topSide() let enPassantPawn = self.getEnPassantTarget() + piece.color.opposite().topSide()
# They can also move on either diagonal one # They can also move one square on either of their
# square, but only to capture or for en passant # forward diagonals, but only for captures and en passant
for diagonal in [location + piece.color.topRightDiagonal(), location + piece.color.topLeftDiagonal()]: for diagonal in [location + piece.color.topRightDiagonal(), location + piece.color.topLeftDiagonal()]:
if diagonal.isValid(): if diagonal.isValid():
let otherPiece = self.grid[diagonal.row, diagonal.col] 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 # Ensure en passant doesn't create a check
let king = self.getKing(piece.color) let king = self.getKing(piece.color)
var ok = true var ok = true
@ -971,7 +964,7 @@ proc generateKingMoves(self: ChessBoard, location: Location): seq[Move] =
else: else:
flag = Default flag = Default
let otherPiece = self.grid[square.row, square.col] let otherPiece = self.grid[square.row, square.col]
if otherPiece.color == self.getActiveColor.opposite(): if otherPiece.color == piece.color.opposite():
flag = Capture flag = Capture
# A friendly piece is in the way, move onto the next direction # A friendly piece is in the way, move onto the next direction
if otherPiece.color == piece.color: if otherPiece.color == piece.color:
@ -1326,9 +1319,9 @@ proc removePiece(self: ChessBoard, location: Location, attack: bool = true, empt
of Pawn: of Pawn:
self.position.pieces.white.pawns.delete(self.position.pieces.white.pawns.find(location)) self.position.pieces.white.pawns.delete(self.position.pieces.white.pawns.find(location))
of Bishop: 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: 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: of Rook:
self.position.pieces.white.rooks.delete(self.position.pieces.white.rooks.find(location)) self.position.pieces.white.rooks.delete(self.position.pieces.white.rooks.find(location))
of Queen: of Queen:
@ -1484,7 +1477,7 @@ proc doMove(self: ChessBoard, move: Move) =
if move.isCapture(): if move.isCapture():
let captured = self.grid[move.targetSquare.row, move.targetSquare.col] let captured = self.grid[move.targetSquare.row, move.targetSquare.col]
if captured.kind == Rook: if captured.kind == Rook:
case piece.color: case captured.color:
of White: of White:
if move.targetSquare == captured.color.queenSideRook(): if move.targetSquare == captured.color.queenSideRook():
# Queen side # Queen side
@ -1694,7 +1687,7 @@ proc `$`*(self: ChessBoard): string =
proc toPretty*(piece: Piece): string = proc toPretty*(piece: Piece): string =
case piece.color: case piece.color:
of Black: of White:
case piece.kind: case piece.kind:
of King: of King:
return "\U2654" return "\U2654"
@ -1710,7 +1703,7 @@ proc toPretty*(piece: Piece): string =
return "\U2659" return "\U2659"
else: else:
discard discard
of White: of Black:
case piece.kind: case piece.kind:
of King: of King:
return "\U265A" return "\U265A"
@ -1723,7 +1716,7 @@ proc toPretty*(piece: Piece): string =
of Knight: of Knight:
return "\U265E" return "\U265E"
of Pawn: of Pawn:
return "\U265F" return "\240\159\168\133"
else: else:
discard discard
else: else:
@ -1731,13 +1724,15 @@ proc toPretty*(piece: Piece): string =
proc pretty*(self: ChessBoard): string = proc pretty*(self: ChessBoard): string =
## Returns a colorized version of the ## Returns a colored version of the
## board for easier visualization ## board for easier visualization
for i in 0..7: for i in 0..7:
if i > 0: if i > 0:
result &= "\n" result &= "\n"
for j in 0..7: 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" result &= "\x1b[39;44;1m"
else: else:
result &= "\x1b[39;40;1m" result &= "\x1b[39;40;1m"
@ -2116,6 +2111,7 @@ 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"
- get <square>: Get the piece on the given square
""" """
@ -2158,6 +2154,15 @@ proc main: int =
echo &"En passant target: {target.locationToAlgebraic()}" echo &"En passant target: {target.locationToAlgebraic()}"
else: else:
echo "En passant target: None" 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": of "castle":
let canCastle = board.canCastle() 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\")}" 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 continue
if nodes[0] != nodes[1]: if nodes[0] != nodes[1]:
mistakes.add(move) mistakes.add(move)
mistakes = sorted(list(mistakes))
total_nodes = {"stockfish": sum(positions["stockfish"][move] for move in positions["stockfish"]), total_nodes = {"stockfish": sum(positions["stockfish"][move] for move in positions["stockfish"]),
"nimfish": sum(positions["nimfish"][move] for move in positions["nimfish"])} "nimfish": sum(positions["nimfish"][move] for move in positions["nimfish"])}
total_difference = total_nodes["stockfish"] - total_nodes["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'}") print(f"Nimfish searched {total_nodes['nimfish']} node{'' if total_nodes['nimfish'] == 1 else 's'}")
if total_difference > 0: 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: elif total_difference < 0:
total_difference = abs(total_difference) total_difference = abs(total_difference)
print(f"Nimfish searched {total_difference} more node{'' if total_difference == 1 else 's'} than Stockfish") print(f"Nimfish searched {total_difference} more node{'' if total_difference == 1 else 's'} than Stockfish")