Minor refactoring and cleanup. Switch away from boehm GC as that's too slow
This commit is contained in:
parent
b865ece113
commit
e6dd6fcf4c
|
@ -3,7 +3,4 @@
|
||||||
-d:danger
|
-d:danger
|
||||||
--passL:"-flto"
|
--passL:"-flto"
|
||||||
--passC:"-flto -march=native -mtune=native"
|
--passC:"-flto -march=native -mtune=native"
|
||||||
--mm:boehm
|
--mm:atomicArc
|
||||||
--stackTrace
|
|
||||||
--lineTrace
|
|
||||||
--debugger:native
|
|
||||||
|
|
|
@ -32,7 +32,7 @@ export pieces, position, bitboards, moves, magics, rays, zobrist
|
||||||
|
|
||||||
|
|
||||||
type
|
type
|
||||||
Chessboard* = ref object
|
Chessboard* = object
|
||||||
## A chessboard
|
## A chessboard
|
||||||
|
|
||||||
# The actual board where pieces live
|
# The actual board where pieces live
|
||||||
|
@ -45,13 +45,12 @@ type
|
||||||
|
|
||||||
# A bunch of simple utility functions and forward declarations
|
# A bunch of simple utility functions and forward declarations
|
||||||
proc toFEN*(self: Chessboard): string
|
proc toFEN*(self: Chessboard): string
|
||||||
proc updateChecksAndPins*(self: Chessboard)
|
proc updateChecksAndPins*(self: var Chessboard)
|
||||||
proc hash*(self: Chessboard)
|
proc hash*(self: var Chessboard)
|
||||||
|
|
||||||
|
|
||||||
proc newChessboard*: Chessboard =
|
proc newChessboard*: Chessboard =
|
||||||
## Returns a new, empty chessboard
|
## Returns a new, empty chessboard
|
||||||
new(result)
|
|
||||||
for i in 0..63:
|
for i in 0..63:
|
||||||
result.grid[i] = nullPiece()
|
result.grid[i] = nullPiece()
|
||||||
result.position = Position(enPassantSquare: nullSquare(), sideToMove: White)
|
result.position = Position(enPassantSquare: nullSquare(), sideToMove: White)
|
||||||
|
@ -102,7 +101,7 @@ proc newChessboardFromFEN*(fen: string): Chessboard =
|
||||||
of 'r', 'n', 'b', 'q', 'k', 'p':
|
of 'r', 'n', 'b', 'q', 'k', 'p':
|
||||||
let square = makeSquare(row, column)
|
let square = makeSquare(row, column)
|
||||||
piece = c.fromChar()
|
piece = c.fromChar()
|
||||||
result.position.pieces[piece.color][piece.kind][].setBit(square)
|
result.position.pieces[piece.color][piece.kind].setBit(square)
|
||||||
result.grid[square] = piece
|
result.grid[square] = piece
|
||||||
inc(column)
|
inc(column)
|
||||||
of '/':
|
of '/':
|
||||||
|
@ -133,13 +132,13 @@ proc newChessboardFromFEN*(fen: string): Chessboard =
|
||||||
of '-':
|
of '-':
|
||||||
discard
|
discard
|
||||||
of 'K':
|
of 'K':
|
||||||
result.position.castlingAvailability[White.int].king = true
|
result.position.castlingAvailability[White].king = true
|
||||||
of 'Q':
|
of 'Q':
|
||||||
result.position.castlingAvailability[White.int].queen = true
|
result.position.castlingAvailability[White].queen = true
|
||||||
of 'k':
|
of 'k':
|
||||||
result.position.castlingAvailability[Black.int].king = true
|
result.position.castlingAvailability[Black].king = true
|
||||||
of 'q':
|
of 'q':
|
||||||
result.position.castlingAvailability[Black.int].queen = true
|
result.position.castlingAvailability[Black].queen = true
|
||||||
else:
|
else:
|
||||||
raise newException(ValueError, &"invalid FEN: unknown symbol '{c}' found in castlingRights availability section")
|
raise newException(ValueError, &"invalid FEN: unknown symbol '{c}' found in castlingRights availability section")
|
||||||
of 3:
|
of 3:
|
||||||
|
@ -186,7 +185,7 @@ func countPieces*(self: Chessboard, kind: PieceKind, color: PieceColor): int {.i
|
||||||
## Returns the number of pieces with
|
## Returns the number of pieces with
|
||||||
## the given color and type in the
|
## the given color and type in the
|
||||||
## current position
|
## current position
|
||||||
return self.position.pieces[color][kind][].countSquares()
|
return self.position.pieces[color][kind].countSquares()
|
||||||
|
|
||||||
|
|
||||||
func getPiece*(self: Chessboard, square: Square): Piece {.inline.} =
|
func getPiece*(self: Chessboard, square: Square): Piece {.inline.} =
|
||||||
|
@ -200,20 +199,20 @@ func getPiece*(self: Chessboard, square: string): Piece {.inline.} =
|
||||||
return self.getPiece(square.toSquare())
|
return self.getPiece(square.toSquare())
|
||||||
|
|
||||||
|
|
||||||
proc removePieceFromBitboard*(self: Chessboard, square: Square) =
|
proc removePieceFromBitboard*(self: var Chessboard, square: Square) =
|
||||||
## Removes a piece at the given square in the chessboard from
|
## Removes a piece at the given square in the chessboard from
|
||||||
## its respective bitboard
|
## its respective bitboard
|
||||||
let piece = self.getPiece(square)
|
let piece = self.getPiece(square)
|
||||||
self.position.pieces[piece.color][piece.kind][].clearBit(square)
|
self.position.pieces[piece.color][piece.kind].clearBit(square)
|
||||||
|
|
||||||
|
|
||||||
proc addPieceToBitboard*(self: Chessboard, square: Square, piece: Piece) =
|
proc addPieceToBitboard*(self: var Chessboard, square: Square, piece: Piece) =
|
||||||
## Adds the given piece at the given square in the chessboard to
|
## Adds the given piece at the given square in the chessboard to
|
||||||
## its respective bitboard
|
## its respective bitboard
|
||||||
self.position.pieces[piece.color][piece.kind][].setBit(square)
|
self.position.pieces[piece.color][piece.kind].setBit(square)
|
||||||
|
|
||||||
|
|
||||||
proc spawnPiece*(self: Chessboard, square: Square, piece: Piece) =
|
proc spawnPiece*(self: var Chessboard, square: Square, piece: Piece) =
|
||||||
## Internal helper to "spawn" a given piece at the given
|
## Internal helper to "spawn" a given piece at the given
|
||||||
## square
|
## square
|
||||||
when not defined(danger):
|
when not defined(danger):
|
||||||
|
@ -222,7 +221,7 @@ proc spawnPiece*(self: Chessboard, square: Square, piece: Piece) =
|
||||||
self.grid[square] = piece
|
self.grid[square] = piece
|
||||||
|
|
||||||
|
|
||||||
proc removePiece*(self: Chessboard, square: Square) =
|
proc removePiece*(self: var Chessboard, square: Square) =
|
||||||
## Removes a piece from the board, updating necessary
|
## Removes a piece from the board, updating necessary
|
||||||
## metadata
|
## metadata
|
||||||
when not defined(danger):
|
when not defined(danger):
|
||||||
|
@ -232,7 +231,7 @@ proc removePiece*(self: Chessboard, square: Square) =
|
||||||
self.grid[square] = nullPiece()
|
self.grid[square] = nullPiece()
|
||||||
|
|
||||||
|
|
||||||
proc movePiece*(self: Chessboard, move: Move) =
|
proc movePiece*(self: var Chessboard, move: Move) =
|
||||||
## Internal helper to move a piece from
|
## Internal helper to move a piece from
|
||||||
## its current square to a target square
|
## its current square to a target square
|
||||||
let piece = self.getPiece(move.startSquare)
|
let piece = self.getPiece(move.startSquare)
|
||||||
|
@ -245,7 +244,7 @@ proc movePiece*(self: Chessboard, move: Move) =
|
||||||
self.spawnPiece(move.targetSquare, piece)
|
self.spawnPiece(move.targetSquare, piece)
|
||||||
|
|
||||||
|
|
||||||
proc movePiece*(self: Chessboard, startSquare, targetSquare: Square) =
|
proc movePiece*(self: var Chessboard, startSquare, targetSquare: Square) =
|
||||||
self.movePiece(createMove(startSquare, targetSquare))
|
self.movePiece(createMove(startSquare, targetSquare))
|
||||||
|
|
||||||
|
|
||||||
|
@ -377,7 +376,7 @@ proc isOccupancyAttacked*(self: Chessboard, square: Square, occupancy: Bitboard)
|
||||||
return true
|
return true
|
||||||
|
|
||||||
|
|
||||||
proc updateChecksAndPins*(self: Chessboard) =
|
proc updateChecksAndPins*(self: var Chessboard) =
|
||||||
## Updates internal metadata about checks and
|
## Updates internal metadata about checks and
|
||||||
## pinned pieces
|
## pinned pieces
|
||||||
|
|
||||||
|
@ -428,7 +427,7 @@ proc canCastle*(self: Chessboard): tuple[queen, king: bool] =
|
||||||
let
|
let
|
||||||
sideToMove = self.position.sideToMove
|
sideToMove = self.position.sideToMove
|
||||||
occupancy = self.getOccupancy()
|
occupancy = self.getOccupancy()
|
||||||
result = self.position.castlingAvailability[sideToMove.int]
|
result = self.position.castlingAvailability[sideToMove]
|
||||||
if result.king:
|
if result.king:
|
||||||
result.king = (kingSideCastleRay(sideToMove) and occupancy) == 0
|
result.king = (kingSideCastleRay(sideToMove) and occupancy) == 0
|
||||||
if result.queen:
|
if result.queen:
|
||||||
|
@ -458,35 +457,35 @@ proc canCastle*(self: Chessboard): tuple[queen, king: bool] =
|
||||||
break
|
break
|
||||||
|
|
||||||
|
|
||||||
proc update*(self: Chessboard) =
|
proc update*(self: var Chessboard) =
|
||||||
## Updates the internal grid representation
|
## Updates the internal grid representation
|
||||||
## according to the positional data stored
|
## according to the positional data stored
|
||||||
## in the chessboard
|
## in the chessboard
|
||||||
for i in 0..63:
|
for i in 0..63:
|
||||||
self.grid[i] = nullPiece()
|
self.grid[i] = nullPiece()
|
||||||
for sq in self.position.pieces[White][Pawn][]:
|
for sq in self.position.pieces[White][Pawn]:
|
||||||
self.grid[sq] = Piece(color: White, kind: Pawn)
|
self.grid[sq] = Piece(color: White, kind: Pawn)
|
||||||
for sq in self.position.pieces[Black][Pawn][]:
|
for sq in self.position.pieces[Black][Pawn]:
|
||||||
self.grid[sq] = Piece(color: Black, kind: Pawn)
|
self.grid[sq] = Piece(color: Black, kind: Pawn)
|
||||||
for sq in self.position.pieces[White][Bishop][]:
|
for sq in self.position.pieces[White][Bishop]:
|
||||||
self.grid[sq] = Piece(color: White, kind: Bishop)
|
self.grid[sq] = Piece(color: White, kind: Bishop)
|
||||||
for sq in self.position.pieces[Black][Bishop][]:
|
for sq in self.position.pieces[Black][Bishop]:
|
||||||
self.grid[sq] = Piece(color: Black, kind: Bishop)
|
self.grid[sq] = Piece(color: Black, kind: Bishop)
|
||||||
for sq in self.position.pieces[White][Knight][]:
|
for sq in self.position.pieces[White][Knight]:
|
||||||
self.grid[sq] = Piece(color: White, kind: Knight)
|
self.grid[sq] = Piece(color: White, kind: Knight)
|
||||||
for sq in self.position.pieces[Black][Knight][]:
|
for sq in self.position.pieces[Black][Knight]:
|
||||||
self.grid[sq] = Piece(color: Black, kind: Knight)
|
self.grid[sq] = Piece(color: Black, kind: Knight)
|
||||||
for sq in self.position.pieces[White][Rook][]:
|
for sq in self.position.pieces[White][Rook]:
|
||||||
self.grid[sq] = Piece(color: White, kind: Rook)
|
self.grid[sq] = Piece(color: White, kind: Rook)
|
||||||
for sq in self.position.pieces[Black][Rook][]:
|
for sq in self.position.pieces[Black][Rook]:
|
||||||
self.grid[sq] = Piece(color: Black, kind: Rook)
|
self.grid[sq] = Piece(color: Black, kind: Rook)
|
||||||
for sq in self.position.pieces[White][Queen][]:
|
for sq in self.position.pieces[White][Queen]:
|
||||||
self.grid[sq] = Piece(color: White, kind: Queen)
|
self.grid[sq] = Piece(color: White, kind: Queen)
|
||||||
for sq in self.position.pieces[Black][Queen][]:
|
for sq in self.position.pieces[Black][Queen]:
|
||||||
self.grid[sq] = Piece(color: Black, kind: Queen)
|
self.grid[sq] = Piece(color: Black, kind: Queen)
|
||||||
for sq in self.position.pieces[White][King][]:
|
for sq in self.position.pieces[White][King]:
|
||||||
self.grid[sq] = Piece(color: White, kind: King)
|
self.grid[sq] = Piece(color: White, kind: King)
|
||||||
for sq in self.position.pieces[Black][King][]:
|
for sq in self.position.pieces[Black][King]:
|
||||||
self.grid[sq] = Piece(color: Black, kind: King)
|
self.grid[sq] = Piece(color: Black, kind: King)
|
||||||
|
|
||||||
|
|
||||||
|
@ -559,8 +558,8 @@ proc toFEN*(self: Chessboard): string =
|
||||||
result &= (if self.position.sideToMove == White: "w" else: "b")
|
result &= (if self.position.sideToMove == White: "w" else: "b")
|
||||||
result &= " "
|
result &= " "
|
||||||
# Castling availability
|
# Castling availability
|
||||||
let castleWhite = self.position.castlingAvailability[White.int]
|
let castleWhite = self.position.castlingAvailability[White]
|
||||||
let castleBlack = self.position.castlingAvailability[Black.int]
|
let castleBlack = self.position.castlingAvailability[Black]
|
||||||
if not (castleBlack.king or castleBlack.queen or castleWhite.king or castleWhite.queen):
|
if not (castleBlack.king or castleBlack.queen or castleWhite.king or castleWhite.queen):
|
||||||
result &= "-"
|
result &= "-"
|
||||||
else:
|
else:
|
||||||
|
@ -586,7 +585,7 @@ proc toFEN*(self: Chessboard): string =
|
||||||
result &= $self.position.fullMoveCount
|
result &= $self.position.fullMoveCount
|
||||||
|
|
||||||
|
|
||||||
proc drawByRepetition*(self: Chessboard): bool =
|
proc drawByRepetition*(self: var Chessboard): bool =
|
||||||
## Returns whether the current position is a draw
|
## Returns whether the current position is a draw
|
||||||
## by repetition
|
## by repetition
|
||||||
# TODO: Improve this
|
# TODO: Improve this
|
||||||
|
@ -601,7 +600,7 @@ proc drawByRepetition*(self: Chessboard): bool =
|
||||||
dec(i)
|
dec(i)
|
||||||
|
|
||||||
|
|
||||||
proc hash*(self: Chessboard) =
|
proc hash*(self: var Chessboard) =
|
||||||
## Computes the zobrist hash of the current
|
## Computes the zobrist hash of the current
|
||||||
## position. This only needs to be called when
|
## position. This only needs to be called when
|
||||||
## a position is loaded the first time, as all
|
## a position is loaded the first time, as all
|
||||||
|
@ -615,13 +614,13 @@ proc hash*(self: Chessboard) =
|
||||||
for sq in self.getOccupancy():
|
for sq in self.getOccupancy():
|
||||||
self.position.zobristKey = self.position.zobristKey xor self.getPiece(sq).getKey(sq)
|
self.position.zobristKey = self.position.zobristKey xor self.getPiece(sq).getKey(sq)
|
||||||
|
|
||||||
if self.position.castlingAvailability[White.int].king:
|
if self.position.castlingAvailability[White].king:
|
||||||
self.position.zobristKey = self.position.zobristKey xor getKingSideCastlingKey(White)
|
self.position.zobristKey = self.position.zobristKey xor getKingSideCastlingKey(White)
|
||||||
if self.position.castlingAvailability[White.int].queen:
|
if self.position.castlingAvailability[White].queen:
|
||||||
self.position.zobristKey = self.position.zobristKey xor getQueenSideCastlingKey(White)
|
self.position.zobristKey = self.position.zobristKey xor getQueenSideCastlingKey(White)
|
||||||
if self.position.castlingAvailability[Black.int].king:
|
if self.position.castlingAvailability[Black].king:
|
||||||
self.position.zobristKey = self.position.zobristKey xor getKingSideCastlingKey(Black)
|
self.position.zobristKey = self.position.zobristKey xor getKingSideCastlingKey(Black)
|
||||||
if self.position.castlingAvailability[Black.int].queen:
|
if self.position.castlingAvailability[Black].queen:
|
||||||
self.position.zobristKey = self.position.zobristKey xor getQueenSideCastlingKey(Black)
|
self.position.zobristKey = self.position.zobristKey xor getQueenSideCastlingKey(Black)
|
||||||
|
|
||||||
if self.position.enPassantSquare != nullSquare():
|
if self.position.enPassantSquare != nullSquare():
|
||||||
|
|
|
@ -32,7 +32,7 @@ export bitboards, magics, pieces, moves, position, rays, board
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
proc generatePawnMoves(self: Chessboard, moves: var MoveList, destinationMask: Bitboard) =
|
proc generatePawnMoves(self: var Chessboard, moves: var MoveList, destinationMask: Bitboard) =
|
||||||
let
|
let
|
||||||
sideToMove = self.position.sideToMove
|
sideToMove = self.position.sideToMove
|
||||||
nonSideToMove = sideToMove.opposite()
|
nonSideToMove = sideToMove.opposite()
|
||||||
|
@ -272,7 +272,7 @@ proc generateCastling(self: Chessboard, moves: var MoveList) =
|
||||||
moves.add(createMove(kingSquare, kingPiece.queenSideCastling(), Castle))
|
moves.add(createMove(kingSquare, kingPiece.queenSideCastling(), Castle))
|
||||||
|
|
||||||
|
|
||||||
proc generateMoves*(self: Chessboard, moves: var MoveList, capturesOnly: bool = false) =
|
proc generateMoves*(self: var Chessboard, moves: var MoveList, capturesOnly: bool = false) =
|
||||||
## Generates the list of all possible legal moves
|
## Generates the list of all possible legal moves
|
||||||
## in the current position. If capturesOnly is
|
## in the current position. If capturesOnly is
|
||||||
## true, only capture moves are generated
|
## true, only capture moves are generated
|
||||||
|
@ -330,7 +330,7 @@ proc generateMoves*(self: Chessboard, moves: var MoveList, capturesOnly: bool =
|
||||||
# Queens are just handled rooks + bishops
|
# Queens are just handled rooks + bishops
|
||||||
|
|
||||||
|
|
||||||
proc doMove*(self: Chessboard, move: Move) =
|
proc doMove*(self: var Chessboard, move: Move) =
|
||||||
## Internal function called by makeMove after
|
## Internal function called by makeMove after
|
||||||
## performing legality checks. Can be used in
|
## performing legality checks. Can be used in
|
||||||
## performance-critical paths where a move is
|
## performance-critical paths where a move is
|
||||||
|
@ -388,7 +388,7 @@ proc doMove*(self: Chessboard, move: Move) =
|
||||||
if move.isCastling() or piece.kind == King:
|
if move.isCastling() or piece.kind == King:
|
||||||
# If the king has moved, all castling rights for the side to
|
# If the king has moved, all castling rights for the side to
|
||||||
# move are revoked
|
# move are revoked
|
||||||
self.position.castlingAvailability[piece.color.int] = (false, false)
|
self.position.castlingAvailability[piece.color] = (false, false)
|
||||||
if move.isCastling():
|
if move.isCastling():
|
||||||
# Move the rook where it belongs
|
# Move the rook where it belongs
|
||||||
var
|
var
|
||||||
|
@ -414,9 +414,9 @@ proc doMove*(self: Chessboard, move: Move) =
|
||||||
# If a rook on either side moves, castling rights are permanently revoked
|
# If a rook on either side moves, castling rights are permanently revoked
|
||||||
# on that side
|
# on that side
|
||||||
if move.startSquare == piece.color.kingSideRook():
|
if move.startSquare == piece.color.kingSideRook():
|
||||||
self.position.castlingAvailability[piece.color.int].king = false
|
self.position.castlingAvailability[piece.color].king = false
|
||||||
elif move.startSquare == piece.color.queenSideRook():
|
elif move.startSquare == piece.color.queenSideRook():
|
||||||
self.position.castlingAvailability[piece.color.int].queen = false
|
self.position.castlingAvailability[piece.color].queen = false
|
||||||
|
|
||||||
if move.isCapture():
|
if move.isCapture():
|
||||||
# Get rid of captured pieces
|
# Get rid of captured pieces
|
||||||
|
@ -426,9 +426,9 @@ proc doMove*(self: Chessboard, move: Move) =
|
||||||
# If a rook has been captured, castling on that side is prohibited
|
# If a rook has been captured, castling on that side is prohibited
|
||||||
if captured.kind == Rook:
|
if captured.kind == Rook:
|
||||||
if move.targetSquare == captured.color.kingSideRook():
|
if move.targetSquare == captured.color.kingSideRook():
|
||||||
self.position.castlingAvailability[captured.color.int].king = false
|
self.position.castlingAvailability[captured.color].king = false
|
||||||
elif move.targetSquare == captured.color.queenSideRook():
|
elif move.targetSquare == captured.color.queenSideRook():
|
||||||
self.position.castlingAvailability[captured.color.int].queen = false
|
self.position.castlingAvailability[captured.color].queen = false
|
||||||
|
|
||||||
# Move the piece to its target square
|
# Move the piece to its target square
|
||||||
self.movePiece(move)
|
self.movePiece(move)
|
||||||
|
@ -457,21 +457,21 @@ proc doMove*(self: Chessboard, move: Move) =
|
||||||
# Updates checks and pins for the (new) side to move
|
# Updates checks and pins for the (new) side to move
|
||||||
self.updateChecksAndPins()
|
self.updateChecksAndPins()
|
||||||
# Last updates to zobrist key
|
# Last updates to zobrist key
|
||||||
if self.position.castlingAvailability[piece.color.int].king:
|
if self.position.castlingAvailability[piece.color].king:
|
||||||
self.position.zobristKey = self.position.zobristKey xor getKingSideCastlingKey(piece.color)
|
self.position.zobristKey = self.position.zobristKey xor getKingSideCastlingKey(piece.color)
|
||||||
if self.position.castlingAvailability[piece.color.int].queen:
|
if self.position.castlingAvailability[piece.color].queen:
|
||||||
self.position.zobristKey = self.position.zobristKey xor getQueenSideCastlingKey(piece.color)
|
self.position.zobristKey = self.position.zobristKey xor getQueenSideCastlingKey(piece.color)
|
||||||
discard self.drawByRepetition()
|
discard self.drawByRepetition()
|
||||||
|
|
||||||
|
|
||||||
proc isLegal*(self: Chessboard, move: Move): bool {.inline.} =
|
proc isLegal*(self: var Chessboard, move: Move): bool {.inline.} =
|
||||||
## Returns whether the given move is legal
|
## Returns whether the given move is legal
|
||||||
var moves = newMoveList()
|
var moves = newMoveList()
|
||||||
self.generateMoves(moves)
|
self.generateMoves(moves)
|
||||||
return move in moves
|
return move in moves
|
||||||
|
|
||||||
|
|
||||||
proc makeMove*(self: Chessboard, move: Move): Move {.discardable.} =
|
proc makeMove*(self: var Chessboard, move: Move): Move {.discardable.} =
|
||||||
## Makes a move on the board
|
## Makes a move on the board
|
||||||
result = move
|
result = move
|
||||||
# Updates checks and pins for the side to move
|
# Updates checks and pins for the side to move
|
||||||
|
@ -480,7 +480,7 @@ proc makeMove*(self: Chessboard, move: Move): Move {.discardable.} =
|
||||||
self.doMove(move)
|
self.doMove(move)
|
||||||
|
|
||||||
|
|
||||||
proc unmakeMove*(self: Chessboard) =
|
proc unmakeMove*(self: var Chessboard) =
|
||||||
## Reverts to the previous board position
|
## Reverts to the previous board position
|
||||||
if self.positions.len() == 0:
|
if self.positions.len() == 0:
|
||||||
return
|
return
|
||||||
|
|
|
@ -25,7 +25,7 @@ type
|
||||||
# of whether the king or the rooks on either side
|
# of whether the king or the rooks on either side
|
||||||
# moved, the actual checks for the legality of castling
|
# moved, the actual checks for the legality of castling
|
||||||
# are done elsewhere
|
# are done elsewhere
|
||||||
castlingAvailability*: array[2, tuple[queen, king: bool]]
|
castlingAvailability*: array[PieceColor.White..PieceColor.Black, tuple[queen, king: bool]]
|
||||||
# Number of half-moves that were performed
|
# Number of half-moves that were performed
|
||||||
# to reach this position starting from the
|
# to reach this position starting from the
|
||||||
# root of the tree
|
# root of the tree
|
||||||
|
@ -42,7 +42,7 @@ type
|
||||||
# The side to move
|
# The side to move
|
||||||
sideToMove*: PieceColor
|
sideToMove*: PieceColor
|
||||||
# Positional bitboards for all pieces
|
# Positional bitboards for all pieces
|
||||||
pieces*: array[2, array[6, Bitboard]]
|
pieces*: array[PieceColor.White..PieceColor.Black, array[PieceKind.Bishop..PieceKind.Rook, Bitboard]]
|
||||||
# Pieces pinned for the current side to move
|
# Pieces pinned for the current side to move
|
||||||
diagonalPins*: Bitboard # Pinned diagonally (by a queen or bishop)
|
diagonalPins*: Bitboard # Pinned diagonally (by a queen or bishop)
|
||||||
orthogonalPins*: Bitboard # Pinned orthogonally (by a queen or rook)
|
orthogonalPins*: Bitboard # Pinned orthogonally (by a queen or rook)
|
||||||
|
@ -66,14 +66,9 @@ func getKingStartingSquare*(color: PieceColor): Square {.inline.} =
|
||||||
discard
|
discard
|
||||||
|
|
||||||
|
|
||||||
func `[]`*(self: array[2, array[6, Bitboard]], color: PieceColor): ptr array[6, Bitboard] {.inline.} = addr self[color.int]
|
|
||||||
func `[]`*(self: array[6, Bitboard], kind: PieceKind): ptr Bitboard {.inline.} = addr self[kind.int]
|
|
||||||
func `[]=`*(self: var array[6, Bitboard], kind: PieceKind, bitboard: Bitboard) {.inline.} = self[kind.int] = bitboard
|
|
||||||
|
|
||||||
|
|
||||||
func getBitboard*(self: Position, kind: PieceKind, color: PieceColor): Bitboard =
|
func getBitboard*(self: Position, kind: PieceKind, color: PieceColor): Bitboard =
|
||||||
## Returns the positional bitboard for the given piece kind and color
|
## Returns the positional bitboard for the given piece kind and color
|
||||||
return self.pieces[color.int][kind.int]
|
return self.pieces[color][kind]
|
||||||
|
|
||||||
|
|
||||||
func getBitboard*(self: Position, piece: Piece): Bitboard =
|
func getBitboard*(self: Position, piece: Piece): Bitboard =
|
||||||
|
@ -84,7 +79,7 @@ func getBitboard*(self: Position, piece: Piece): Bitboard =
|
||||||
func getOccupancyFor*(self: Position, color: PieceColor): Bitboard =
|
func getOccupancyFor*(self: Position, color: PieceColor): Bitboard =
|
||||||
## Get the occupancy bitboard for every piece of the given color
|
## Get the occupancy bitboard for every piece of the given color
|
||||||
result = Bitboard(0)
|
result = Bitboard(0)
|
||||||
for b in self.pieces[color][]:
|
for b in self.pieces[color]:
|
||||||
result = result or b
|
result = result or b
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@ type
|
||||||
CountData = tuple[nodes: uint64, captures: uint64, castles: uint64, checks: uint64, promotions: uint64, enPassant: uint64, checkmates: uint64]
|
CountData = tuple[nodes: uint64, captures: uint64, castles: uint64, checks: uint64, promotions: uint64, enPassant: uint64, checkmates: uint64]
|
||||||
|
|
||||||
|
|
||||||
proc perft*(board: Chessboard, ply: int, verbose = false, divide = false, bulk = false, capturesOnly = false): CountData =
|
proc perft*(board: var Chessboard, ply: int, verbose = false, divide = false, bulk = false, capturesOnly = false): CountData =
|
||||||
## Counts (and debugs) the number of legal positions reached after
|
## Counts (and debugs) the number of legal positions reached after
|
||||||
## the given number of ply
|
## the given number of ply
|
||||||
|
|
||||||
|
@ -134,7 +134,7 @@ proc perft*(board: Chessboard, ply: int, verbose = false, divide = false, bulk =
|
||||||
result.checkmates += next.checkmates
|
result.checkmates += next.checkmates
|
||||||
|
|
||||||
|
|
||||||
proc handleGoCommand(board: Chessboard, command: seq[string]) =
|
proc handleGoCommand(board: var Chessboard, command: seq[string]) =
|
||||||
if len(command) < 2:
|
if len(command) < 2:
|
||||||
echo &"Error: go: invalid number of arguments"
|
echo &"Error: go: invalid number of arguments"
|
||||||
return
|
return
|
||||||
|
@ -191,7 +191,7 @@ proc handleGoCommand(board: Chessboard, command: seq[string]) =
|
||||||
echo &"Error: go: unknown subcommand '{command[1]}'"
|
echo &"Error: go: unknown subcommand '{command[1]}'"
|
||||||
|
|
||||||
|
|
||||||
proc handleMoveCommand(board: Chessboard, command: seq[string]): Move {.discardable.} =
|
proc handleMoveCommand(board: var Chessboard, command: seq[string]): Move {.discardable.} =
|
||||||
if len(command) != 2:
|
if len(command) != 2:
|
||||||
echo &"Error: move: invalid number of arguments"
|
echo &"Error: move: invalid number of arguments"
|
||||||
return
|
return
|
||||||
|
|
|
@ -303,7 +303,7 @@ proc bestMove(args: tuple[session: UCISession, command: UCICommand]) {.thread.}
|
||||||
echo &"info string created {session.hashTableSize} MiB TT"
|
echo &"info string created {session.hashTableSize} MiB TT"
|
||||||
session.transpositionTable = newTranspositionTable(session.hashTableSize * 1024 * 1024)
|
session.transpositionTable = newTranspositionTable(session.hashTableSize * 1024 * 1024)
|
||||||
var command = args.command
|
var command = args.command
|
||||||
var searcher = newSearchManager(session.board.deepCopy(), session.transpositionTable)
|
var searcher = newSearchManager(session.board, session.transpositionTable)
|
||||||
session.currentSearch.store(searcher)
|
session.currentSearch.store(searcher)
|
||||||
var
|
var
|
||||||
timeRemaining = (if session.board.position.sideToMove == White: command.wtime else: command.btime)
|
timeRemaining = (if session.board.position.sideToMove == White: command.wtime else: command.btime)
|
||||||
|
|
Loading…
Reference in New Issue