def POST(self, game_id):
    you = require_you()
    game = get_game(game_id)

    params = web.input(from_space=None, to_space=None)
    if not (params["from_space"] and params["to_space"]):
      raise http.badrequest("Moves must include from_space and to_space")

    from_space = tag_2d(params["from_space"])
    to_space   = tag_2d(params["to_space"])
    
    if not (len(from_space) == len(to_space) == 2):
      raise http.badrequest("Invalid space tags")

    # check if it's your turn
    player = game["order"][game["turn"] % len(game["order"])]
    if game["players"][player] != you.id:
      raise http.precondition("It's not your turn")

    board = game["board"]
    attacking_piece = game["board"][from_space[0]][from_space[1]]

    if attacking_piece == None:
      raise http.forbidden("No piece to move from %s" % params["from_space"])

    if attacking_piece["player"] != player:
      raise http.forbidden("It's not %s's turn" % attacking_piece["player"])

    if not valid_move(attacking_piece["kind"], from_space, to_space):
      raise http.forbidden("You can't move %s from %s to %s" % (attacking_piece["kind"], params["from_space"], params["to_space"]))
    
    defending_piece = game["board"][to_space[0]][to_space[1]]
    if defending_piece != None:
    
      if attacking_piece["player"] == defending_piece["player"]:
        raise http.forbidden("You can't attack yourself")
    
      if not battle(attacking_piece["kind"], defending_piece["kind"]):
        raise http.forbidden("You can't beat %s with %s" % (defending_piece["kind"], attacking_piece["kind"]))
      
    # actually move the piece
    game["board"][from_space[0]][from_space[1]] = None
    game["board"][to_space[0]][to_space[1]] = attacking_piece
    
    # advance the turn
    game["turn"] += 1

    # trigger an event
    move = {"type":"move", "game":game_id, "user":you.id, "name":you["name"],
            "from_space":params["from_space"], "to_space":params["to_space"]}
    
    # update timestamps just before saving
    game["timestamp"] = move["timestamp"] = timestamp = make_timestamp()    
    db[game_id] = game
    move_id = db.create(move)
      
    return timestamp
  def POST(self, game_id):
    you = require_you()
    game = get_game(game_id)

    params = web.input(text='')
    text = params["text"]
    if len(text) == 0:
      raise http.unacceptable("Chat messages must contain some text")

    chat = {"type":"chat", "text":text, "game":game_id, "user":you.id, "name":you["name"]}
    
    # synchronize timestamps
    game["timestamp"] = chat["timestamp"] = make_timestamp()    
    db[game_id] = game
    db.create(chat)
    return "OK"
  def POST(self):
    you = require_you()
    params = web.input()

    if not params["user"]:
      return web.notfound()
    
    user = dbview.users(db, startkey=params['user'], endkey=params['user']).rows
    if not len(user):
      return web.notfound()
    else:
      user = user[0]
    
    from setup_board import board
    game = {"type":"game", "board":board, "timestamp":make_timestamp(), "turn":0, 
            "players":{"red":you.id,"blue":user.id}, "order":["red","blue"]}
    game_id = db.create(game)
    web.seeother("/games/%s" % game_id)