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