import string, random from game import * import web from google.appengine.ext import db ############################################################################## # vars ####################################################################### ############################################################################## ourcarddata = { "l": "Luggage", "r": "Crown", "d": "The Diplomatic Bag", "n": "Jewels", "m": "Camera", "a": "Watch", "p": "Ring", "b": "Champagne", "c": "Cigarettes", "w": "Wine"} ourcardimagedata = { "l": "luggage", "r": "crown", "d": "diplomaticbag", "n": "jewels", "m": "camera", "a": "watch", "p": "ring", "b": "champagne", "c": "cigarettes", "w": "wine"} carddata = {} for k, v in ourcarddata.items(): carddata[k] = [v, DUTY["green"][k], DUTY["red"][k], ourcardimagedata[k], None] carddata["l"][4] = "no duty required" carddata["d"][4] = "no duty, just declare the diplomatic bag" ############################################################################## # models ##################################################################### ############################################################################## class DBGame(db.Model): date_created = db.DateTimeProperty(auto_now_add=True) deck = db.StringProperty() class DBPlayer(db.Model): name = db.StringProperty() email = db.StringProperty() game = db.ReferenceProperty(DBGame) random = db.StringProperty() joined = db.BooleanProperty(default=False) playorder = db.IntegerProperty() def display(self): if self.name: return web.websafe(self.name) else: return web.websafe(self.email.split("@")[0]) def url(self): return web.websafe("/play/%s/%s/" % (self.game.key(), self.random)) class DBMove(db.Model): player = db.ReferenceProperty(DBPlayer) game = db.ReferenceProperty(DBGame) occurred = db.DateTimeProperty(auto_now_add=True) move = db.StringProperty() param = db.StringProperty() comment = db.TextProperty() def display(self): if self.move == "declare": return ["%s declared " % self.player.display(), self.param, self.comment] elif self.move == "accept": return ["%s accepted the declaration" % self.player.display(), None, self.comment] elif self.move == "challenge": return ["%s challenged the declaration" % self.player.display(), None, self.comment] elif self.move == "discard": return ["%s discarded a card" % self.player.display(), None, self.comment] else: return ["", None, self.comment] ############################################################################# # views ##################################################################### ############################################################################# class homepage: def GET(self): return render.homepage() class newgame: def GET(self): return render.newgame(errors=[]) def POST(self): names = [("name%s" % i, None) for i in range(1,11)] emails = [("email%s" % i, None) for i in range(1,11)] items = dict(names + emails) rq = web.input(**items) players = [] nameplayers = [] for i in range(1,11): email = rq["email%s" % i] if email: players.append(email) nameplayers.append((rq["name%s" % i], email)) try: game = Game(players) except InsufficientPlayersException: return render.newgame(errors=["You must specify a minimum of three players"]) except EmailAddressInvalidException, e: return render.newgame(errors=["Email address '%s' is not a correct address" % e.bademail]) except EmailAddressRepeatedException, e: return render.newgame(errors=["Two players cannot have the same email address '%s'" % e.bademail]) # create game object in DB dbgame = DBGame() dbgame.deck = game.original_deck dbgame.put() # create player objects count = 1 for name, email in nameplayers: dbplayer = DBPlayer() dbplayer.game = dbgame dbplayer.name = name dbplayer.email = email # assign players random strings dbplayer.random = ''.join([random.choice(string.lowercase) for x in range(10)]) dbplayer.playorder = count count += 1 dbplayer.put() # email each player FIXME return render.newgame_begin(dbgame, nameplayers) class browse: def GET(self, gameid=None): if not gameid: games = db.GqlQuery("SELECT * FROM DBGame ORDER BY date_created DESC") return render.gamelist(games) else: key = db.Key(encoded=gameid) dbgame = DBGame.get(key) if dbgame: playerset = dbgame.dbplayer_set.order("playorder") players = [x.email for x in playerset] game = Game(players=players, deck=dbgame.deck) for m in dbgame.dbmove_set.order("occurred"): game.move(m.player.email, m.move, m.param) return render.game(game, dbgame, carddata) else: return "no such game go away" class play: def GET(self, gameid, playerkey): key = db.Key(encoded=gameid) dbgame = DBGame.get(key) if not dbgame: return "no such game go away" dbplayer = None playerset = dbgame.dbplayer_set.order("playorder") for dbplayerp in playerset: if dbplayerp.random == playerkey: dbplayer = dbplayerp break if not dbplayer: return "you're not in this game go away" if not dbplayer.joined: return render.join(dbgame, dbplayer) for dbplayerp in playerset: if not dbplayerp.joined: raise web.seeother("/browse/%s/" % dbgame.key()) # everyone has joined! # create the game and play all the moves players = [x.email for x in playerset] game = Game(players=players, deck=dbgame.deck) for m in dbgame.dbmove_set.order("occurred"): game.move(m.player.email, m.move, m.param) if game.state.move == "end": raise web.seeother("/browse/%s/" % dbgame.key()) if game.state.player.email == dbplayer.email: # get the details of the last two moves in case they're required antepenultimate = None penultimate = None for m in dbgame.dbmove_set.order("occurred"): antepenultimate = penultimate penultimate = m return render.yourmove(game, dbgame, antepenultimate, penultimate, carddata) else: for dbplayerp in playerset: if game.state.player.email == dbplayerp.email: dbplayer_to_play = dbplayerp return render.othermove(game, dbgame, dbplayer_to_play) class join: def POST(self, gameid, playerkey): key = db.Key(encoded=gameid) dbgame = DBGame.get(key) if not dbgame: return "no such game go away" dbplayer = None playerset = dbgame.dbplayer_set.order("playorder") for dbplayerp in playerset: if dbplayerp.random == playerkey: dbplayer = dbplayerp break if not dbplayer: return "you're not in this game go away" rq = web.input(join=None) if not rq.join: raise web.seeother("/browse/%s/" % dbgame.key()) if rq.join == "No": # abandon game! FIXME # mail other players to say game is abandoned FIXME raise web.seeother("/browse/%s/" % dbgame.key()) if rq.join == "Yes": dbplayer.joined = True dbplayer.put() # mail other players to say you have joined FIXME raise web.seeother("/browse/%s/" % dbgame.key()) return "bad input go away" class move: def POST(self, gameid, playerkey): key = db.Key(encoded=gameid) dbgame = DBGame.get(key) if not dbgame: return "no such game go away" dbplayer = None playerset = dbgame.dbplayer_set.order("playorder") for dbplayerp in playerset: if dbplayerp.random == playerkey: dbplayer = dbplayerp break if not dbplayer: return "you're not in this game go away" # create game and play through all moves to date playerset = dbgame.dbplayer_set.order("playorder") players = [x.email for x in playerset] game = Game(players=players, deck=dbgame.deck) for m in dbgame.dbmove_set.order("occurred"): game.move(m.player.email, m.move, m.param) # try this move rq = web.input(move="invalid", param=None, card1="", card2="", card3="", card4="", comment="") param = "%s%s%s%s" % (rq.card1, rq.card2, rq.card3, rq.card4) # special for declare if not param: param = rq.param try: game.move(dbplayer.email, rq.move, param) except Exception, e: return render.badmove(dbgame, dbplayer, str(e)) dbmove = DBMove() dbmove.game = dbgame dbmove.player = dbplayer dbmove.move = rq.move dbmove.param = param dbmove.comment = rq.comment dbmove.put() # mail other players to say you have moved FIXME if rq.move == "discard": # they have just discarded a card, so it's their move again # so, force-redirect them back to the their-move screen raise web.seeother(dbplayer.url()) return render.move(dbgame, dbplayer) ############################################################################# # setup ##################################################################### ############################################################################# urls = ( '/', 'homepage', '/newgame/', 'newgame', '/browse/(.*)/', 'browse', '/browse/', 'browse', '/play/(.+)/(.+)/', 'play', '/play/(.+)/(.+)/join', 'join', '/play/(.+)/(.+)/move', 'move', ) render = web.template.render('templates/', base="base") app = web.application(urls, globals()) main = app.cgirun()