-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathuci_player.py
More file actions
91 lines (76 loc) · 2.36 KB
/
uci_player.py
File metadata and controls
91 lines (76 loc) · 2.36 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
import re
import subprocess
class UciPlayer:
def __init__(self, path, weights = None):
self.name = (path, weights)
self._p = subprocess.Popen(path, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
self.allin = []
self.allout = []
self.command("uci")
if weights is not None and weights.lower() != 'none':
self.command(f"loadweights {weights}")
def __del__(self):
self._p.terminate()
def command(self, text):
self.allin.append(text)
self._p.stdin.write((text + '\n').encode())
self._p.stdin.flush()
def setoption(self, name : str, value : str = None):
if value is None:
self.command(f"setoption name {name}")
else:
self.command(f"setoption name {name} value {value}")
def set_multipv(self, value : int):
self.setoption("MultiPV", value)
@staticmethod
def _parse_line(line):
parts = line.split(' ')[1:]
r = {}
i = 0
while i < len(parts):
if parts[i] == 'pv':
r['pv'] = parts[i+1:]
break
if parts[i] == 'score':
assert parts[i + 1] in ['cp', 'mate']
r['score'] = [parts[i+1], int(parts[i+2])]
i += 3
continue
if parts[i] == 'wdl':
r['wdl'] = [int(x) for x in parts[i+1:i+4]]
i += 4
continue
if parts[i] == 'upperbound': # ignore this for now
assert parts[i + 1] == 'nodes'
i += 1
continue
if i + 1 >= len(parts):
print(parts)
r[parts[i]] = parts[i + 1]
i += 2
intkeys = set(['depth', 'seldepth', 'multipv', 'nodes', 'nps', 'hashfull', 'tbhits', 'time'])
for k in r:
if k in intkeys:
r[k] = int(r[k])
return r
def go(self, fen, depth):
self.command(f"position fen {fen}")
self.command(f"go depth {depth}")
lines = []
while True:
line = self._p.stdout.readline().decode()
self.allout.append(line)
lines.append(line.strip())
if line.startswith('bestmove '):
break
assert 'bestmove ' in lines[-1] # e.g. "bestmove h6h7 ponder a2a3"
lines = [line for line in lines if re.match(rf"info depth {depth}.+", line)]
R = []
for line in lines:
R.append(UciPlayer._parse_line(line))
return R
if __name__ == '__main__':
import chess
player = UciPlayer('/usr/local/bin/stockfish')
player.setoption('UCI_ShowWDL', 'true')
r = player.go(chess.Board().fen(), depth=20)