Refactored piece location storage and added test for it
This commit is contained in:
parent
9af32e5e40
commit
d3cc7bddde
|
@ -21,15 +21,15 @@ import std/strformat
|
|||
|
||||
type
|
||||
Location = tuple[row, col: int]
|
||||
Pieces = tuple[king: Location, queen: Location, rooks: array[2, Location],
|
||||
bishops: array[2, Location], knights: array[2, Location],
|
||||
pawns: array[8, Location]]
|
||||
Pieces = tuple[king: Location, queen: Location, rooks: seq[Location],
|
||||
bishops: seq[Location], knights: seq[Location],
|
||||
pawns: seq[Location]]
|
||||
PieceColor* = enum
|
||||
None = 0,
|
||||
White,
|
||||
Black
|
||||
PieceKind* = enum
|
||||
Empty = 0, # No piece
|
||||
Empty = '\0', # No piece
|
||||
Bishop = 'b',
|
||||
King = 'k'
|
||||
Knight = 'n',
|
||||
|
@ -39,12 +39,13 @@ type
|
|||
Piece* = object
|
||||
color*: PieceColor
|
||||
kind*: PieceKind
|
||||
captured*: bool
|
||||
Position* = object
|
||||
piece*: Piece
|
||||
location*: Location
|
||||
ChessBoard* = ref object
|
||||
## A chess board object
|
||||
grid*: Matrix[Piece]
|
||||
grid: Matrix[Piece]
|
||||
# Currently active color
|
||||
turn: PieceColor
|
||||
# Number of half moves since
|
||||
|
@ -72,6 +73,53 @@ for _ in countup(0, 63):
|
|||
empty.add(Piece(kind: Empty, color: None))
|
||||
|
||||
|
||||
proc countPieces*(self: ChessBoard, kind: PieceKind, color: PieceColor): int =
|
||||
## Counts the number of pieces with
|
||||
## the given color and type
|
||||
case color:
|
||||
of White:
|
||||
case kind:
|
||||
of Pawn:
|
||||
return self.pieces.white.pawns.len()
|
||||
of Bishop:
|
||||
return self.pieces.white.bishops.len()
|
||||
of Knight:
|
||||
return self.pieces.white.knights.len()
|
||||
of Rook:
|
||||
return self.pieces.white.rooks.len()
|
||||
of Queen:
|
||||
return int(self.pieces.white.queen != (-1, -1))
|
||||
of King:
|
||||
# There shall be only one, forever
|
||||
return 1
|
||||
else:
|
||||
discard
|
||||
of Black:
|
||||
case kind:
|
||||
of Pawn:
|
||||
return self.pieces.black.pawns.len()
|
||||
of Bishop:
|
||||
return self.pieces.black.bishops.len()
|
||||
of Knight:
|
||||
return self.pieces.black.knights.len()
|
||||
of Rook:
|
||||
return self.pieces.black.rooks.len()
|
||||
of Queen:
|
||||
return int(self.pieces.black.queen != (-1, -1))
|
||||
of King:
|
||||
return 1
|
||||
else:
|
||||
discard
|
||||
of None:
|
||||
raise newException(ValueError, "invalid piece type")
|
||||
|
||||
|
||||
proc countPieces*(self: ChessBoard, piece: Piece): int =
|
||||
## Returns the number of pieces on the board that
|
||||
## are of the same type and color of the given piece
|
||||
return self.countPieces(piece.kind, piece.color)
|
||||
|
||||
|
||||
func rankToColumn(rank: int): int =
|
||||
## Converts a chess rank (1-indexed)
|
||||
## into a 0-indexed column value for our
|
||||
|
@ -110,7 +158,6 @@ proc getPiece*(self: ChessBoard, square: string): Piece =
|
|||
|
||||
proc `$`*(self: ChessBoard): string =
|
||||
result &= "- - - - - - - -"
|
||||
#const indeces = [7, 6, 5, 4, 3, 2, 1, 0]
|
||||
for i, row in self.grid:
|
||||
result &= "\n"
|
||||
for piece in row:
|
||||
|
@ -129,20 +176,6 @@ proc `$`*(self: ChessBoard): string =
|
|||
proc newChessboard: ChessBoard =
|
||||
## Returns a new, empty chessboard
|
||||
new(result)
|
||||
# Initialize all positions to a known default state.
|
||||
# This is useful in newChessBoardFromFEN
|
||||
result.pieces.black.king = (-1, -1)
|
||||
result.pieces.white.king = (-1, -1)
|
||||
result.pieces.black.queen = (-1, -1)
|
||||
result.pieces.white.queen = (-1, -1)
|
||||
result.pieces.black.rooks = [(-1, -1), (-1, -1)]
|
||||
result.pieces.white.rooks = [(-1, -1), (-1, -1)]
|
||||
result.pieces.black.bishops = [(-1, -1), (-1, -1)]
|
||||
result.pieces.white.bishops = [(-1, -1), (-1, -1)]
|
||||
result.pieces.black.knights = [(-1, -1), (-1, -1)]
|
||||
result.pieces.white.knights = [(-1, -1), (-1, -1)]
|
||||
result.pieces.black.pawns = [(-1, -1), (-1, -1), (-1, -1), (-1, -1), (-1, -1), (-1, -1), (-1, -1), (-1, -1)]
|
||||
result.pieces.white.pawns = [(-1, -1), (-1, -1), (-1, -1), (-1, -1), (-1, -1), (-1, -1), (-1, -1), (-1, -1)]
|
||||
# Turns our flat sequence into an 8x8 grid
|
||||
result.grid = newMatrixFromSeq[Piece](empty, (8, 8))
|
||||
result.attacked = (@[], @[])
|
||||
|
@ -187,26 +220,13 @@ proc newChessboardFromFEN*(state: string): ChessBoard =
|
|||
of Black:
|
||||
case piece.kind:
|
||||
of Pawn:
|
||||
# Find first empty slot in the pieces array
|
||||
for i, e in result.pieces.black.pawns:
|
||||
if e == (-1, -1):
|
||||
result.pieces.black.pawns[i] = (row, column)
|
||||
break
|
||||
result.pieces.black.pawns.add((row, column))
|
||||
of Bishop:
|
||||
if result.pieces.black.bishops[0] == (-1, -1):
|
||||
result.pieces.black.bishops[0] = (row, column)
|
||||
else:
|
||||
result.pieces.black.bishops[1] = (row, column)
|
||||
result.pieces.black.bishops.add((row, column))
|
||||
of Knight:
|
||||
if result.pieces.black.knights[0] == (-1, -1):
|
||||
result.pieces.black.knights[0] = (row, column)
|
||||
else:
|
||||
result.pieces.black.knights[1] = (row, column)
|
||||
result.pieces.black.knights.add((row, column))
|
||||
of Rook:
|
||||
if result.pieces.black.rooks[0] == (-1, -1):
|
||||
result.pieces.black.rooks[0] = (row, column)
|
||||
else:
|
||||
result.pieces.black.rooks[1] = (row, column)
|
||||
result.pieces.black.rooks.add((row, column))
|
||||
of Queen:
|
||||
result.pieces.black.queen = (row, column)
|
||||
of King:
|
||||
|
@ -216,25 +236,13 @@ proc newChessboardFromFEN*(state: string): ChessBoard =
|
|||
of White:
|
||||
case piece.kind:
|
||||
of Pawn:
|
||||
for i, e in result.pieces.white.pawns:
|
||||
if e == (-1, -1):
|
||||
result.pieces.white.pawns[i] = (row, column)
|
||||
break
|
||||
result.pieces.white.pawns.add((row, column))
|
||||
of Bishop:
|
||||
if result.pieces.white.bishops[0] == (-1, -1):
|
||||
result.pieces.white.bishops[0] = (row, column)
|
||||
else:
|
||||
result.pieces.white.bishops[1] = (row, column)
|
||||
result.pieces.white.bishops.add((row, column))
|
||||
of Knight:
|
||||
if result.pieces.white.knights[0] == (-1, -1):
|
||||
result.pieces.white.knights[0] = (row, column)
|
||||
else:
|
||||
result.pieces.white.knights[1] = (row, column)
|
||||
result.pieces.white.knights.add((row, column))
|
||||
of Rook:
|
||||
if result.pieces.white.rooks[0] == (-1, -1):
|
||||
result.pieces.white.rooks[0] = (row, column)
|
||||
else:
|
||||
result.pieces.white.rooks[1] = (row, column)
|
||||
result.pieces.white.rooks.add((row, column))
|
||||
of Queen:
|
||||
result.pieces.white.queen = (row, column)
|
||||
of King:
|
||||
|
@ -330,9 +338,30 @@ when isMainModule:
|
|||
proc testPiece(piece: Piece, kind: PieceKind, color: PieceColor) =
|
||||
doAssert piece.kind == kind and piece.color == color, &"expected piece of kind {kind} and color {color}, got {piece.kind} / {piece.color} instead"
|
||||
|
||||
proc testPieceCount(board: ChessBoard, kind: PieceKind, color: PieceColor, count: int) =
|
||||
let pieces = board.countPieces(kind, color)
|
||||
doAssert pieces == count, &"expected {count} pieces of kind {kind} and color {color}, got {pieces} instead"
|
||||
|
||||
echo "Running tests"
|
||||
var b = newDefaultChessboard()
|
||||
# Ensure pawns are in the correct location
|
||||
# Ensure correct number of pieces
|
||||
testPieceCount(b, Pawn, White, 8)
|
||||
testPieceCount(b, Pawn, Black, 8)
|
||||
testPieceCount(b, Knight, White, 2)
|
||||
testPieceCount(b, Knight, Black, 2)
|
||||
testPieceCount(b, Bishop, White, 2)
|
||||
testPieceCount(b, Bishop, Black, 2)
|
||||
testPieceCount(b, Rook, White, 2)
|
||||
testPieceCount(b, Rook, Black, 2)
|
||||
testPieceCount(b, Queen, White, 1)
|
||||
testPieceCount(b, Queen, Black, 1)
|
||||
testPieceCount(b, King, White, 1)
|
||||
testPieceCount(b, King, Black, 1)
|
||||
|
||||
|
||||
# Ensure pieces are in the correct location
|
||||
|
||||
# Pawns
|
||||
for loc in ["a2", "b2", "c2", "d2", "e2", "f2", "g2", "h2"]:
|
||||
testPiece(b.getPiece(loc), Pawn, White)
|
||||
for loc in ["a7", "b7", "c7", "d7", "e7", "f7", "g7", "h7"]:
|
||||
|
|
Loading…
Reference in New Issue