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
gnugocommand = "/usr/games/gnugo --mode gtp"
@ -155,10 +155,15 @@ def is_legal(gobandict,coords,req,form):
tests wether proposed move is legal.
returns True or False.
"""
size = gobandict["size"]
"""size = gobandict["size"]
turn = gobandict["turn_number"]
#who's turn is it?
color = ["white","black"][turn % 2] #even turn: white plays, else black plays
"""
gamename = gobandict["name"]
color = gobandict["play"]
size = gobandict["size"]
#convert given coordinates
gnucoords = " " + helper.dict_coords_to_gnugo_coords(coords,size)
#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)
# get current player
#even turn: white plays, else its blacks turn
"""
color = ["white","black"][turn % 2]
"""
color = gobandict["play"]
helper.debug(req,form,"color: %s -- turn: %s " % (color,turn))
#generate tmpfile
if filename == "":
@ -221,6 +229,88 @@ def make_move_in_sgf(req,form,gobandict,coords,filename = ""):
result = conn.exec_cmd("quit")
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__':
#showboard_to_goban_dict(showboard)
@ -245,3 +335,21 @@ if __name__ == '__main__':
#is_legal black 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">
""" % (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:
size = goban["size"]
except:
@ -39,9 +43,9 @@ def display_goban(goban,req,form):
for x in range(1,size+1):
for y in range(1,size+1):
# check for white or black stone
if goban[(x,y)] == 1:
if gobandict[(x,y)] == 1:
stone = "_white"
elif goban[(x,y)] == 2:
elif gobandict[(x,y)] == 2:
stone = "_black"
else:
stone = ""
@ -67,9 +71,9 @@ def display_goban(goban,req,form):
else: # hoshi or empty inner field
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:
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>'
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>'
else: #empty hoshi
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)
#write new sgf file into database
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)
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]))
psql.update_turn_number(name,turn+1)
return ""
else: #move not ok
return "This is not a legal move (says Gnugo)."
@ -165,7 +157,8 @@ def update_goban_dict_and_table(gobandict,gobanlite):
psql.update_goban_field(gobandict["name"],key[0],key[1],gobandict[key])
tf = True
return gobandict,tf
###############################################################################

View file

@ -101,83 +101,13 @@ def dict_coords_to_gnugo_coords(coords,size):
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():
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__":
test()

View file

@ -1,4 +1,4 @@
import goban,helper,psql,login
import goban,helper,psql,login,gnugo
import string
DEBUG = 1
@ -9,31 +9,32 @@ def is_my_turn(req,form,gobandict):
check wether or not the current this is the players turn.
return true or false.
"""
#INFO: player1 is black,player2 is white. black starts the game.
me = form["username"]
player1 = gobandict["player1"]
player2 = gobandict["player2"]
#get turn_number.
turn_number = gobandict["turn_number"]
#if player 2 can play: are we player two?
# yes:return True, else return False
if turn_number % 2 == 0:
if me == player2:
return True
else:
return False
#else:are we player1?
# yes:return True, else return False
else:
if me == player1:
return True
else:
return False
play = gobandict["play"]
if ((player1 == me) and (play == "white")) or ((player2 == me) and (play == "black")):
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):
"""
@ -48,10 +49,7 @@ def main(req,form):
data = ""
req.write(helper.header())
#helper.debug(req,form,str(form.keys()))
#read goban table from database
tmplist = psql.read_table(gamename)
#make a dictionary out of the list
gobandict = psql.fetchall_list_to_goban_dict(tmplist)
gobandict = create_gobandict(req,form,gamename)
#check if user has already clicked onto a field:
click_on_field = False
for item in form.keys():
@ -66,11 +64,12 @@ def main(req,form):
helper.debug(req,form,"playgame.main says: "+str(retstring))
else:
#reload gobandict, it has been changed.
gobandict = psql.fetchall_list_to_goban_dict(psql.read_table(gamename))
gobandict = create_gobandict(req,form,gamename)
else:
helper.debug(req,form,"its not my turn.")
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
#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.
the table looks like this:
line x1 x2 x3 x4 ... x(size)
y1
y2
y3
...
y(size)
line x1
turn_number
size
name
@ -53,7 +48,6 @@ def create_goban_table(player1,player2,size):
sgf
and the meaning of these fields:
(xn,yn) is a field of the goban,
(turn_number,x1) is the current turn,
(size,x1) is the length of a side of the 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()
data="line text"
for i in range(1,size+1):
if data != "":
data += ", "
data += "x"+str(i) + ' text'
data = "x1 text"
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
tmplist=[]
tmplist.append("turn_number")