@@ -29,6 +29,8 @@ class UCI {
29
29
handleUCINewGame ( )
30
30
case " position " :
31
31
handlePosition ( command: command)
32
+ case " goperft " :
33
+ handlePerft ( command: command. joined ( separator: " " ) )
32
34
case " go " :
33
35
handleGo ( command: command. joined ( separator: " " ) , board: board)
34
36
case " quit " :
@@ -53,6 +55,59 @@ class UCI {
53
55
private func handleUCINewGame( ) {
54
56
board = ChessBoard ( fen: startPosFen)
55
57
}
58
+
59
+ func handlePerft( command: String ) {
60
+ let board = ChessBoard ( fen: startPosFen)
61
+ let parts = command. split ( separator: " " )
62
+ guard parts. count > 1 , let depth = Int ( parts [ 1 ] ) else {
63
+ print ( " Invalid perft command " )
64
+ return
65
+ }
66
+
67
+ let startTime = Date ( )
68
+ let totalNodes = perft ( board: board, depth: depth)
69
+ let endTime = Date ( )
70
+
71
+ let timeTaken = endTime. timeIntervalSince ( startTime)
72
+ let nodesPerSecond = Double ( totalNodes) / timeTaken
73
+
74
+ print ( " Total: \( totalNodes) " )
75
+ print ( String ( format: " Time: %.2f secs " , timeTaken) )
76
+ print ( String ( format: " NodesPerSec: %.2f NPS " , nodesPerSecond) )
77
+ }
78
+
79
+ private func perft( board: ChessBoard , depth: Int ) -> Int {
80
+ var totalNodes = 0
81
+ let moves = MoveGenerator . generateMoves ( for: board, color: board. turn)
82
+
83
+ for move in moves {
84
+ board. makeMove ( move)
85
+ let nodes = perftRecursive ( board: board, depth: depth - 1 )
86
+ board. undoMove ( move)
87
+
88
+ print ( " \( move. toUCI ( ) ) - \( nodes) " )
89
+ totalNodes += nodes
90
+ }
91
+
92
+ return totalNodes
93
+ }
94
+
95
+ private func perftRecursive( board: ChessBoard , depth: Int ) -> Int {
96
+ if depth == 0 {
97
+ return 1
98
+ }
99
+
100
+ var nodes = 0
101
+ let moves = MoveGenerator . generateMoves ( for: board, color: board. turn)
102
+
103
+ for move in moves {
104
+ board. makeMove ( move)
105
+ nodes += perftRecursive ( board: board, depth: depth - 1 )
106
+ board. undoMove ( move)
107
+ }
108
+
109
+ return nodes
110
+ }
56
111
57
112
private func handlePosition( command: [ Substring ] ) {
58
113
guard command. count > 1 else { return }
@@ -161,7 +216,6 @@ class UCI {
161
216
moveValue = Search . minimax ( board: boardCopy, depth: searchDepth - 1 , maximizingPlayer: true )
162
217
} else {
163
218
moveValue = Search . minimax ( board: boardCopy, depth: searchDepth - 1 , maximizingPlayer: false )
164
-
165
219
}
166
220
board. undoMove ( move)
167
221
0 commit comments