[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/