Implemented knight moves

This commit is contained in:
Mattia Giambirtone 2023-10-17 12:42:15 +02:00
parent e782935fd7
commit ca498ebc42
2 changed files with 94 additions and 3 deletions

View File

@ -107,6 +107,9 @@ func `+`*(a, b: Location): Location = (a.row + b.row, a.col + b.col)
func isValid*(a: Location): bool = a.row in 0..7 and a.col in 0..7
proc generateMoves(self: ChessBoard, location: Location): seq[Move]
# Due to our board layout, directions of movement are reversed for white/black so
# we need these helpers to avoid going mad with integer tuples and minus signs
# everywhere
func topLeftDiagonal(piece: Piece): Location {.inline.} = (if piece.color == White: (-1, -1) else: (1, 1))
func topRightDiagonal(piece: Piece): Location {.inline.} = (if piece.color == White: (-1, 1) else: (1, -1))
func bottomLeftDiagonal(piece: Piece): Location {.inline.} = (if piece.color == White: (1, -1) else: (-1, 1))
@ -115,8 +118,60 @@ func leftSide(piece: Piece): Location {.inline.} = (if piece.color == White: (0,
func rightSide(piece: Piece): Location {.inline.} = (if piece.color == White: (0, 1) else: (0, -1))
func topSide(piece: Piece): Location {.inline.} = (if piece.color == White: (-1, 0) else: (1, 0))
func bottomSide(piece: Piece): Location {.inline.} = (if piece.color == White: (1, 0) else: (-1, 0))
func forward(piece: Piece): Location {.inline.} = (if piece.color == Black: (1, 0) else: (-1, 0))
func doublePush(piece: Piece): Location {.inline.} = (if piece.color == Black: (2, 0) else: (-2, 0))
func forward(piece: Piece): Location {.inline.} = (if piece.color == White: (-1, 0) else: (1, 0))
func doublePush(piece: Piece): Location {.inline.} = (if piece.color == White: (-2, 0) else: (2, 0))
func bottomLeftKnightMove(piece: Piece, long: bool = true): Location {.inline.} =
if piece.color == White:
if long:
return (-2, 1)
else:
return (1, -2)
elif piece.color == Black:
if long:
return (2, -1)
else:
return (1, -2)
func bottomRightKnightMove(piece: Piece, long: bool = true): Location {.inline.} =
if piece.color == White:
if long:
return (2, -1)
else:
return (1, 2)
elif piece.color == Black:
if long:
return (2, 1)
else:
return (1, 2)
func topLeftKnightMove(piece: Piece, long: bool = true): Location {.inline.} =
if piece.color == White:
if long:
return (-2, -1)
else:
return (-1, -2)
elif piece.color == Black:
if long:
return (2, 1)
else:
return (1, 2)
func topRightKnightMove(piece: Piece, long: bool = true): Location {.inline.} =
if piece.color == White:
if long:
return (-2, 1)
else:
return (-1, 2)
elif piece.color == Black:
if long:
return (2, -1)
else:
return (-1, 2)
proc getActiveColor*(self: ChessBoard): PieceColor =
@ -556,7 +611,39 @@ proc generateKingMoves(self: ChessBoard, location: Location): seq[Move] =
continue
# Target square is empty
result.add(Move(startSquare: location, targetSquare: square, piece: piece))
proc generateKnightMoves(self: ChessBoard, location: Location): seq[Move] =
## Generates moves for the knight in the given location
var
piece = self.grid[location.row, location.col]
doAssert piece.kind == Knight, &"generateKnightMoves called on a {piece.kind}"
var directions: seq[Location] = @[piece.bottomLeftKnightMove(),
piece.bottomRightKnightMove(),
piece.topLeftKnightMove(),
piece.topRightKnightMove(),
piece.bottomLeftKnightMove(long=false),
piece.bottomRightKnightMove(long=false),
piece.topLeftKnightMove(long=false),
piece.topRightKnightMove(long=false)]
for direction in directions:
# Jump to this square
let square: Location = location + direction
# End of board reached
if not square.isValid():
continue
let otherPiece = self.grid[square.row, square.col]
# A friendly piece is in the way
if otherPiece.color == piece.color:
continue
if otherPiece.color == piece.color.opposite:
# Target square contains an enemy piece: capture
# it
result.add(Move(startSquare: location, targetSquare: square, piece: piece))
continue
# Target square is empty
result.add(Move(startSquare: location, targetSquare: square, piece: piece))
proc generateMoves(self: ChessBoard, location: Location): seq[Move] =
## Returns the list of possible legal chess moves for the
@ -569,6 +656,8 @@ proc generateMoves(self: ChessBoard, location: Location): seq[Move] =
return self.generatePawnMoves(location)
of King:
return self.generateKingMoves(location)
of Knight:
return self.generateKnightMoves(location)
else:
return @[]

View File

@ -35,3 +35,5 @@ when isMainModule:
move = board.makeMove(startSquare, targetSquare)
except ValueError:
echo &"Error: {getCurrentExceptionMsg()}"
if move == emptyMove():
echo &"Error: move is illegal"