webgo/goban.py

196 lines
6.7 KiB
Python
Raw Normal View History

2005-09-06 19:52:46 +02:00
#!/usr/bin/python
DEBUG = 1
2005-09-06 19:52:46 +02:00
import sys,string
import cgi
import psql,helper,gnugo
2005-09-06 19:52:46 +02:00
picklefile = "goban.pickledump"
###############################################################################
def display_goban(goban,req,form):
2005-09-06 19:52:46 +02:00
"""
gets: dictionary containing the layout of the used goban.
returns: string containing the HTML code for a clickable goban.
"""
data = ""
hoshis19x19 = [(4,4),(4,10),(4,16),(10,4),(10,10),(10,16),(16,4),(16,10),(16,16)]
hoshis13x13 = [(4,4),(4,10),(7,7),(10,4),(10,10)]
hoshis9x9 = [(3,3),(3,7),(5,5),(7,3),(7,7)]
data += '\n<p>\n<form method="post">\n'
data += """<input type="hidden" name="sessionid" value="%s">
<input type="hidden" name="username" value="%s">
<input type="hidden" name="game" value="%s">
""" % (form["sessionid"],form["username"],form["game"])
2005-09-06 19:52:46 +02:00
try:
size = goban["size"]
except:
#TODO: proper error management
raise "[EE] display_goban: got broken goban dictionary."
sys.exit(1)
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:
stone = "_white"
elif goban[(x,y)] == 2:
stone = "_black"
else:
stone = ""
sx = str(x)
sy = str(y)
# check position:
if (x == 1) and (y == 1): # upper left
data += '<input type=image id="goban" src="img/topleftline'+stone+'.png" name="('+sx+','+sy+')"\n>'
2005-09-06 19:52:46 +02:00
elif (x == 1) and (y == size): # upper right
data += '<input type=image id="goban" src="img/toprightline'+stone+'.png" name="('+sx+','+sy+')"\n><br\n>'
2005-09-06 19:52:46 +02:00
elif (x == size) and (y == size): # lower right
data += '<input type=image id="goban" src="img/bottomrightline'+stone+'.png" name="('+sx+','+sy+')"\n><br>\n'
2005-09-06 19:52:46 +02:00
elif (x == size) and (y == 1): # lower left
data += '<input type=image id="goban" src="img/bottomleftline'+stone+'.png" name="('+sx+','+sy+')"\n>'
2005-09-06 19:52:46 +02:00
elif (y == 1): #left line
data += '<input type=image id="goban" src="img/leftline'+stone+'.png" name="('+sx+','+sy+')"\n>'
2005-09-06 19:52:46 +02:00
elif (x == 1): # top line
data += '<input type=image id="goban" src="img/topline'+stone+'.png" name="('+sx+','+sy+')"\n>'
2005-09-06 19:52:46 +02:00
elif (y == size): # right line
data += '<input type=image id="goban" src="img/rightline'+stone+'.png" name="('+sx+','+sy+')"\n><br\n>'
2005-09-06 19:52:46 +02:00
elif (x == size): #bottom line
data += '<input type=image id="goban" src="img/bottomline'+stone+'.png" name="('+sx+','+sy+')"\n>'
2005-09-06 19:52:46 +02:00
else: # hoshi or empty inner field
defaultfield = '<input type=image id="goban" src="img/centerline'+stone+'.png" name="('+sx+','+sy+')"\n>'
2005-09-06 19:52:46 +02:00
#too lazy to make special images for hoshi fields with stones:
if goban[(x,y)] == 1:
hoshifield = '<input type=image id="goban" src="img/centerline_white.png" name="('+sx+','+sy+')"\n>'
2005-09-06 19:52:46 +02:00
elif goban[(x,y)] == 2:
hoshifield = '<input type=image id="goban" src="img/centerline_black.png" name="('+sx+','+sy+')"\n>'
2005-09-06 19:52:46 +02:00
else: #empty hoshi
hoshifield = '<input type=image id="goban" src="img/hoshi.png" name="('+sx+','+sy+')"\n>'
2005-09-06 19:52:46 +02:00
if size == 19: # 9 hoshis
if (x,y) in hoshis19x19:
data += hoshifield
else:
data += defaultfield
elif size == 13:
if (x,y) in hoshis13x13:
data += hoshifield
else:
data += defaultfield
elif size == 9:
if (x,y) in hoshis9x9:
data += hoshifield
else:
data += defaultfield
data += '\n<input type="hidden" name="play" value="foo">'
data += '\n</form></p>'
2005-09-06 19:52:46 +02:00
return data
2005-09-06 19:52:46 +02:00
def process_form(req,form,gobandict):
2005-09-06 19:52:46 +02:00
"""
gets a goban dictionary.
reads out the returned CGI form.
if the goban has been clicked, return a (x,y) tuple of the position.
"""
ret = ""
2005-09-06 19:52:46 +02:00
#if form == empty (which means if page is displayed for the first time):
if form.keys() != []:
#cut out the name of the clicked button
for item in form.keys():
if string.find(item,").x")>0:
coordstring = string.split(item,".x")[0]
position = helper.string_to_tuple(coordstring)
ret = set_stone(gobandict, position,req,form)
return ret
2005-09-06 19:52:46 +02:00
def set_stone(gobandict, position,req,form):
2005-09-06 19:52:46 +02:00
"""gets a goban dictionary and a (x,y)-tuple. Returns a modified goban."""
size = gobandict["size"]
name = gobandict["name"]
turn = gobandict["turn_number"]
if (gobandict[position] == 0): #empty field
if gnugo.is_legal(gobandict,position,req,form): #gnugo says the move is ok
#let gnugo make the above move, let gnugo write move to file
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]))
return ""
else: #move not ok
return "This is not a legal move (says Gnugo)."
else: #position not empty
2005-09-06 19:52:46 +02:00
return "Could not make move: Field not empty."
def update_goban_dict_and_table(gobandict,gobanlite):
"""
gets a gobandict and a gobdict light (just coordinates and size).
updates the fields in gobandict and database.
returns changed gobandict and True (or False) if something has been changed (or not).
"""
tf = False
for key in gobanlite.keys():
if gobandict[key] != gobanlite[key]:
#found difference in dicts.
#update gobandict
gobandict[key] = gobanlite[key]
#update databse table. the only valid difference can be changed goban field positions.
psql.update_goban_field(gobandict["name"],key[0],key[1],gobandict[key])
tf = True
return gobandict,tf
2005-09-06 19:52:46 +02:00
###############################################################################
def main(gamename):
2005-09-06 19:52:46 +02:00
# Print the required header that tells the browser how to render the text.
#(currently done by error logger)
#print "Content-Type: text/plain\n\n"
#do stuff
data = helper.header()
#read goban table from database
tmplist = psql.read_table(gamename)
2005-09-06 19:52:46 +02:00
#make a dictionary out of the list
goban = psql.fetchall_list_to_goban_dict(tmplist)
#print goban
(goban,retstring) = process_form(goban)
2005-09-06 19:52:46 +02:00
data += "<p> Turn number: %s, %s Player's Move.</p>" % (goban["turn_number"],("White","Black")[goban["turn_number"] % 2]) #eleet ;>
data += display_goban(goban)
if retstring != "":
data +="\n<p>"+retstring+"</p>\n"
2005-09-06 19:52:46 +02:00
data += helper.footer()
print data