forked from LKnecht/LeelaSgfChecker
-
Notifications
You must be signed in to change notification settings - Fork 0
/
leelasgfchecker.py
154 lines (130 loc) · 4.61 KB
/
leelasgfchecker.py
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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
from subprocess import PIPE, Popen
import os, sys
import sgf
leela_path = "./Leela090/leela_090_linux_x64"
skip_opening_moves = 0 #number of the first moves to skip checking
#~ LIST OF GTP COMMANDS: list_commands
GTP_POS = ' abcdefghjklmnopqrstuvwxyzABCDEFGHJKLMNOPQRSTUVWXYZ'
def sgf2gpt_move(sgf_move):
'''convert the move coordinate from sgf to gtp.
Note that gtp skips the 'i'.'''
if len(sgf_move) < 2:
print("whywhywhywhywhyw?!")
return ""
x = GTP_POS[sgf.SGF_POS.find(sgf_move[0])]
y = sgf.SGF_POS.find(sgf_move[1])
return "{}{}".format(x, y)
def analyze(sgf_string, player_name):
'''Analyzes the sgf_string on how many moves of player_name are matching leelas moves.
Returns a tuple containing the moves matching to leelas moves and the total number of moves.'''
#initialize
coll = sgf.parse(sgf_string)
if len(coll) == 0:
print("No game in sgf found")
return
if len(coll) > 1:
print("Multiple games in sgf found, using the first!")
game_iterator = coll[0].__iter__()
meta = game_iterator.__next__().properties
player_white = meta['PW'][0]
player_black = meta['PB'][0]
player_color = None
if player_white == player_name:
player_color = 'W'
elif player_black == player_name:
player_color = 'B'
else:
print("{} doesn't match with either black or white player".format(player_name))
return None
print("\nStart Analysis for {} (b) vs {} (w)\ncomparing {} with Leela's moves\n".format(
player_black, player_white, player_name))
movelist = []
leelas_move = None
move_counter = 0
leela_moves_played = 0
for i, node in enumerate(game_iterator):
prop = node.properties
for c in ['B', 'W']:
if c in prop:
movelist.append( (c, sgf2gpt_move(prop[c][0])) )
break
if i + 1 < skip_opening_moves:
continue
if not leelas_move is None and not leelas_move == "":
move = movelist[-1][1]
print("#{} {}: {} leela: {}".format(i+1, player_name, move, leelas_move), end='')
move_counter += 1
if move == leelas_move:
leela_moves_played += 1
print("\t<-- {} match".format(leela_moves_played), end='')
print()
else:
print("#{} {}: {}".format(i+1, movelist[-1][0], movelist[-1][1]))
# probably bad solution?
# start leela, manually play all moves in movelist
# and then get the result of genmove:
next_color = movelist[-1][0]
if next_color == 'W': next_color = 'B'
else: next_color = 'W'
if next_color == player_color:
leela_input = ''
for move in movelist:
leela_input += 'play {} {}\n'.format(move[0], move[1])
leela_input += 'genmove {}'.format(next_color)
leela = Popen([leela_path, "--gtp", "--quiet"], stdin=PIPE, stdout=PIPE, bufsize=1)
res = leela.communicate(input=leela_input.encode())[0]
leela.stdin.close()
if len(res) > 12:
res = res[-7:]
leelas_move = res[res.find(b'\n= ')+3:res.find(b'\n\n', res.find(b'\n= '))].decode().lower()
leelas_move = leelas_move.replace('\n', '')
else:
leelas_move = None
if move_counter == 0: move_counter = 1
print("\n\nResult of analysis: {} / {} ({}%) leela moves played".format(leela_moves_played, move_counter, leela_moves_played * 100. / move_counter))
return leela_moves_played, move_counter
def analyze_collection(sgf_subfolder, player_name):
'''Analyze the sgf collection in the folder sgf_subfolder.
Returns a tuple containing the number of games,
the number of moves leela would have played too
and the total number of moves.'''
games, leela_moves_played, move_counter = (0,0,0)
history = []
for filename in os.listdir(sgf_subfolder):
if not filename.endswith(".sgf"):
continue
filename = os.path.join(sgf_subfolder, filename)
sgf = open(filename, 'r').read()
res = analyze(sgf, player_name)
if res is None:
continue
leelas_moves, moves = res
games += 1
leela_moves_played += leelas_moves
move_counter += moves
history.append( (filename, leelas_moves, moves ) )
print("\n\nRESULT:")
for h in history:
print("{}\t{} / {} ({}%)".format(h[0], h[1], h[2], h[1] * 100. / h[2]))
print("\nGames: \t{}\nleela moves:\t{}\nmoves total\t{}\n%\t\t{}%".format(
games, leela_moves_played, move_counter, leela_moves_played * 100. / move_counter))
return games, leela_moves_played, move_counter
if __name__ == '__main__':
argv = sys.argv[1:]
if len(argv) != 2:
print("Usage: python leelasgfchecker.py PLAYER_NAME SGF-FOLDER[/FILENAME]")
exit()
player_name, path = argv
if path.endswith('.sgf'):
try:
sgf_string = open(path, 'r').read()
analyze(sgf_string, player_name)
except KeyboardInterrupt:
print("Aborted.")
exit()
else:
try:
analyze_collection(path, player_name)
except KeyboardInterrupt:
print("aborted.")
exit()