Speedups
This commit is contained in:
parent
64c30b8a90
commit
6fbcd4ff74
|
@ -721,109 +721,45 @@ proc generatePawnMoves(self: ChessBoard, moves: var MoveList) =
|
||||||
self.generatePawnPromotions(moves)
|
self.generatePawnPromotions(moves)
|
||||||
|
|
||||||
|
|
||||||
proc generateRookMovements(self: ChessBoard, moves: var MoveList) =
|
|
||||||
## Helper of generateRookMoves to generate all non-capture
|
|
||||||
## rook moves
|
|
||||||
let
|
|
||||||
sideToMove = self.getSideToMove()
|
|
||||||
occupancy = self.getOccupancy()
|
|
||||||
rooks = self.getBitboard(Rook, sideToMove)
|
|
||||||
for square in rooks:
|
|
||||||
let blockers = occupancy and Rook.getRelevantBlockers(square)
|
|
||||||
# Can't move over other pieces (captures are handled elsewhere)
|
|
||||||
let moveset = getRookMoves(square, blockers) and not occupancy
|
|
||||||
for target in moveset:
|
|
||||||
moves.add(createMove(square, target))
|
|
||||||
|
|
||||||
|
|
||||||
proc generateRookCaptures(self: ChessBoard, moves: var MoveList) =
|
|
||||||
## Helper of generateRookMoves to generate all capture
|
|
||||||
## rook moves
|
|
||||||
let
|
|
||||||
sideToMove = self.getSideToMove()
|
|
||||||
occupancy = self.getOccupancy()
|
|
||||||
enemyPieces = self.getCapturablePieces(sideToMove.opposite())
|
|
||||||
rooks = self.getBitboard(Rook, sideToMove)
|
|
||||||
for square in rooks:
|
|
||||||
let blockers = occupancy and Rook.getRelevantBlockers(square)
|
|
||||||
var moveset = getRookMoves(square, blockers)
|
|
||||||
# Can only cature enemy pieces
|
|
||||||
moveset = moveset and enemyPieces
|
|
||||||
for target in moveset:
|
|
||||||
moves.add(createMove(square, target, Capture))
|
|
||||||
|
|
||||||
|
|
||||||
proc generateRookMoves(self: ChessBoard, moves: var MoveList) =
|
proc generateRookMoves(self: ChessBoard, moves: var MoveList) =
|
||||||
## Helper of generateSlidingMoves to generate rook moves
|
## Helper of generateSlidingMoves to generate rook moves
|
||||||
self.generateRookMovements(moves)
|
|
||||||
self.generateRookCaptures(moves)
|
|
||||||
|
|
||||||
|
|
||||||
proc generateBishopMovements(self: ChessBoard, moves: var MoveList) =
|
|
||||||
## Helper of generateBishopMoves to generate all non-capture
|
|
||||||
## bishop moves
|
|
||||||
let
|
|
||||||
sideToMove = self.getSideToMove()
|
|
||||||
occupancy = self.getOccupancy()
|
|
||||||
bishops = self.getBitboard(Bishop, sideToMove)
|
|
||||||
for square in bishops:
|
|
||||||
let blockers = occupancy and Bishop.getRelevantBlockers(square)
|
|
||||||
var moveset = getBishopMoves(square, blockers)
|
|
||||||
# Can't move over other pieces (captures are handled elsewhere)
|
|
||||||
moveset = moveset and not occupancy
|
|
||||||
for target in moveset:
|
|
||||||
moves.add(createMove(square, target))
|
|
||||||
|
|
||||||
|
|
||||||
proc generateBishopCaptures(self: ChessBoard, moves: var MoveList) =
|
|
||||||
## Helper of generateBishopMoves to generate all capture
|
|
||||||
## bishop moves
|
|
||||||
let
|
let
|
||||||
sideToMove = self.getSideToMove()
|
sideToMove = self.getSideToMove()
|
||||||
occupancy = self.getOccupancy()
|
occupancy = self.getOccupancy()
|
||||||
enemyPieces = self.getCapturablePieces(sideToMove.opposite())
|
enemyPieces = self.getCapturablePieces(sideToMove.opposite())
|
||||||
bishops = self.getBitboard(Bishop, sideToMove)
|
rooks = self.getBitboard(Rook, sideToMove)
|
||||||
for square in bishops:
|
for square in rooks:
|
||||||
let blockers = occupancy and Bishop.getRelevantBlockers(square)
|
let blockers = occupancy and Rook.getRelevantBlockers(square)
|
||||||
|
# Quiet moves
|
||||||
var moveset = getRookMoves(square, blockers)
|
var moveset = getRookMoves(square, blockers)
|
||||||
# Can only cature enemy pieces
|
for target in moveset and not occupancy:
|
||||||
moveset = moveset and enemyPieces
|
moves.add(createMove(square, target))
|
||||||
for target in moveset:
|
# Captures
|
||||||
|
for target in moveset and enemyPieces:
|
||||||
moves.add(createMove(square, target, Capture))
|
moves.add(createMove(square, target, Capture))
|
||||||
|
|
||||||
|
|
||||||
proc generateBishopMoves(self: ChessBoard, moves: var MoveList) =
|
proc generateBishopMoves(self: ChessBoard, moves: var MoveList) =
|
||||||
## Helper of generateSlidingMoves to generate bishop moves
|
## Helper of generateSlidingMoves to generate bishop moves
|
||||||
self.generateBishopMovements(moves)
|
# self.generateBishopMovements(moves)
|
||||||
self.generateBishopCaptures(moves)
|
# self.generateBishopCaptures(moves)
|
||||||
|
|
||||||
|
|
||||||
proc generateQueenMovements(self: ChessBoard, moves: var MoveList) =
|
|
||||||
## Helper of generateQueenMoves to generate all non-capture
|
|
||||||
## bishop moves
|
|
||||||
let
|
let
|
||||||
sideToMove = self.getSideToMove()
|
sideToMove = self.getSideToMove()
|
||||||
|
enemyPieces = self.getOccupancyFor(sideToMove.opposite())
|
||||||
occupancy = self.getOccupancy()
|
occupancy = self.getOccupancy()
|
||||||
friendlyPieces = self.getOccupancyFor(sideToMove)
|
bishops = self.getBitboard(Bishop, sideToMove)
|
||||||
queens = self.getBitboard(Queen, sideToMove)
|
for square in bishops:
|
||||||
for square in queens:
|
let blockers = occupancy and Bishop.getRelevantBlockers(square)
|
||||||
# A queen is just a rook plus a bishop in terms of move
|
let moveset = getBishopMoves(square, blockers)
|
||||||
# generation
|
# Can't move over other pieces
|
||||||
let
|
for target in moveset and not occupancy:
|
||||||
rookBlockers = Rook.getRelevantBlockers(square) and occupancy
|
|
||||||
bishopBlockers = Bishop.getRelevantBlockers(square) and occupancy
|
|
||||||
rookMoves = getRookMoves(square, rookBlockers)
|
|
||||||
bishopMoves = getBishopMoves(square, bishopBlockers)
|
|
||||||
var moveset = rookMoves or bishopMoves
|
|
||||||
# Can't move over other pieces (captures are handled elsewhere)
|
|
||||||
moveset = moveset and not occupancy
|
|
||||||
for target in moveset:
|
|
||||||
moves.add(createMove(square, target))
|
moves.add(createMove(square, target))
|
||||||
|
for target in moveset and enemyPieces:
|
||||||
|
moves.add(createMove(square, target, Capture))
|
||||||
|
|
||||||
|
|
||||||
proc generateQueenCaptures(self: ChessBoard, moves: var MoveList) =
|
proc generateQueenMoves(self: ChessBoard, moves: var MoveList) =
|
||||||
## Helper of generateQueenMoves to generate all capture
|
## Helper of generateSlidingMoves to generate queen moves
|
||||||
## queen moves
|
|
||||||
let
|
let
|
||||||
sideToMove = self.getSideToMove()
|
sideToMove = self.getSideToMove()
|
||||||
occupancy = self.getOccupancy()
|
occupancy = self.getOccupancy()
|
||||||
|
@ -837,17 +773,12 @@ proc generateQueenCaptures(self: ChessBoard, moves: var MoveList) =
|
||||||
bishopBlockers = Bishop.getRelevantBlockers(square) and occupancy
|
bishopBlockers = Bishop.getRelevantBlockers(square) and occupancy
|
||||||
rookMoves = getRookMoves(square, rookBlockers)
|
rookMoves = getRookMoves(square, rookBlockers)
|
||||||
bishopMoves = getBishopMoves(square, bishopBlockers)
|
bishopMoves = getBishopMoves(square, bishopBlockers)
|
||||||
var moveset = rookMoves or bishopMoves
|
let moveset = rookMoves or bishopMoves
|
||||||
# Can only capture the enemy pieces
|
# Can't move over other pieces
|
||||||
moveset = moveset and enemyPieces
|
for target in moveset and not occupancy:
|
||||||
for target in moveset:
|
moves.add(createMove(square, target))
|
||||||
moves.add(createMove(square, target, Capture))
|
for target in moveset and enemyPieces:
|
||||||
|
moves.add(createMove(square, target))
|
||||||
|
|
||||||
proc generateQueenMoves(self: ChessBoard, moves: var MoveList) =
|
|
||||||
## Helper of generateSlidingMoves to generate queen moves
|
|
||||||
self.generateQueenMovements(moves)
|
|
||||||
self.generateQueenCaptures(moves)
|
|
||||||
|
|
||||||
|
|
||||||
proc generateSlidingMoves(self: ChessBoard, moves: var MoveList) =
|
proc generateSlidingMoves(self: ChessBoard, moves: var MoveList) =
|
||||||
|
@ -894,7 +825,6 @@ proc generateKnightMoves(self: ChessBoard, moves: var MoveList)=
|
||||||
proc generateMoves*(self: ChessBoard, moves: var MoveList) =
|
proc generateMoves*(self: ChessBoard, moves: var MoveList) =
|
||||||
## Generates the list of all possible legal moves
|
## Generates the list of all possible legal moves
|
||||||
## in the current position
|
## in the current position
|
||||||
moves.clear()
|
|
||||||
if self.position.halfMoveClock >= 100:
|
if self.position.halfMoveClock >= 100:
|
||||||
# Draw by 50-move rule
|
# Draw by 50-move rule
|
||||||
return
|
return
|
||||||
|
@ -1084,7 +1014,6 @@ proc doMove*(self: ChessBoard, move: Move) =
|
||||||
else:
|
else:
|
||||||
# Unreachable
|
# Unreachable
|
||||||
discard
|
discard
|
||||||
self.updateCheckers()
|
|
||||||
|
|
||||||
|
|
||||||
proc spawnPiece(self: ChessBoard, square: Square, piece: Piece) =
|
proc spawnPiece(self: ChessBoard, square: Square, piece: Piece) =
|
||||||
|
|
|
@ -6,6 +6,8 @@ import std/strutils
|
||||||
import std/times
|
import std/times
|
||||||
import std/math
|
import std/math
|
||||||
|
|
||||||
|
from std/lenientops import `/`
|
||||||
|
|
||||||
|
|
||||||
type
|
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]
|
||||||
|
@ -148,11 +150,13 @@ proc handleGoCommand(board: ChessBoard, command: seq[string]) =
|
||||||
if bulk:
|
if bulk:
|
||||||
let t = cpuTime()
|
let t = cpuTime()
|
||||||
let nodes = board.perft(ply, divide=true, bulk=true, verbose=verbose).nodes
|
let nodes = board.perft(ply, divide=true, bulk=true, verbose=verbose).nodes
|
||||||
|
let tot = cpuTime() - t
|
||||||
echo &"\nNodes searched (bulk-counting: on): {nodes}"
|
echo &"\nNodes searched (bulk-counting: on): {nodes}"
|
||||||
echo &"Time taken: {round(cpuTime() - t, 3)} seconds\n"
|
echo &"Time taken: {round(tot, 3)} seconds\nNodes per second: {round(nodes / tot).uint64}"
|
||||||
else:
|
else:
|
||||||
let t = cpuTime()
|
let t = cpuTime()
|
||||||
let data = board.perft(ply, divide=true, verbose=verbose)
|
let data = board.perft(ply, divide=true, verbose=verbose)
|
||||||
|
let tot = cpuTime()
|
||||||
echo &"\nNodes searched (bulk-counting: off): {data.nodes}"
|
echo &"\nNodes searched (bulk-counting: off): {data.nodes}"
|
||||||
echo &" - Captures: {data.captures}"
|
echo &" - Captures: {data.captures}"
|
||||||
echo &" - Checks: {data.checks}"
|
echo &" - Checks: {data.checks}"
|
||||||
|
@ -161,7 +165,7 @@ proc handleGoCommand(board: ChessBoard, command: seq[string]) =
|
||||||
echo &" - Castles: {data.castles}"
|
echo &" - Castles: {data.castles}"
|
||||||
echo &" - Promotions: {data.promotions}"
|
echo &" - Promotions: {data.promotions}"
|
||||||
echo ""
|
echo ""
|
||||||
echo &"Time taken: {round(cpuTime() - t, 3)} seconds"
|
echo &"Time taken: {round(t, 3)} seconds\nNodes per second: {round(data.nodes / tot).uint64}"
|
||||||
except ValueError:
|
except ValueError:
|
||||||
echo "Error: go: perft: invalid depth"
|
echo "Error: go: perft: invalid depth"
|
||||||
else:
|
else:
|
||||||
|
|
Loading…
Reference in New Issue