before this change WebGo had 2 represenations of the goban simultaneously (one in sgf and the other as a table in the database). This was just too ugly, even for me. Now all relevant functions use the parser from the last commit.It seems to work ...

This commit is contained in:
phear 2005-10-09 17:27:17 +00:00
parent 5ab93abaf2
commit e9d3a9aaaa
5 changed files with 149 additions and 136 deletions

112
gnugo.py
View file

@ -1,4 +1,4 @@
import string,sys,popen2 import string,sys,popen2,re
import helper,filehandling import helper,filehandling
gnugocommand = "/usr/games/gnugo --mode gtp" gnugocommand = "/usr/games/gnugo --mode gtp"
@ -155,10 +155,15 @@ def is_legal(gobandict,coords,req,form):
tests wether proposed move is legal. tests wether proposed move is legal.
returns True or False. returns True or False.
""" """
size = gobandict["size"] """size = gobandict["size"]
turn = gobandict["turn_number"] turn = gobandict["turn_number"]
#who's turn is it? #who's turn is it?
color = ["white","black"][turn % 2] #even turn: white plays, else black plays color = ["white","black"][turn % 2] #even turn: white plays, else black plays
"""
gamename = gobandict["name"]
color = gobandict["play"]
size = gobandict["size"]
#convert given coordinates #convert given coordinates
gnucoords = " " + helper.dict_coords_to_gnugo_coords(coords,size) gnucoords = " " + helper.dict_coords_to_gnugo_coords(coords,size)
#open connection to gnugo: #open connection to gnugo:
@ -201,7 +206,10 @@ def make_move_in_sgf(req,form,gobandict,coords,filename = ""):
gnucoords = " " + helper.dict_coords_to_gnugo_coords(coords,size) gnucoords = " " + helper.dict_coords_to_gnugo_coords(coords,size)
# get current player # get current player
#even turn: white plays, else its blacks turn #even turn: white plays, else its blacks turn
"""
color = ["white","black"][turn % 2] color = ["white","black"][turn % 2]
"""
color = gobandict["play"]
helper.debug(req,form,"color: %s -- turn: %s " % (color,turn)) helper.debug(req,form,"color: %s -- turn: %s " % (color,turn))
#generate tmpfile #generate tmpfile
if filename == "": if filename == "":
@ -221,6 +229,88 @@ def make_move_in_sgf(req,form,gobandict,coords,filename = ""):
result = conn.exec_cmd("quit") result = conn.exec_cmd("quit")
return sgf return sgf
def parse_static_gnugo_sgf(s):
"""
gets a string containing the data saved by the gnugo "printsgf" order.
"""
#dicitonary to return
ret = {}
#removing newlines vom given string
s = s.replace("\r\n","") #windoze
s = s.replace("\n","") #unix
#getting the board size
# looks like SZ[19]
# the pattern finds a number ([0-9]) with length (1-2) between "SZ[" and "]"
boardsize = re.search("SZ\[([0-9]{1,2})\]",s).groups()[0]
boardsize = int(boardsize)
ret["size"] = boardsize
#now fill ret with default values (== 0):
for i in range (1,boardsize+1):
for k in range (1,boardsize+1):
ret[(i,k)] = 0
#some regexp patterns:
#(?: ...) groups items
stones = "%s((?:\[[a-z][a-z]\])*)" #dont forget to set %s!
whitestones = stones % "AW"
blackstones = stones % "AB"
#getting white stones
#looks like AW[bb][cb][cc][cd][de][df]
try:
stonestring = re.search(whitestones,s).groups()[0]
except:
#we could not find anything
stonestring = ""
if stonestring != "":
ret = set_stones(stonestring,1,ret)
#getting black stones
try:
stonestring = re.search(blackstones,s).groups()[0]
except:
#we could not find anything
stonestring = ""
if stonestring != "":
ret = set_stones(stonestring,2,ret)
#who's turn is it?
if string.find(s,"PL[B]")>0:
ret["play"] = "black"
else:
ret["play"] = "white"
return ret
def set_stones(stonestring,value,ret):
"""
gets:
- string from sgf file with stone postitions in brackets: '[ab][ac]...'
- value to set
- dictionary to transform
does:
returns:
- dicionary
"""
#create a list of letters
letters = [" "]
letters.extend(list(string.letters)[0:26])
#regexp
stonestolist = "\[([a-z][a-z])\]"
rawlist = re.findall(stonestolist,stonestring)
for item in rawlist:
#fill in specific values
ret[(letters.index(item[1]),letters.index(item[0]))] = value
return ret
if __name__ == '__main__': if __name__ == '__main__':
#showboard_to_goban_dict(showboard) #showboard_to_goban_dict(showboard)
@ -245,3 +335,21 @@ if __name__ == '__main__':
#is_legal black F2 #is_legal black F2
#dict_coords_to_gnugo_coords(coords) translates (6,6) to "F2" #dict_coords_to_gnugo_coords(coords) translates (6,6) to "F2"
#sample output
s = """(;
GM[1]
FF[4]
SZ[19]
GN[GNU Go 3.7.4 load and print]
DT[2005-10-09]
KM[5.5]
RU[Japanese]
AP[GNU Go:3.7.4]
AW[bb][cb][cc][cd][de][df]
[ag][cg][ah][ch][dh][ai][bi][ci]
AB[ba][ab][ac][bc][bd][be][ce][af][cf][bg][bh]
PL[B]
)"""
print parse_static_gnugo_sgf(s)

View file

@ -30,6 +30,10 @@ def display_goban(goban,req,form):
<input type="hidden" name="game" value="%s"> <input type="hidden" name="game" value="%s">
""" % (form["sessionid"],form["username"],form["game"]) """ % (form["sessionid"],form["username"],form["game"])
sgf = psql.get_sgf(form["game"])
helper.debug(req,form,sgf)
gobandict = gnugo.parse_static_gnugo_sgf(sgf)
try: try:
size = goban["size"] size = goban["size"]
except: except:
@ -39,9 +43,9 @@ def display_goban(goban,req,form):
for x in range(1,size+1): for x in range(1,size+1):
for y in range(1,size+1): for y in range(1,size+1):
# check for white or black stone # check for white or black stone
if goban[(x,y)] == 1: if gobandict[(x,y)] == 1:
stone = "_white" stone = "_white"
elif goban[(x,y)] == 2: elif gobandict[(x,y)] == 2:
stone = "_black" stone = "_black"
else: else:
stone = "" stone = ""
@ -67,9 +71,9 @@ def display_goban(goban,req,form):
else: # hoshi or empty inner field else: # hoshi or empty inner field
defaultfield = '<input type=image id="goban" src="img/centerline'+stone+'.png" name="('+sx+','+sy+')"\n>' defaultfield = '<input type=image id="goban" src="img/centerline'+stone+'.png" name="('+sx+','+sy+')"\n>'
#too lazy to make special images for hoshi fields with stones: #too lazy to make special images for hoshi fields with stones:
if goban[(x,y)] == 1: if gobandict[(x,y)] == 1:
hoshifield = '<input type=image id="goban" src="img/centerline_white.png" name="('+sx+','+sy+')"\n>' hoshifield = '<input type=image id="goban" src="img/centerline_white.png" name="('+sx+','+sy+')"\n>'
elif goban[(x,y)] == 2: elif gobandict[(x,y)] == 2:
hoshifield = '<input type=image id="goban" src="img/centerline_black.png" name="('+sx+','+sy+')"\n>' hoshifield = '<input type=image id="goban" src="img/centerline_black.png" name="('+sx+','+sy+')"\n>'
else: #empty hoshi else: #empty hoshi
hoshifield = '<input type=image id="goban" src="img/hoshi.png" name="('+sx+','+sy+')"\n>' hoshifield = '<input type=image id="goban" src="img/hoshi.png" name="('+sx+','+sy+')"\n>'
@ -130,19 +134,7 @@ def set_stone(gobandict, position,req,form):
new_sgf = gnugo.make_move_in_sgf(req,form,gobandict,position) new_sgf = gnugo.make_move_in_sgf(req,form,gobandict,position)
#write new sgf file into database #write new sgf file into database
psql.update_goban_table_field(name,"x1","sgf",new_sgf) psql.update_goban_table_field(name,"x1","sgf",new_sgf)
#...and in current gobandict
gobandict["sgf"] = new_sgf
#now convert sgf to gobandict coordinates.
gobanlite = gnugo.sgf_to_goban_dict(gobandict)
#merge new coordinates with gobandict and update database where necessary
(new_gobandict, something_changed) = update_goban_dict_and_table(gobandict,gobanlite)
#and finally:
if something_changed:
psql.update_turn_number(name,turn+1) psql.update_turn_number(name,turn+1)
helper.debug(req,form,"updated turn b/c gobandict has changed")
else:
helper.debug(req,form,"gobandict has not been changed, leaving turn_number untouched")
helper.debug(req,form,"set_stone:game name: %s, turn: %s, value at position: %s" % (name,turn,new_gobandict[position]))
return "" return ""
else: #move not ok else: #move not ok
return "This is not a legal move (says Gnugo)." return "This is not a legal move (says Gnugo)."
@ -167,6 +159,7 @@ def update_goban_dict_and_table(gobandict,gobanlite):
return gobandict,tf return gobandict,tf
############################################################################### ###############################################################################
def main(gamename): def main(gamename):

View file

@ -101,83 +101,13 @@ def dict_coords_to_gnugo_coords(coords,size):
return letter+str(digit) return letter+str(digit)
def parse_static_gnugo_sgf(s):
"""
gets a string containing the data saved by the gnugo "printsgf" order.
"""
#create a list of letters
letters = [" "]
letters.extend(list(string.letters)[0:26])
#dicitonary to return
ret = {}
#removing newlines vom given string
s = s.replace("\r\n","") #windoze
s = s.replace("\n","") #unix
#getting the board size
# looks like SZ[19]
# the pattern finds a number ([0-9]) with length (1-2) between "SZ[" and "]"
boardsize = re.search("SZ\[([0-9]{1,2})\]",s).groups()[0]
boardsize = int(boardsize)
ret["size"] = boardsize
#some regexp patterns:
#(?: ...) groups items
stones = "%s((?:\[[a-z][a-z]\])*)" #dont forget to set %s!
whitestones = stones % "AW"
blackstones = stones % "AB"
stonestolist = "\[([a-z][a-z])\]"
#getting white stones
#looks like AW[bb][cb][cc][cd][de][df]
stonestring = re.search(whitestones,s).groups()[0]
rawlist = re.findall(stonestolist,stonestring)
for item in rawlist:
#fill in specific values
ret[(letters.index(item[0]),letters.index(item[1]))] = 1
#getting black stones
stonestring = re.search(blackstones,s).groups()[0]
rawlist = re.findall(stonestolist,stonestring)
for item in rawlist:
#fill in specific values
ret[(letters.index(item[0]),letters.index(item[1]))] = 2
#who's turn is it?
if string.find(s,"PL[B]")>0:
ret["player"] = "black"
else:
ret["player"] = "white"
return ret
def test(): def test():
print dict_coords_to_gnugo_coords((6,5),7) print dict_coords_to_gnugo_coords((6,5),7)
#sample output
s = """(;
GM[1]
FF[4]
SZ[19]
GN[GNU Go 3.7.4 load and print]
DT[2005-10-09]
KM[5.5]
RU[Japanese]
AP[GNU Go:3.7.4]
AW[bb][cb][cc][cd][de][df]
[ag][cg][ah][ch][dh][ai][bi][ci]
AB[ba][ab][ac][bc][bd][be][ce][af][cf][bg][bh]
PL[B]
)"""
print parse_static_gnugo_sgf(s)
if __name__ == "__main__": if __name__ == "__main__":
test() test()

View file

@ -1,4 +1,4 @@
import goban,helper,psql,login import goban,helper,psql,login,gnugo
import string import string
DEBUG = 1 DEBUG = 1
@ -9,31 +9,32 @@ def is_my_turn(req,form,gobandict):
check wether or not the current this is the players turn. check wether or not the current this is the players turn.
return true or false. return true or false.
""" """
#INFO: player1 is black,player2 is white. black starts the game.
me = form["username"] me = form["username"]
player1 = gobandict["player1"] player1 = gobandict["player1"]
player2 = gobandict["player2"] player2 = gobandict["player2"]
#get turn_number. play = gobandict["play"]
turn_number = gobandict["turn_number"]
#if player 2 can play: are we player two? if ((player1 == me) and (play == "white")) or ((player2 == me) and (play == "black")):
# yes:return True, else return False
if turn_number % 2 == 0:
if me == player2:
return True return True
else: else:
return False return false
#else:are we player1?
# yes:return True, else return False
else:
if me == player1:
return True
else:
return False
def create_gobandict(req,form,gamename):
"""
gets a gamename
loads sgf, transforms it to dict, writes stuff like player names to dict
returns dict
"""
#read goban table from database
tmplist = psql.read_table(gamename)
#make a dictionary out of the list
tmpdict = psql.fetchall_list_to_goban_dict(tmplist)
sgf = psql.get_sgf(gamename)
gobandict = gnugo.parse_static_gnugo_sgf(sgf)
for key in ["player1","player2","turn_number","name","sgf"]:
gobandict[key] = tmpdict[key]
return gobandict
def main(req,form): def main(req,form):
""" """
@ -48,10 +49,7 @@ def main(req,form):
data = "" data = ""
req.write(helper.header()) req.write(helper.header())
#helper.debug(req,form,str(form.keys())) #helper.debug(req,form,str(form.keys()))
#read goban table from database gobandict = create_gobandict(req,form,gamename)
tmplist = psql.read_table(gamename)
#make a dictionary out of the list
gobandict = psql.fetchall_list_to_goban_dict(tmplist)
#check if user has already clicked onto a field: #check if user has already clicked onto a field:
click_on_field = False click_on_field = False
for item in form.keys(): for item in form.keys():
@ -66,11 +64,12 @@ def main(req,form):
helper.debug(req,form,"playgame.main says: "+str(retstring)) helper.debug(req,form,"playgame.main says: "+str(retstring))
else: else:
#reload gobandict, it has been changed. #reload gobandict, it has been changed.
gobandict = psql.fetchall_list_to_goban_dict(psql.read_table(gamename)) gobandict = create_gobandict(req,form,gamename)
else: else:
helper.debug(req,form,"its not my turn.") helper.debug(req,form,"its not my turn.")
data += """<br>Turn number: %s. %s plays.\n data += """<br>Turn number: %s. %s plays.\n
""" % (str(gobandict["turn_number"]), ["White","Black"][int(gobandict["turn_number"] % 2)]) """ % (str(gobandict["turn_number"]), (string.capitalize(gobandict["play"])))
#check whether its our turn #check whether its our turn
#if yes: print 'your move' and display goban and process move #if yes: print 'your move' and display goban and process move

21
psql.py
View file

@ -39,12 +39,7 @@ def create_goban_table(player1,player2,size):
returns: name of created table. returns: name of created table.
the table looks like this: the table looks like this:
line x1 x2 x3 x4 ... x(size) line x1
y1
y2
y3
...
y(size)
turn_number turn_number
size size
name name
@ -53,7 +48,6 @@ def create_goban_table(player1,player2,size):
sgf sgf
and the meaning of these fields: and the meaning of these fields:
(xn,yn) is a field of the goban,
(turn_number,x1) is the current turn, (turn_number,x1) is the current turn,
(size,x1) is the length of a side of the goban, (size,x1) is the length of a side of the goban,
(name,x1) is the name of this goban. (name,x1) is the name of this goban.
@ -63,19 +57,8 @@ def create_goban_table(player1,player2,size):
""" """
tablename = helper.generate_game_name() tablename = helper.generate_game_name()
data="line text" data="line text"
for i in range(1,size+1): data = "x1 text"
if data != "":
data += ", "
data += "x"+str(i) + ' text'
create_table(tablename,data) create_table(tablename,data)
#table created, now fill the table
for i in range(1,size+1):
tmplist=[]
tmplist.append("y"+str(i))
for k in range(1,size+1):
tmplist.append(0)
insert_into_table(tablename,str(tuple(tmplist)))
#ok, goban itself has been created and filled,
#now insert additional variables #now insert additional variables
tmplist=[] tmplist=[]
tmplist.append("turn_number") tmplist.append("turn_number")