webgo/gnugo.py

248 lines
6.6 KiB
Python
Raw Normal View History

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"