Bishops are now behaving
This commit is contained in:
parent
e1ee38ab6e
commit
63b39dc761
|
@ -69,7 +69,7 @@ type
|
||||||
## A chess board object
|
## A chess board object
|
||||||
grid: Matrix[Piece]
|
grid: Matrix[Piece]
|
||||||
# Currently active color
|
# Currently active color
|
||||||
turn*: PieceColor
|
turn: PieceColor
|
||||||
# Number of half moves since
|
# Number of half moves since
|
||||||
# last piece capture or pawn movement.
|
# last piece capture or pawn movement.
|
||||||
# Used for the 50-move rule
|
# Used for the 50-move rule
|
||||||
|
@ -87,7 +87,7 @@ type
|
||||||
pieces: tuple[white: Pieces, black: Pieces]
|
pieces: tuple[white: Pieces, black: Pieces]
|
||||||
# Locations of all attacked squares and their
|
# Locations of all attacked squares and their
|
||||||
# respective attackers
|
# respective attackers
|
||||||
attacked*: tuple[white: seq[tuple[attacker: Piece, loc: Location]], black: seq[tuple[attacker: Piece, loc: Location]]]
|
attacked: tuple[white: seq[tuple[attacker: Piece, loc: Location]], black: seq[tuple[attacker: Piece, loc: Location]]]
|
||||||
|
|
||||||
|
|
||||||
# Initialized only once, copied every time
|
# Initialized only once, copied every time
|
||||||
|
@ -102,6 +102,21 @@ func opposite*(c: PieceColor): PieceColor {.inline.} = (if c == White: Black els
|
||||||
proc algebraicToPosition*(s: string): Location {.inline.}
|
proc algebraicToPosition*(s: string): Location {.inline.}
|
||||||
proc getCapture*(self: ChessBoard, move: Move): Location
|
proc getCapture*(self: ChessBoard, move: Move): Location
|
||||||
func emptyMove*: Move {.inline.} = Move(startSquare: emptyLocation(), targetSquare: emptyLocation(), piece: emptyPiece())
|
func emptyMove*: Move {.inline.} = Move(startSquare: emptyLocation(), targetSquare: emptyLocation(), piece: emptyPiece())
|
||||||
|
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]
|
||||||
|
|
||||||
|
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 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))
|
||||||
|
proc testMoveOffsets(self: ChessBoard, move: Move): bool
|
||||||
|
|
||||||
|
|
||||||
|
proc getActiveColor*(self: ChessBoard): PieceColor =
|
||||||
|
## Returns the currently active color
|
||||||
|
## (turn of who has to move)
|
||||||
|
return self.turn
|
||||||
|
|
||||||
|
|
||||||
func getStartRow(piece: Piece): int {.inline.} =
|
func getStartRow(piece: Piece): int {.inline.} =
|
||||||
|
@ -376,6 +391,29 @@ proc getPiece*(self: ChessBoard, square: string): Piece =
|
||||||
return self.grid[loc.row, loc.col]
|
return self.grid[loc.row, loc.col]
|
||||||
|
|
||||||
|
|
||||||
|
proc getCapture*(self: ChessBoard, move: Move): Location =
|
||||||
|
## Returns the location that would be captured if this
|
||||||
|
## move were played on the board, taking en passant and
|
||||||
|
## other things into account (the move is assumed to be
|
||||||
|
## already valid). An empty location is returned if no
|
||||||
|
## piece is captured by the given move
|
||||||
|
result = emptyLocation()
|
||||||
|
let target = self.grid[move.targetSquare.row, move.targetSquare.col]
|
||||||
|
if target.color == None:
|
||||||
|
if move.targetSquare != self.enPassantSquare.targetSquare:
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
return ((if move.piece.color == White: move.targetSquare.row + 1 else: move.targetSquare.row - 1), move.targetSquare.col)
|
||||||
|
if target.color == move.piece.color.opposite():
|
||||||
|
return move.targetSquare
|
||||||
|
|
||||||
|
|
||||||
|
proc isCapture*(self: ChessBoard, move: Move): bool {.inline.} =
|
||||||
|
## Returns whether the given move is a capture
|
||||||
|
## or not
|
||||||
|
return self.getCapture(move) != emptyLocation()
|
||||||
|
|
||||||
|
|
||||||
proc generatePawnMoves(self: ChessBoard, location: Location): seq[Move] =
|
proc generatePawnMoves(self: ChessBoard, location: Location): seq[Move] =
|
||||||
## Generates the possible moves for the pawn in the given
|
## Generates the possible moves for the pawn in the given
|
||||||
## location
|
## location
|
||||||
|
@ -383,78 +421,83 @@ proc generatePawnMoves(self: ChessBoard, location: Location): seq[Move] =
|
||||||
piece = self.grid[location.row, location.col]
|
piece = self.grid[location.row, location.col]
|
||||||
locations: seq[Location] = @[]
|
locations: seq[Location] = @[]
|
||||||
doAssert piece.kind == Pawn, &"generatePawnMoves called on a {piece.kind}"
|
doAssert piece.kind == Pawn, &"generatePawnMoves called on a {piece.kind}"
|
||||||
case piece.color:
|
# Pawns can move forward one square
|
||||||
of White:
|
let forwardOffset = piece.forward()
|
||||||
# Pawns can move forward one square. In our flipped
|
let forward = (forwardOffset + location)
|
||||||
# board configuration, that means moving up one row
|
if forward.isValid() and self.grid[forward.row, forward.col].color == None:
|
||||||
# while keeping the column the same
|
locations.add(forwardOffset)
|
||||||
if location.row in 1..6 and self.grid[location.row - 1, location.col].color == None:
|
# If the pawn is on its first rank, it can push two squares
|
||||||
locations.add((location.row - 1, location.col))
|
if location.row == piece.getStartRow():
|
||||||
|
locations.add(piece.doublePush())
|
||||||
if self.enPassantSquare.piece.color == piece.color.opposite:
|
if self.enPassantSquare.piece.color == piece.color.opposite:
|
||||||
if abs(self.enPassantSquare.targetSquare.col - location.col) == 1 and abs(self.enPassantSquare.targetSquare.row - location.row) == 1:
|
if abs(self.enPassantSquare.targetSquare.col - location.col) == 1 and abs(self.enPassantSquare.targetSquare.row - location.row) == 1:
|
||||||
# Only viable if the piece is on the diagonal of the target
|
# Only viable if the piece is on the diagonal of the target
|
||||||
locations.add(self.enPassantSquare.targetSquare)
|
locations.add(self.enPassantSquare.targetSquare)
|
||||||
# They can also move on either diagonal one
|
# They can also move on either diagonal one
|
||||||
# square, but only to capture
|
# square, but only to capture
|
||||||
if location.col in 1..6 and location.row in 1..6:
|
if location.col in 1..6:
|
||||||
if self.grid[location.row + 1, location.col + 1].color == Black:
|
# Top right diagonal
|
||||||
# Top right diagonal (white side)
|
locations.add(piece.topRightDiagonal())
|
||||||
locations.add((location.row + 1, location.col + 1))
|
if location.row in 1..6:
|
||||||
if self.grid[location.row - 1, location.col - 1].color == Black:
|
|
||||||
# Top left diagonal
|
# Top left diagonal
|
||||||
locations.add((location.row + 1, location.col + 1))
|
locations.add(piece.topLeftDiagonal())
|
||||||
|
|
||||||
# Pawn is at the right side, can only capture
|
# Pawn is at the right side, can only capture
|
||||||
# on the left one
|
# on the left one
|
||||||
elif location.col == 0 and location.row < 7 and self.grid[location.row + 1, location.col + 1].color == Black:
|
if location.col == 7 and location.row < 7:
|
||||||
locations.add((location.row + 1, location.col + 1))
|
locations.add(piece.topLeftDiagonal())
|
||||||
# Pawn is at the left side, can only capture
|
# Pawn is at the left side, can only capture
|
||||||
# on the right one
|
# on the right one
|
||||||
elif location.col == 7 and location.row < 7 and self.grid[location.row + 1, location.col - 1].color == Black:
|
if location.col == 0 and location.row < 7:
|
||||||
locations.add((location.row - 1, location.col - 1))
|
locations.add(piece.topRightDiagonal())
|
||||||
of Black:
|
var
|
||||||
# Pawns can move forward one square. In our flipped
|
newLocation: Location
|
||||||
# board configuration, that means moving down one row
|
targetPiece: Piece
|
||||||
# while keeping the column the same
|
|
||||||
if location.row in 1..6 and self.grid[location.row - 1, location.col].color == None:
|
|
||||||
locations.add((1, 0))
|
|
||||||
if self.enPassantSquare.piece.color == piece.color.opposite:
|
|
||||||
if abs(self.enPassantSquare.targetSquare.col - location.col) == 1 and abs(self.enPassantSquare.targetSquare.row - location.row) == 1:
|
|
||||||
# Only viable if the piece is on the diagonal of the target
|
|
||||||
locations.add(self.enPassantSquare.targetSquare)
|
|
||||||
# They can also move on either diagonal one
|
|
||||||
# square, but only to capture
|
|
||||||
if location.col in 1..6 and location.row in 1..6:
|
|
||||||
if self.grid[location.row - 1, location.col - 1].color == White:
|
|
||||||
# Top right diagonal (black side)
|
|
||||||
locations.add((1, 1))
|
|
||||||
if self.grid[location.row + 1, location.col + 1].color == White:
|
|
||||||
# Top left diagonal
|
|
||||||
locations.add((-1, -1))
|
|
||||||
# Pawn is at the right side, can only capture
|
|
||||||
# on the left one
|
|
||||||
elif location.col > 0 and location.row > 0 and self.grid[location.row - 1, location.col + 1].color == White:
|
|
||||||
locations.add((-1, -1))
|
|
||||||
# Pawn is at the left side, can only capture
|
|
||||||
# on the right one
|
|
||||||
elif location.col == 7 and location.row > 0 and self.grid[location.row + 1, location.col + 1].color == White:
|
|
||||||
locations.add((1, 1))
|
|
||||||
else:
|
|
||||||
discard
|
|
||||||
for target in locations:
|
for target in locations:
|
||||||
if target.row == piece.color.getLastRow():
|
newLocation = location + target
|
||||||
|
if not newLocation.isValid():
|
||||||
|
continue
|
||||||
|
targetPiece = self.grid[newLocation.row, newLocation.col]
|
||||||
|
if targetPiece.color == piece.color:
|
||||||
|
# Can't move over a friendly piece
|
||||||
|
continue
|
||||||
|
if location.col != newLocation.col and not self.isCapture(Move(piece: piece, startSquare: location, targetSquare: newLocation)):
|
||||||
|
# Can only move diagonally when capturing
|
||||||
|
continue
|
||||||
|
if newLocation.row == piece.color.getLastRow():
|
||||||
# Generate all promotion moves
|
# Generate all promotion moves
|
||||||
for promotionType in [PromoteToKnight, PromoteToBishop, PromoteToRook, PromoteToQueen]:
|
for promotionType in [PromoteToKnight, PromoteToBishop, PromoteToRook, PromoteToQueen]:
|
||||||
result.add(Move(startSquare: location, targetSquare: target, piece: self.grid[location.row, location.col], flag: promotionType))
|
result.add(Move(startSquare: location, targetSquare: newLocation, piece: piece, flag: promotionType))
|
||||||
else:
|
continue
|
||||||
result.add(Move(startSquare: location, targetSquare: target, piece: self.grid[location.row, location.col]))
|
# Move is just a pawn push
|
||||||
|
result.add(Move(startSquare: location, targetSquare: newLocation, piece: piece))
|
||||||
|
|
||||||
|
|
||||||
proc generateSlidingMoves(self: ChessBoard, location: Location): seq[Move] =
|
proc generateSlidingMoves(self: ChessBoard, location: Location): seq[Move] =
|
||||||
## Generates sliding moves for the sliding piece in the given location
|
## Generates moves for the sliding piece in the given location
|
||||||
var
|
var
|
||||||
piece = self.grid[location.row, location.col]
|
piece = self.grid[location.row, location.col]
|
||||||
doAssert piece.kind in [Bishop, Rook, Queen], &"generateSlidingMoves called on a {piece.kind}"
|
doAssert piece.kind in [Bishop, Rook, Queen], &"generateSlidingMoves called on a {piece.kind}"
|
||||||
|
var directions: seq[Location] = @[piece.topRightDiagonal(), piece.topLeftDiagonal()]
|
||||||
|
echo piece, " ", location
|
||||||
|
for direction in directions:
|
||||||
|
echo "dir ", direction
|
||||||
|
# Slide in this direction as long as it's possible
|
||||||
|
var
|
||||||
|
square: Location = location
|
||||||
|
otherPiece: Piece
|
||||||
|
while true:
|
||||||
|
square = square + direction
|
||||||
|
# End of board reached
|
||||||
|
if not square.isValid():
|
||||||
|
break
|
||||||
|
echo square
|
||||||
|
otherPiece = self.grid[square.row, square.col]
|
||||||
|
# A friendly piece is in the way
|
||||||
|
if otherPiece.color == piece.color:
|
||||||
|
break
|
||||||
|
# Target square is empty or occupied by the enemy
|
||||||
|
result.add(Move(startSquare: location, targetSquare: square, piece: piece))
|
||||||
|
|
||||||
|
|
||||||
proc generateMoves(self: ChessBoard, location: Location): seq[Move] =
|
proc generateMoves(self: ChessBoard, location: Location): seq[Move] =
|
||||||
|
@ -470,76 +513,6 @@ proc generateMoves(self: ChessBoard, location: Location): seq[Move] =
|
||||||
return @[]
|
return @[]
|
||||||
|
|
||||||
|
|
||||||
proc getCapture*(self: ChessBoard, move: Move): Location =
|
|
||||||
## Returns the location that would be captured if this
|
|
||||||
## move were played on the board, taking en passant and
|
|
||||||
## other things into account. An empty location is returned
|
|
||||||
## if no piece is captured by the given move
|
|
||||||
result = emptyLocation()
|
|
||||||
let target = self.grid[move.targetSquare.row, move.targetSquare.col]
|
|
||||||
if target.color == None:
|
|
||||||
if move.targetSquare != self.enPassantSquare.targetSquare:
|
|
||||||
return
|
|
||||||
else:
|
|
||||||
return ((if move.piece.color == White: move.targetSquare.row + 1 else: move.targetSquare.row - 1), move.targetSquare.col)
|
|
||||||
if target.color == move.piece.color.opposite() and move in self.generateMoves(move.startSquare):
|
|
||||||
return move.targetSquare
|
|
||||||
|
|
||||||
|
|
||||||
proc isCapture*(self: ChessBoard, move: Move): bool {.inline.} =
|
|
||||||
## Returns whether the given move is a capture
|
|
||||||
## or not
|
|
||||||
return self.getCapture(move) != emptyLocation()
|
|
||||||
|
|
||||||
|
|
||||||
proc validatePawnMove(self: ChessBoard, move: Move): bool =
|
|
||||||
## Returns true if the given pawn move is allowed
|
|
||||||
## (internal helper to testMoveOffsets)
|
|
||||||
if move.targetSquare.col != move.startSquare.col:
|
|
||||||
# Pawn can only change column in case of capture or en passant
|
|
||||||
if self.enPassantSquare == emptyMove():
|
|
||||||
# No en passant possible, only possibility
|
|
||||||
# is a capture
|
|
||||||
return self.isCapture(move)
|
|
||||||
# En passant is possible, check if the destination is
|
|
||||||
# its target square
|
|
||||||
if self.enPassantSquare.targetSquare != move.targetSquare:
|
|
||||||
# We still need to check for captures even if en passant
|
|
||||||
# is possible
|
|
||||||
return self.isCapture(move)
|
|
||||||
# Number of rows traveled
|
|
||||||
var rows: int
|
|
||||||
# Due to our unique board layout, we need to do this nonsense
|
|
||||||
if move.piece.color == White:
|
|
||||||
rows = move.startSquare.row - move.targetSquare.row
|
|
||||||
else:
|
|
||||||
rows = move.targetSquare.row - move.startSquare.row
|
|
||||||
if rows < 0 or rows > 2:
|
|
||||||
# Pawns don't go backwards, I'm afraid. They also can't
|
|
||||||
# go any further than 2 squares
|
|
||||||
return false
|
|
||||||
if rows == 2:
|
|
||||||
# Check if double pawn pushing is possible (only the first
|
|
||||||
# move for each pawn)
|
|
||||||
if move.startSquare.row != move.piece.getStartRow():
|
|
||||||
# Pawn has already moved more than once, double push
|
|
||||||
# is not allowed
|
|
||||||
return false
|
|
||||||
# En passant is now possible
|
|
||||||
let targetSquare: Location = ((if move.piece.color == White: move.targetSquare.row + 1 else: move.targetSquare.row - 1), move.targetSquare.col)
|
|
||||||
self.enPassantSquare = Move(piece: move.piece, startSquare: move.startSquare, targetSquare: targetSquare)
|
|
||||||
# Captures are checked earlier, so we only need to make sure we aren't blocked by
|
|
||||||
# a piece
|
|
||||||
return self.grid[move.targetSquare.row, move.targetSquare.col].kind == Empty
|
|
||||||
|
|
||||||
|
|
||||||
proc validateSlidingMove(self: ChessBoard, move: Move): bool =
|
|
||||||
## Returns true if the given pawn move is allowed
|
|
||||||
## (internal helper to testMoveOffsets)
|
|
||||||
|
|
||||||
var directions: seq[Location]
|
|
||||||
|
|
||||||
|
|
||||||
proc testMoveOffsets(self: ChessBoard, move: Move): bool =
|
proc testMoveOffsets(self: ChessBoard, move: Move): bool =
|
||||||
## Returns true if the piece in the given
|
## Returns true if the piece in the given
|
||||||
## move is pseudo-legal: this does not take pins
|
## move is pseudo-legal: this does not take pins
|
||||||
|
@ -552,9 +525,15 @@ proc testMoveOffsets(self: ChessBoard, move: Move): bool =
|
||||||
## does)
|
## does)
|
||||||
case move.piece.kind:
|
case move.piece.kind:
|
||||||
of Pawn:
|
of Pawn:
|
||||||
return self.validatePawnMove(move)
|
return move in self.generatePawnMoves(move.startSquare)
|
||||||
of Bishop:
|
of Bishop, Queen, Rook:
|
||||||
return self.validateSlidingMove(move)
|
return move in self.generateSlidingMoves(move.startSquare)
|
||||||
|
of Knight:
|
||||||
|
# TODO
|
||||||
|
discard
|
||||||
|
of King:
|
||||||
|
# TODO
|
||||||
|
discard
|
||||||
else:
|
else:
|
||||||
return false
|
return false
|
||||||
|
|
||||||
|
@ -610,10 +589,9 @@ proc getAttackers*(self: ChessBoard, square: string): seq[Piece] =
|
||||||
# We don't use getAttackers because this one only cares about whether
|
# We don't use getAttackers because this one only cares about whether
|
||||||
# the square is attacked or not (and can therefore exit earlier than
|
# the square is attacked or not (and can therefore exit earlier than
|
||||||
# getAttackers)
|
# getAttackers)
|
||||||
proc isAttacked*(self: ChessBoard, square: string): bool =
|
proc isAttacked*(self: ChessBoard, loc: Location): bool =
|
||||||
## Returns whether the given square is attacked
|
## Returns whether the given location is attacked
|
||||||
## by one of the enemy pieces
|
## by the current inactive color
|
||||||
let loc = square.algebraicToPosition()
|
|
||||||
case self.turn:
|
case self.turn:
|
||||||
of White:
|
of White:
|
||||||
for (attacker, location) in self.attacked.black:
|
for (attacker, location) in self.attacked.black:
|
||||||
|
@ -629,6 +607,12 @@ proc isAttacked*(self: ChessBoard, square: string): bool =
|
||||||
discard
|
discard
|
||||||
|
|
||||||
|
|
||||||
|
proc isAttacked*(self: ChessBoard, square: string): bool =
|
||||||
|
## Returns whether the given square is attacked
|
||||||
|
## by the current inactive color
|
||||||
|
return self.isAttacked(square.algebraicToPosition())
|
||||||
|
|
||||||
|
|
||||||
proc removePiece(self: ChessBoard, location: Location) =
|
proc removePiece(self: ChessBoard, location: Location) =
|
||||||
## Removes a piece from the board, updating necessary
|
## Removes a piece from the board, updating necessary
|
||||||
## metadata
|
## metadata
|
||||||
|
@ -646,7 +630,7 @@ proc removePiece(self: ChessBoard, location: Location) =
|
||||||
of Rook:
|
of Rook:
|
||||||
self.pieces.white.rooks.delete(self.pieces.white.rooks.find(location))
|
self.pieces.white.rooks.delete(self.pieces.white.rooks.find(location))
|
||||||
of Queen:
|
of Queen:
|
||||||
self.pieces.white.queens.delete(self.pieces.white.rooks.find(location))
|
self.pieces.white.queens.delete(self.pieces.white.queens.find(location))
|
||||||
of King:
|
of King:
|
||||||
doAssert false, "removePiece: attempted to remove the white king"
|
doAssert false, "removePiece: attempted to remove the white king"
|
||||||
else:
|
else:
|
||||||
|
@ -654,15 +638,15 @@ proc removePiece(self: ChessBoard, location: Location) =
|
||||||
of Black:
|
of Black:
|
||||||
case piece.kind:
|
case piece.kind:
|
||||||
of Pawn:
|
of Pawn:
|
||||||
self.pieces.black.pawns.delete(self.pieces.black.pawns.find(location))
|
self.pieces.black.pawns.delete(self.pieces.white.pawns.find(location))
|
||||||
of Bishop:
|
of Bishop:
|
||||||
self.pieces.black.pawns.delete(self.pieces.black.bishops.find(location))
|
self.pieces.black.bishops.delete(self.pieces.black.bishops.find(location))
|
||||||
of Knight:
|
of Knight:
|
||||||
self.pieces.black.pawns.delete(self.pieces.black.knights.find(location))
|
self.pieces.black.knights.delete(self.pieces.black.knights.find(location))
|
||||||
of Rook:
|
of Rook:
|
||||||
self.pieces.black.rooks.delete(self.pieces.black.rooks.find(location))
|
self.pieces.black.rooks.delete(self.pieces.black.rooks.find(location))
|
||||||
of Queen:
|
of Queen:
|
||||||
self.pieces.black.queens.delete(self.pieces.black.rooks.find(location))
|
self.pieces.black.queens.delete(self.pieces.black.queens.find(location))
|
||||||
of King:
|
of King:
|
||||||
doAssert false, "removePiece: attempted to remove the black king"
|
doAssert false, "removePiece: attempted to remove the black king"
|
||||||
else:
|
else:
|
||||||
|
@ -674,13 +658,12 @@ proc removePiece(self: ChessBoard, location: Location) =
|
||||||
proc updatePositions(self: ChessBoard, move: Move) =
|
proc updatePositions(self: ChessBoard, move: Move) =
|
||||||
## Internal helper to update the position of
|
## Internal helper to update the position of
|
||||||
## the pieces on the board after a move
|
## the pieces on the board after a move
|
||||||
|
|
||||||
let capture = self.getCapture(move)
|
let capture = self.getCapture(move)
|
||||||
if capture != emptyLocation():
|
if capture != emptyLocation():
|
||||||
# Move has captured a piece: remove the destination square's piece as well.
|
# Move has captured a piece: remove it as well. We call a helper instead
|
||||||
# We call a helper instead of doing it ourselves because there's a bunch
|
# of doing it ourselves because there's a bunch of metadata that needs
|
||||||
# of metadata that needs to be updated to do this properly and I thought
|
# to be updated to do this properly and I thought it'd fit into its neat
|
||||||
# it'd fit into its neat little function
|
# little function
|
||||||
self.removePiece(capture)
|
self.removePiece(capture)
|
||||||
# Update the positional metadata of the moving piece
|
# Update the positional metadata of the moving piece
|
||||||
case move.piece.color:
|
case move.piece.color:
|
||||||
|
|
|
@ -1,5 +1,22 @@
|
||||||
import board as chess
|
import board as chess
|
||||||
|
import std/strformat
|
||||||
|
import std/strutils
|
||||||
|
|
||||||
var board = newDefaultChessboard()
|
|
||||||
|
|
||||||
|
var
|
||||||
|
board = newChessboardFromFEN("rnbqkbnr/8/8/8/8/8/8/RNBQKBNR w KQkq - 0 1")
|
||||||
|
startSquare: string
|
||||||
|
targetSquare: string
|
||||||
|
move: Move
|
||||||
|
|
||||||
|
while true:
|
||||||
echo board.pretty()
|
echo board.pretty()
|
||||||
|
echo &"Turn: {board.getActiveColor()}"
|
||||||
|
stdout.write("From -> ")
|
||||||
|
startSquare = readLine(stdin).strip(chars={'\0', ' '})
|
||||||
|
stdout.write("To -> ")
|
||||||
|
targetSquare = readLine(stdin)
|
||||||
|
try:
|
||||||
|
move = board.makeMove(startSquare, targetSquare)
|
||||||
|
except ValueError:
|
||||||
|
echo &"Error: {getCurrentExceptionMsg()}"
|
Loading…
Reference in New Issue