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:
parent
5ab93abaf2
commit
e9d3a9aaaa
5 changed files with 149 additions and 136 deletions
112
gnugo.py
112
gnugo.py
|
@ -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)
|
29
goban.py
29
goban.py
|
@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
###############################################################################
|
||||
|
||||
|
|
72
helper.py
72
helper.py
|
@ -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()
|
||||
|
|
51
playgame.py
51
playgame.py
|
@ -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
21
psql.py
|
@ -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")
|
||||
|
|
Loading…
Reference in a new issue