chess: improved documentation and deleted unused stuff

master
TiynGER 4 years ago
parent 81d5d57e75
commit c4f7e3b98d

@ -16,3 +16,9 @@ Testing is done by `einheit` by [jyapayne](https://github.com/jyapayne/einheit).
All legal chess moves are implemented in `chess.nim` and tested by the TestSuite All legal chess moves are implemented in `chess.nim` and tested by the TestSuite
in `test.nim`. in `test.nim`.
You can simply run the tests with `nim c -r test.nim`. You can simply run the tests with `nim c -r test.nim`.
## Documentation
Documentation is written into the code via DocGen.
For this reason it is not saved in this repository.
To extract it into html run `nim doc --project --index:on --outdir:htmldocs game.nim`

@ -4,71 +4,87 @@ import algorithm
type type
Color* = enum Color* = enum
Black = -1, White = 1 ## `Color` describes the possible color of players.
## Board that saves the board Black = -1,
Board* = array[0..119, int] White = 1
## Board that checks if pieces moved Board* = array[0..119, int] ## \
Moved* = array[0..119, bool] ## `Board` saves the position of the chess pieces.
## Castle rights for each player Moved* = array[0..119, bool] ## \
## `Moved` saves the position of squares a piece moved on or from.
CastleRights = tuple CastleRights = tuple
wk: bool # `CastleRights` contains the rights to castling for each player.
wq: bool wk: bool # `wk` describes White kingside castle
bk: bool wq: bool # `wq` describes White queenside castle
bq: bool bk: bool # `bk` describes Black kingside castle
## Game as object of different values bq: bool # `bq` describes Black queenside castle
Game* = object Game* = object
## `Game` stores all important information of a chess game.
board*: Board board*: Board
moved: Moved moved: Moved
toMove*: Color toMove*: Color
previousBoard: seq[Board] previousBoard: seq[Board]
previousCastleRights: seq[CastleRights] previousCastleRights: seq[CastleRights]
fiftyMoveCounter: int fiftyMoveCounter: int
## Move as object
Move* = object Move* = object
## `Move` stores all important information for a move.
start: int start: int
dest: int dest: int
color: Color color: Color
prom: int prom: int
## Amount of pieces of a player PieceAmount = tuple
Pieces = tuple # `PieceAmount` describes the number of pieces of a certain type a/both
p: int # player/s has/have.
k: int p: int # `p` describes the amount of pawns.
b: int n: int # `n` describes the amount of knights.
r: int b: int # `b` describes the amount of bishops.
q: int r: int # `r` describes the amount of rooks.
q: int # `q` describes the amount of queens.
const const
# IDs for piece Block* = 999 ## \
BlockID* = 999 ## `Block` is the value assigned to empty blocked fields in a board.
PawnID* = 1 WPawn* = 1
KnightID* = 2 ## `WPawn` is the value assigned to a square in a board with a white pawn.
BishopID* = 3 WKnight* = 2 ## \
RookID* = 4 ## `WKnight` is the value assigned to a square in a board with a white
QueenID* = 5 ## knight.
KingID* = 6 WBishop* = 3 ## \
EnPassantID* = 7 ## `WBishop` is the value assigned to a square in a board with a white
# IDs that are saved in the array ## bishop.
Block* = BlockID WRook* = 4 ## \
WPawn* = PawnID ## `WRook` is the value assigned to a square in a board with a white rook.
WKnight* = KnightID WQueen* = 5 ## \
WBishop* = BishopID ## `WQueen` is the value assigned to a square in a board with a white
WRook* = RookID ## queen.
WQueen* = QueenID WKing* = 6 ## \
WKing* = KingID ## `WKing` is the value assigned to a square in a board with a white king.
WEnPassant* = EnPassantID WEnPassant* = 7 ## \
BPawn* = -PawnID ## `WEnPassant` is assigned to a square in a board with an invisible white
BKnight* = -KnightID ## en passant pawn.
BBishop* = -BishopID BPawn* = -WPawn ## \
BRook* = -RookID ## `BPawn` is the value assigned to a square in a board with a black pawn.
BQueen* = -QueenID BKnight* = -WKnight ## \
BKing* = -KingID ## `BKnight` is the value assigned to a square in a board with a black\
BEnPassant* = EnPassantID ## knight.
# Directions of movement BBishop* = -WBishop ## \
N = 10 ## `BBishop` is the value assigned to a square in a board with a black\
S = -N ## bishop.
W = 1 BRook* = -WRook ## \
E = -W ## `BRook` is the value assigned to a square in a board with a black rook.
# Movement options for pieces (Bishop/Rook/Queen can repeat in the same direction) BQueen* = -WQueen ## \
## `BQueen` is the value assigned to a square in a board with a black queen.
BKing* = -WKing ## \
## `BKing` is the value assigned to a square in a board with a black king.
BEnPassant* = -WEnPassant ## \
## `BEnPassant` is assigned to a square in a board with an invisible black
## en passant pawn.
# Directions of squares from whites perspective.
N = 10 # move up
S = -N # Move down
W = 1 # Move left
E = -W # Move right
# Directions for the pieces. Special moves are in separate arrays.
Knight_Moves = [N+N+E, N+N+W, E+E+N, E+E+S, S+S+E, S+S+W, W+W+N, W+W+S] Knight_Moves = [N+N+E, N+N+W, E+E+N, E+E+S, S+S+E, S+S+W, W+W+N, W+W+S]
Bishop_Moves = [N+E, N+W, S+E, S+W] Bishop_Moves = [N+E, N+W, S+E, S+W]
Rook_Moves = [N, E, S, W] Rook_Moves = [N, E, S, W]
@ -78,27 +94,36 @@ const
Pawn_Moves_White = [N] Pawn_Moves_White = [N]
Pawn_Moves_White_Double = [N+N] Pawn_Moves_White_Double = [N+N]
Pawn_Moves_White_Attack = [N+E, N+W] Pawn_Moves_White_Attack = [N+E, N+W]
# Material as PieceAmount where a forced checkmate is not possible.
InsufficientMaterial: array[4,PieceAmount] = [
(0, 0, 0, 0, 0), # only kings
(0, 0, 1, 0, 0), # knight only
(0, 1, 0, 0, 0), # bishop only
(0, 2, 0, 0, 0) # 2 knights
]
let PieceChar = { let
# Representation of the pieces by ID.
PieceChar = {
0: " ", 0: " ",
1: "P", WPawn: "P",
2: "N", WKnight: "N",
3: "B", WBishop: "B",
4: "R", WRook: "R",
5: "Q", WQueen: "Q",
6: "K", WKing: "K",
7: " ", WEnPassant: " ",
-1: "p", BPawn: "p",
-2: "n", BKnight: "n",
-3: "b", BBishop: "b",
-4: "r", BRook: "r",
-5: "q", BQueen: "q",
-6: "k", BKing: "k",
-7: " ", BEnPassant: " ",
999: "-"
}.newTable }.newTable
# Files on the chess board mapped to according integers.
let FileChar = { FileChar = {
"a": 7, "a": 7,
"b": 6, "b": 6,
"c": 5, "c": 5,
@ -109,18 +134,6 @@ let FileChar = {
"h": 0 "h": 0
}.newTable }.newTable
const InsufficientMaterial = @[
#p, n, b, r, q
# lone kings
(0, 0, 0, 0, 0),
# knight only
(0, 0, 1, 0, 0),
# bishop only
(0, 1, 0, 0, 0),
# 2 knights
(0, 2, 0, 0, 0)
]
proc setField(board: var Board, field: int, val: int): bool {.discardable.} = proc setField(board: var Board, field: int, val: int): bool {.discardable.} =
try: try:
if (val in PieceChar): if (val in PieceChar):
@ -173,8 +186,8 @@ proc checkInsufficientMaterial(board: Board): bool =
bq = bq + 1 bq = bq + 1
else: else:
continue continue
let wpieces = (wp, wn, wb, wr, wq) let wpieces: PieceAmount = (wp, wn, wb, wr, wq)
let bpieces = (bp, bn, bb, br, bq) let bpieces: PieceAmount = (bp, bn, bb, br, bq)
return (wpieces in InsufficientMaterial) and (bpieces in InsufficientMaterial) return (wpieces in InsufficientMaterial) and (bpieces in InsufficientMaterial)
proc initBoard(): Board = proc initBoard(): Board =
@ -227,7 +240,8 @@ proc initMoved(): Moved =
proc initGame*(): Game = proc initGame*(): Game =
## Create and return a Game object. ## Create and return a Game object.
let game = Game(board: initBoard(), moved: initMoved(), let game = Game(board: initBoard(), moved: initMoved(),
to_move: Color.White, previousBoard: @[], previousCastleRights: @[], fiftyMoveCounter: 0) to_move: Color.White, previousBoard: @[], previousCastleRights: @[],
fiftyMoveCounter: 0)
return game return game
proc initGame*(board: array[0..63, int], color: Color): Game = proc initGame*(board: array[0..63, int], color: Color): Game =
@ -240,19 +254,20 @@ proc initGame*(board: array[0..63, int], color: Color): Game =
same_piece = (board[ind] != compare[ind]) same_piece = (board[ind] != compare[ind])
moved.setField(ind, same_piece) moved.setField(ind, same_piece)
let game = Game(board: board, moved: moved, let game = Game(board: board, moved: moved,
to_move: color, previousBoard: @[], previousCastleRights: @[], fiftyMoveCounter: 0) to_move: color, previousBoard: @[], previousCastleRights: @[],
fiftyMoveCounter: 0)
return game return game
proc getMove*(start: int, dest: int, prom: int, color: Color): Move = proc getMove*(start: int, dest: int, prom: int, color: Color): Move =
## Get a move object from `start` to `dest` with an eventual promition to `prom` ## Get a move object from `start` to `dest` with an eventual promition to `prom`
var move = Move(start: start, dest: dest, prom: prom * ord(color), color: color) var move = Move(start: start, dest: dest, prom: prom * ord(color), color: color)
if (KnightID > prom or QueenID < prom): if (WKnight > prom or WQueen < prom):
move.prom = QueenID move.prom = WQueen
return move return move
proc getMove*(start: int, dest: int, color: Color): Move = proc getMove*(start: int, dest: int, color: Color): Move =
## Get a move object from `start` to `dest` with automatic promition to `queen` ## Get a move object from `start` to `dest` with automatic promition to `queen`
var move = Move(start: start, dest: dest, prom: QueenID * ord(color), color: color) var move = Move(start: start, dest: dest, prom: WQueen * ord(color), color: color)
return move return move
proc echoBoard*(game: Game, color: Color) = proc echoBoard*(game: Game, color: Color) =
@ -319,13 +334,13 @@ proc notationToMove*(notation: string, color: Color): Move =
var prom: int var prom: int
case promStr: case promStr:
of "Q": of "Q":
prom = QueenID * ord(color) prom = WQueen * ord(color)
of "R": of "R":
prom = RookID * ord(color) prom = WRook * ord(color)
of "B": of "B":
prom = BishopID * ord(color) prom = WBishop * ord(color)
of "N": of "N":
prom = KnightID * ord(color) prom = WKnight * ord(color)
move = getMove(start, dest, prom, color) move = getMove(start, dest, prom, color)
return move return move
except IndexError: except IndexError:
@ -343,9 +358,9 @@ proc genBishopDests(game: Game, field: int, color: Color): seq[int] =
dest = field+move dest = field+move
target = game.board[dest] target = game.board[dest]
while (target != 999 and (ord(color) * target <= 0) or target == while (target != 999 and (ord(color) * target <= 0) or target ==
EnPassantID or target == -EnPassantID): WEnPassant or target == -WEnPassant):
res.add(dest) res.add(dest)
if (ord(color) * target < 0 and ord(color) * target > -EnPassantID): if (ord(color) * target < 0 and ord(color) * target > -WEnPassant):
break break
dest = dest+move dest = dest+move
target = game.board[dest] target = game.board[dest]
@ -364,9 +379,9 @@ proc genRookDests(game: Game, field: int, color: Color): seq[int] =
dest = field+move dest = field+move
target = game.board[dest] target = game.board[dest]
while (target != 999 and (ord(color) * target <= 0) or target == while (target != 999 and (ord(color) * target <= 0) or target ==
EnPassantID or target == -EnPassantID): WEnPassant or target == -WEnPassant):
res.add(dest) res.add(dest)
if (ord(color) * target < 0 and ord(color) * target > -EnPassantID): if (ord(color) * target < 0 and ord(color) * target > -WEnPassant):
break break
dest = dest+move dest = dest+move
target = game.board[dest] target = game.board[dest]
@ -385,9 +400,9 @@ proc genQueenDests(game: Game, field: int, color: Color): seq[int] =
dest = field+move dest = field+move
target = game.board[dest] target = game.board[dest]
while (target != 999 and (ord(color) * target <= 0) or target == while (target != 999 and (ord(color) * target <= 0) or target ==
EnPassantID or target == -EnPassantID): WEnPassant or target == -WEnPassant):
res.add(dest) res.add(dest)
if (ord(color) * target < 0 and ord(color) * target > -EnPassantID): if (ord(color) * target < 0 and ord(color) * target > -WEnPassant):
break break
dest = dest+move dest = dest+move
target = game.board[dest] target = game.board[dest]
@ -429,7 +444,7 @@ proc genKingDests(game: Game, field: int, color: Color): seq[int] =
for move in King_Moves: for move in King_Moves:
dest = field + move dest = field + move
target = game.board[dest] target = game.board[dest]
if (target == 999 or (ord(color) * target > 0 and ord(color) * target != EnPassantID)): if (target == 999 or (ord(color) * target > 0 and ord(color) * target != WEnPassant)):
continue continue
res.add(dest) res.add(dest)
res.add(game.genKingCastleDest(field, color)) res.add(game.genKingCastleDest(field, color))
@ -447,7 +462,7 @@ proc genKnightDests(game: Game, field: int, color: Color): seq[int] =
for move in Knight_Moves: for move in Knight_Moves:
dest = field + move dest = field + move
target = game.board[dest] target = game.board[dest]
if (target == 999 or (ord(color) * target > 0 and ord(color) * target != EnPassantID)): if (target == 999 or (ord(color) * target > 0 and ord(color) * target != WEnPassant)):
continue continue
res.add(dest) res.add(dest)
return res return res
@ -499,7 +514,7 @@ proc genPawnDests(game: Game, field: int, color: Color): seq[int] =
for move in Pawn_Moves_White: for move in Pawn_Moves_White:
dest = field + move * ord(color) dest = field + move * ord(color)
target = game.board[dest] target = game.board[dest]
if (target != 0 and target != ord(color) * EnPassantID): if (target != 0 and target != ord(color) * WEnPassant):
continue continue
res.add(dest) res.add(dest)
res.add(game.genPawnAttackDests(field, color)) res.add(game.genPawnAttackDests(field, color))
@ -520,24 +535,24 @@ proc isAttacked(game: Game, position: int, color: Color): bool =
## Check if a field is attacked by the opposite of `color` in a `game`. ## Check if a field is attacked by the opposite of `color` in a `game`.
var attacked = false var attacked = false
attacked = attacked or game.pieceOn(color, game.genPawnAttackDests( attacked = attacked or game.pieceOn(color, game.genPawnAttackDests(
position, color), PawnID) position, color), WPawn)
attacked = attacked or game.pieceOn(color, game.genQueenDests(position, attacked = attacked or game.pieceOn(color, game.genQueenDests(position,
color), QueenID) color), WQueen)
attacked = attacked or game.pieceOn(color, game.genKingDests(position, attacked = attacked or game.pieceOn(color, game.genKingDests(position,
color), KingID) color), WKing)
attacked = attacked or game.pieceOn(color, game.genRookDests(position, attacked = attacked or game.pieceOn(color, game.genRookDests(position,
color), RookID) color), WRook)
attacked = attacked or game.pieceOn(color, game.genBishopDests(position, attacked = attacked or game.pieceOn(color, game.genBishopDests(position,
color), BishopID) color), WBishop)
attacked = attacked or game.pieceOn(color, game.genKnightDests(position, attacked = attacked or game.pieceOn(color, game.genKnightDests(position,
color), KnightID) color), WKnight)
return attacked return attacked
proc isInCheck*(game: Game, color: Color): bool = proc isInCheck*(game: Game, color: Color): bool =
## Check if the King of a given `color` is in check in a `game`. ## Check if the King of a given `color` is in check in a `game`.
var king_pos: int var king_pos: int
for i in countup(0, game.board.high): for i in countup(0, game.board.high):
if game.board[i] == ord(color) * KingID: if game.board[i] == ord(color) * WKing:
king_pos = i king_pos = i
return game.isAttacked(king_pos, color) return game.isAttacked(king_pos, color)
@ -567,12 +582,12 @@ proc moveLeadsToCheck(game: Game, start: int, dest: int,
proc removeEnPassant(board: var Board, color: Color): void = proc removeEnPassant(board: var Board, color: Color): void =
## Removes every en passant of given `color` from the `game`. ## Removes every en passant of given `color` from the `game`.
for field in board.low..board.high: for field in board.low..board.high:
if board[field] == ord(color) * EnPassantID: if board[field] == ord(color) * WEnPassant:
board.setField(field, 0) board.setField(field, 0)
proc genLegalKnightMoves(game: Game, field: int, color: Color): seq[Move] = proc genLegalKnightMoves(game: Game, field: int, color: Color): seq[Move] =
## Generates all legal knight moves starting from `field` in a `game` for a `color`. ## Generates all legal knight moves starting from `field` in a `game` for a `color`.
if game.board[field] != KnightID * ord(color): if game.board[field] != WKnight * ord(color):
return @[] return @[]
var res = newSeq[Move]() var res = newSeq[Move]()
var moves = game.genKnightDests(field, color) var moves = game.genKnightDests(field, color)
@ -583,7 +598,7 @@ proc genLegalKnightMoves(game: Game, field: int, color: Color): seq[Move] =
proc genLegalBishopMoves(game: Game, field: int, color: Color): seq[Move] = proc genLegalBishopMoves(game: Game, field: int, color: Color): seq[Move] =
## Generates all legal bishop moves starting from `field` in a `game` for a `color`. ## Generates all legal bishop moves starting from `field` in a `game` for a `color`.
if game.board[field] != BishopID * ord(color): if game.board[field] != WBishop * ord(color):
return @[] return @[]
var res = newSeq[Move]() var res = newSeq[Move]()
var moves = game.genBishopDests(field, color) var moves = game.genBishopDests(field, color)
@ -594,7 +609,7 @@ proc genLegalBishopMoves(game: Game, field: int, color: Color): seq[Move] =
proc genLegalRookMoves(game: Game, field: int, color: Color): seq[Move] = proc genLegalRookMoves(game: Game, field: int, color: Color): seq[Move] =
## Generates all legal rook moves starting from `field` in a `game` for a `color`. ## Generates all legal rook moves starting from `field` in a `game` for a `color`.
if game.board[field] != RookID * ord(color): if game.board[field] != WRook * ord(color):
return @[] return @[]
var res = newSeq[Move]() var res = newSeq[Move]()
var moves = game.genRookDests(field, color) var moves = game.genRookDests(field, color)
@ -605,7 +620,7 @@ proc genLegalRookMoves(game: Game, field: int, color: Color): seq[Move] =
proc genLegalQueenMoves(game: Game, field: int, color: Color): seq[Move] = proc genLegalQueenMoves(game: Game, field: int, color: Color): seq[Move] =
## Generates all legal queen moves starting from `field` in a `game` for a `color`. ## Generates all legal queen moves starting from `field` in a `game` for a `color`.
if game.board[field] != QueenID * ord(color): if game.board[field] != WQueen * ord(color):
return @[] return @[]
var res = newSeq[Move]() var res = newSeq[Move]()
var moves = game.genQueenDests(field, color) var moves = game.genQueenDests(field, color)
@ -616,7 +631,7 @@ proc genLegalQueenMoves(game: Game, field: int, color: Color): seq[Move] =
proc genLegalKingMoves(game: Game, field: int, color: Color): seq[Move] = proc genLegalKingMoves(game: Game, field: int, color: Color): seq[Move] =
## Generates all legal king moves starting from `field` in a `game` for a `color`. ## Generates all legal king moves starting from `field` in a `game` for a `color`.
if game.board[field] != KingID * ord(color): if game.board[field] != WKing * ord(color):
return @[] return @[]
var res = newSeq[Move]() var res = newSeq[Move]()
var moves = game.genKingDests(field, color) var moves = game.genKingDests(field, color)
@ -635,13 +650,13 @@ proc genPawnPromotion(move: Move, color: Color): seq[Move] =
let start = move.start let start = move.start
let dest = move.dest let dest = move.dest
if (90 < dest and dest < 99) or (20 < dest and dest < 29): if (90 < dest and dest < 99) or (20 < dest and dest < 29):
for piece in KnightID..QueenID: for piece in WKnight..WQueen:
promotions.add(getMove(start, dest, piece, color)) promotions.add(getMove(start, dest, piece, color))
return promotions return promotions
proc genLegalPawnMoves(game: Game, field: int, color: Color): seq[Move] = proc genLegalPawnMoves(game: Game, field: int, color: Color): seq[Move] =
## Generates all legal pawn moves starting from `field` in a `game` for a `color`. ## Generates all legal pawn moves starting from `field` in a `game` for a `color`.
if game.board[field] != PawnID * ord(color): if game.board[field] != WPawn * ord(color):
return @[] return @[]
var res = newSeq[Move]() var res = newSeq[Move]()
var moves = game.genPawnDests(field, color) var moves = game.genPawnDests(field, color)
@ -658,19 +673,19 @@ proc genLegalMoves*(game: Game, field: int, color: Color): seq[Move] =
## Generates all legal moves starting from `field` in a `game` for a `color`. ## Generates all legal moves starting from `field` in a `game` for a `color`.
var legal_moves = newSeq[Move]() var legal_moves = newSeq[Move]()
var target = ord(color) * game.board[field] var target = ord(color) * game.board[field]
if 0 < target and target < EnPassantID: if 0 < target and target < WEnPassant:
legal_moves = case target: legal_moves = case target:
of PawnID: of WPawn:
game.genLegalPawnMoves(field, color) game.genLegalPawnMoves(field, color)
of KnightID: of WKnight:
game.genLegalKnightMoves(field, color) game.genLegalKnightMoves(field, color)
of BishopID: of WBishop:
game.genLegalBishopMoves(field, color) game.genLegalBishopMoves(field, color)
of RookID: of WRook:
game.genLegalRookMoves(field, color) game.genLegalRookMoves(field, color)
of QueenID: of WQueen:
game.genLegalQueenMoves(field, color) game.genLegalQueenMoves(field, color)
of KingID: of WKing:
game.genLegalKingMoves(field, color) game.genLegalKingMoves(field, color)
else: else:
@[] @[]
@ -742,28 +757,28 @@ proc checkedMove*(game: var Game, move: Move): bool {.discardable.} =
var fiftyMoveRuleReset = false var fiftyMoveRuleReset = false
var move: Move var move: Move
move = getMove(start, dest, color) move = getMove(start, dest, color)
if (piece == PawnID * ord(color)): if (piece == WPawn * ord(color)):
createEnPassant = dest in game.genPawnDoubleDests(start, color) createEnPassant = dest in game.genPawnDoubleDests(start, color)
capturedEnPassant = (game.board[dest] == -1 * ord(color) * EnPassantID) capturedEnPassant = (game.board[dest] == -1 * ord(color) * WEnPassant)
fiftyMoveRuleReset = true fiftyMoveRuleReset = true
if (game.board[move.dest] != 0): if (game.board[move.dest] != 0):
fiftyMoveRuleReset = true fiftyMoveRuleReset = true
sequence.add(game.genLegalMoves(start, color)) sequence.add(game.genLegalMoves(start, color))
if (move in sequence): if (move in sequence):
game.board.removeEnPassant(color) game.board.removeEnPassant(color)
if (piece == KingID * ord(color) and (start - dest == (W+W))): if (piece == WKing * ord(color) and (start - dest == (W+W))):
return game.castling(start, true, color) return game.castling(start, true, color)
elif (piece == KingID * ord(color) and (start - dest == (E+E))): elif (piece == WKing * ord(color) and (start - dest == (E+E))):
return game.castling(start, false, color) return game.castling(start, false, color)
else: else:
game.uncheckedMove(start, dest) game.uncheckedMove(start, dest)
game.toMove = Color(ord(game.toMove)*(-1)) game.toMove = Color(ord(game.toMove)*(-1))
if createEnPassant: if createEnPassant:
game.board.setField(dest-(N*ord(color)), EnPassantID * ord(color)) game.board.setField(dest-(N*ord(color)), WEnPassant * ord(color))
if capturedEnPassant: if capturedEnPassant:
game.board.setField(dest-(N*ord(color)), 0) game.board.setField(dest-(N*ord(color)), 0)
if ((90 < dest and dest < 99) or (20 < dest and dest < 29)) and if ((90 < dest and dest < 99) or (20 < dest and dest < 29)) and
game.board[dest] == PawnID * ord(color): game.board[dest] == WPawn * ord(color):
game.board.setField(dest, prom) game.board.setField(dest, prom)
var prevBoard = game.previousBoard var prevBoard = game.previousBoard
var prevCastle = game.previousCastleRights var prevCastle = game.previousCastleRights

Loading…
Cancel
Save