[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [computer-go] Mass estimation of game results?
For anyone who's interested, I've finished the short script. All it
needs is Python and gnugo installed. I've only tested it on Linux, but I
see no reason why it wouldn't work on some other platform. Hopefully
someone else also finds it useful =) I know I did.
It can be found at http://thegoban.com/estimate_sgf_results.py , or as
an attachment to this message.
#!/usr/bin/python
import os
from os.path import *
import sre
from subprocess import *
import popen2
#RE_PREFIX and PREFIX are the tag that should show up right before
#the RE[] tag. The RE_PREFIX (Regular Expression prefix) should be the
#regular expression version of the prefix, and PREFIX should be what it
#will show up as in the final file. In general, RE_PREFIX should be the
#same as PREFIX, but with the ']' and '[' characters escaped by '/'
RE_PREFIX='ST\[1\]'
PREFIX='ST[1]'
def scanSGF (target):
if isdir(target):
for sgf_file in os.listdir(target):
if sgf_file!='Desktop':
scanSGF(target+os.sep+sgf_file)
elif isfile(target) and target[len(target)-4:]=='.sgf':
try:
#Check to see if there is already a result tag. At the moment, it will accept any sort
#of result tag, but this is easily modified to replace result tags that are improper.
if len(sre.findall('(RE\[.*\])',file(target,'r').read())) >0:
print target+" already has a result. Skipping..."
else:
print target+":",
next_move = sre.findall('([B|W])\[[a-z][a-z]\]',file(target,'r').read())[-1]
#next_move looks inside the SGF to find the last player who made a move. This is so that later, the
#GnuGo engine knows for which player to generate a move.
if next_move=='W':
next_move='black'
else:
next_move='white'
#The black/white syntax is needed by the GTP protocol.
gtp_test = file('gtp_test','w')
gtp_test.write('reg_genmove '+next_move+'\ntop_moves\nquit')
gtp_test.flush()
#Although it would technically be possible to bind gnugo's STDIN and STDOUT to Python, it is just
#so much simpler to put the commands in a file. The file is deleted later anyway.
gnugo_session = os.popen('gnugo --mode gtp --gtp-input gtp_test -l '+target).read()
if len(sre.findall('PASS',gnugo_session))>0:
move_value = 0
#If GnuGo thinks the best move is to pass, then the game is obviously over, and setting
#move_value to 0 will ensure that the game will later be given to GnuGo to estimate score.
else:
move_value = sre.findall('([\d\d|\d]\.[\d|\d\d])',gnugo_session)[0]
#Since GnuGo will give the values of the move in reverse order that they are played, the
#value of the most recent move (which we generated in gtp_test) will be the first one.
#This is the value we want to check for size.
if next_move=='black':
next_move='W'
else:
next_move='B'
#I am making an assumption here, that the last person to move is going to win the game.
#It seems silly for a player to make a move and then resign, but it is not an impossibility.
#Therefore, if you need that extra bit of accuracy, you can make some minor modifications
#to check the estimated score regardless of whether the game ended in resign or not, and
#use that as a sign of who won.
game_result = next_move+'+R'
if float(move_value)<2:
#If the value of the move generated by GnuGo is less than 2, then it is clear that the late
#endgame has been reached, and the game is probably over. In this case, we will use GnuGo
#to calculate the relative score.
result_string = os.popen('gnugo -l '+target+' --score estimate').read()
winning_color = result_string[:1]
score_estimate = sre.findall('(\d.\d)',result_string)[0]
game_result = winning_color+'+'+score_estimate
print game_result
sgf_raw = file(target,'r')
file_dump = sgf_raw.read()
file_dump = sre.sub(RE_PREFIX,PREFIX+game_result+']',file_dump)
sgf_write=file(target,'w')
sgf_write.write(file_dump)
sgf_write.flush()
sgf_write.close()
os.remove('gtp_test')
#Remove the old gtp_test.
except IndexError:
print "Error with SGF "+target+". Deleting ..."
error_log = file('error_log','a')
error_log.write("Error on "+target+". Deleting file.\n")
error_log.flush()
error_log.close()
os.remove(target)
#Uncomment previous line if you would like to keep illegal SGF's.
except Exception:
print "Error. Skipping ..."
print Exception
error_log = file('error_log','a')
error_log.write("Error on "+target+". Skipping file.\n")
error_log.flush()
error_log.close()
except Error:
print "Error. Skipping ..."
print Error
error_log = file('error_log','a')
error_log.write("Error on "+target+". Skipping file.\n")
error_log.flush()
error_log.close()
error_log = file('error_log','w')
error_log.write("Starting error log...\n")
error_log.flush()
error_log.close()
scanSGF('/home/hikaru79/Desktop/IGS')
_______________________________________________
computer-go mailing list
computer-go@xxxxxxxxxxxxxxxxx
http://www.computer-go.org/mailman/listinfo/computer-go/