247 lines
6.6 KiB
Python
247 lines
6.6 KiB
Python
import string,sys,popen2
|
|
import helper,filehandling
|
|
|
|
gnugocommand = "/usr/games/gnugo --mode gtp"
|
|
|
|
|
|
showboard = """
|
|
=
|
|
A B C D E F G
|
|
7 . . . . . . . 7
|
|
6 . . . . . . . 6
|
|
5 . . + . + . . 5
|
|
4 . . X X . . . 4
|
|
3 . . O . + . . 3
|
|
2 . . . . . . . 2 WHITE (O) has captured 0 stones
|
|
1 . . . . . . . 1 BLACK (X) has captured 0 stones
|
|
A B C D E F G
|
|
|
|
"""
|
|
|
|
|
|
|
|
def is_int( str ):
|
|
""" Is the given string an integer? """
|
|
ok = 1
|
|
try:
|
|
num = int(str)
|
|
except ValueError:
|
|
ok = 0
|
|
return ok
|
|
|
|
|
|
def showboard_to_goban_dict(showboard):
|
|
"""
|
|
gets a string containing the result of the 'showboard' command from
|
|
gnugo --mode gtp.
|
|
returns a goban dictionary .
|
|
"""
|
|
gobandict= {}
|
|
|
|
showboardlist = string.split(showboard,'\n')
|
|
while '' in showboardlist:
|
|
showboardlist.remove('')
|
|
#remove '='
|
|
if string.find(showboardlist[0],"=")>=0:
|
|
showboardlist.remove(showboardlist[0])
|
|
#get boardsize
|
|
tmplist = string.split(showboardlist[0]," ")
|
|
while '' in tmplist:
|
|
tmplist.remove('')
|
|
boardsize = len(tmplist)
|
|
#remove first A B C D ...
|
|
showboardlist.remove(showboardlist[0])
|
|
#remove last A B C D ...
|
|
showboardlist.remove(showboardlist[-1])
|
|
|
|
for i in range(0,boardsize):
|
|
#make string to list
|
|
linelist = string.split(showboardlist[i],' ')
|
|
#clean list from '' entries
|
|
while '' in linelist:
|
|
linelist.remove('')
|
|
# remove numbers
|
|
for p in range(0,boardsize+1):
|
|
if is_int(linelist[p]):
|
|
linelist.remove(linelist[p])
|
|
#print linelist,'\n'
|
|
|
|
#now fill dictionary:
|
|
for j in range(0,boardsize):
|
|
if (linelist[j] == ".") or (linelist[j] == "+"):
|
|
gobandict[(i+1,j+1)] = 0 #empty
|
|
if linelist[j] == "O":
|
|
gobandict[(i+1,j+1)] = 1 #white stone
|
|
if linelist[j] == "X":
|
|
gobandict[(i+1,j+1)] = 2 #black stone
|
|
|
|
#check for info of caputered stones:
|
|
if len(linelist) > boardsize:
|
|
if 'WHITE' in linelist:
|
|
whitecapture = "white has captured %s stones." % linelist[-2]
|
|
#print whitecapture
|
|
elif 'BLACK' in linelist:
|
|
blackcapture = "black has captured %s stones." % linelist[-2]
|
|
gobandict["size"] = boardsize
|
|
|
|
return gobandict
|
|
|
|
def sgf_to_goban_dict(gobandict, filename=""):
|
|
"""
|
|
gets a goban dictionary and optionally a temporary filename.
|
|
saves string to file, loads in gnugo, does showboard, convert showboard to gobandict.
|
|
return gobandict 'lite' (just coordinates and size)
|
|
"""
|
|
sgf = gobandict["sgf"]
|
|
#generate tmpfile
|
|
if filename == "":
|
|
filename = filehandling.gen_temp_file()
|
|
#write sgf data to file
|
|
filehandling.write_file(filename,sgf)
|
|
#open connection to gnugo:
|
|
conn = GTP_connection(gnugocommand)
|
|
#load sgf file in gnugo
|
|
result = conn.exec_cmd("loadsgf "+filename)
|
|
#make move (looks like 'play black F2'
|
|
result = conn.exec_cmd("showboard")
|
|
#convert to goban dict
|
|
ret = showboard_to_goban_dict(result)
|
|
result = conn.exec_cmd("quit")
|
|
return ret
|
|
|
|
|
|
### GTP_connection is based on twogtp.py packaged with gnugo.
|
|
class GTP_connection:
|
|
"""
|
|
gets a program call string, opens an interactive session with
|
|
program called with 'program'. GTP_connection.exec_cmd(command)
|
|
returns result of command.
|
|
#
|
|
# Class members:
|
|
# outfile File to write to
|
|
# infile File to read from
|
|
"""
|
|
def __init__(self, command):
|
|
try:
|
|
infile, outfile = popen2.popen2(command)
|
|
except:
|
|
print "popen2 failed"
|
|
self.infile = infile
|
|
self.outfile = outfile
|
|
|
|
def exec_cmd(self, cmd):
|
|
self.outfile.write(cmd + "\n\n")
|
|
self.outfile.flush()
|
|
result = ""
|
|
line = self.infile.readline()
|
|
while line != "\n":
|
|
result = result + line
|
|
line = self.infile.readline()
|
|
# Remove trailing newline from the result
|
|
if result[-1] == "\n":
|
|
result = result[:-1]
|
|
if len(result) == 0:
|
|
return "ERROR: len = 0"
|
|
if (result[0] == "?"):
|
|
return "ERROR: GTP Command failed: " + result[2:]
|
|
if (result[0] == "="):
|
|
return result[2:]
|
|
return "ERROR: Unrecognized answer: " + result
|
|
|
|
|
|
def is_legal(gobandict,coords,req,form):
|
|
"""
|
|
gets a goban dict and a (x,y) tuple.
|
|
tests wether proposed move is legal.
|
|
returns True or False.
|
|
"""
|
|
size = gobandict["size"]
|
|
turn = gobandict["turn_number"]
|
|
#who's turn is it?
|
|
color = ["white","black"][turn % 2] #even turn: white plays, else black plays
|
|
#convert given coordinates
|
|
gnucoords = " " + helper.dict_coords_to_gnugo_coords(coords,size)
|
|
#open connection to gnugo:
|
|
conn = GTP_connection(gnugocommand)
|
|
result = conn.exec_cmd("is_legal "+ color +gnucoords)
|
|
if result == "1":
|
|
return True
|
|
else:
|
|
return False
|
|
result = conn.exec_cmd("quit")
|
|
|
|
|
|
def create_sgf_file(size, filename=""):
|
|
"""
|
|
gets: board size, optionally a temporary filename to use.
|
|
returns the content of an empty sgf file.
|
|
"""
|
|
conn = GTP_connection(gnugocommand)
|
|
result = conn.exec_cmd("boardsize "+str(size))
|
|
if filename == "":
|
|
filename = filehandling.gen_temp_file()
|
|
result = conn.exec_cmd("printsgf "+filename)
|
|
ret = filehandling.read_file(filename)
|
|
result = conn.exec_cmd("quit")
|
|
return ret
|
|
|
|
|
|
def make_move_in_sgf(req,form,gobandict,coords,filename = ""):
|
|
"""
|
|
gets: goban dict, (x,y) tuple for move, optionally a filename for tempfile.
|
|
writes the string to a file, opens gnugo, makes the move, writes new sgf
|
|
to temporary file, reads content of temporary file.
|
|
returns: sgf string of new file.
|
|
"""
|
|
size = gobandict["size"]
|
|
turn = gobandict["turn_number"]
|
|
sgf = gobandict["sgf"]
|
|
|
|
#convert given coordinates
|
|
gnucoords = " " + helper.dict_coords_to_gnugo_coords(coords,size)
|
|
# get current player
|
|
#even turn: white plays, else its blacks turn
|
|
color = ["white","black"][turn % 2]
|
|
helper.debug(req,form,"color: %s -- turn: %s " % (color,turn))
|
|
#generate tmpfile
|
|
if filename == "":
|
|
filename = filehandling.gen_temp_file()
|
|
#write sgf data to file
|
|
filehandling.write_file(filename,sgf)
|
|
#open connection to gnugo:
|
|
conn = GTP_connection(gnugocommand)
|
|
#load sgf file in gnugo
|
|
result = conn.exec_cmd("loadsgf "+filename)
|
|
#make move (looks like 'play black F2'
|
|
result = conn.exec_cmd("play "+color+gnucoords)
|
|
#save result to file
|
|
result = conn.exec_cmd("printsgf "+filename)
|
|
#read out new file
|
|
sgf = filehandling.read_file(filename)
|
|
result = conn.exec_cmd("quit")
|
|
return sgf
|
|
|
|
|
|
if __name__ == '__main__':
|
|
#showboard_to_goban_dict(showboard)
|
|
import popen2
|
|
|
|
conn = GTP_connection("gnugo --mode gtp")
|
|
result = conn.exec_cmd("boardsize 7")
|
|
result = conn.exec_cmd("genmove black")
|
|
result = conn.exec_cmd("genmove white")
|
|
result = conn.exec_cmd("printsgf test.sgf")
|
|
result = conn.exec_cmd("quit")
|
|
conn = GTP_connection("gnugo --mode gtp")
|
|
result = conn.exec_cmd("loadsgf test.sgf")
|
|
result = conn.exec_cmd("showboard")
|
|
print result,"\n----\n"
|
|
print showboard_to_goban_dict(result)
|
|
print create_sgf_file(7)
|
|
|
|
|
|
#loadsgf
|
|
#printsgf
|
|
#is_legal black F2
|
|
#dict_coords_to_gnugo_coords(coords) translates (6,6) to "F2"
|
|
|