diff --git a/Chess/nimfish/nimfish.nim b/Chess/nimfish/nimfish.nim index 16e9be4..3ae169c 100644 --- a/Chess/nimfish/nimfish.nim +++ b/Chess/nimfish/nimfish.nim @@ -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) = diff --git a/Chess/nimfish/tui.nim b/Chess/nimfish/tui.nim index a990719..38d215d 100644 --- a/Chess/nimfish/tui.nim +++ b/Chess/nimfish/tui.nim @@ -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: