Пример #1
0
    def get(self, gid, cmd):
        """Delegates the request to the corresponding core game operation."""
        gid = int(gid)
        if not 0 <= gid < len(self.application.games):
            raise APIError(Codes.ILLEGAL_RANGE, gid)
        game = self.application.games[gid]

        cmd = int(cmd)
        if cmd == Commands.GET_BOARD:
            self.write(self._get_board(self.user, game))
        elif cmd == Commands.JOIN_GAME:
            colour = self.get_argument("colour")
            game.add_player(self.user, colour)
        elif cmd == Commands.START_GAME:
            game.start_game()
        elif cmd == Commands.CREATE_CLUE:
            clue = StringClue(self.get_argument("clue"))
            card = game.get_card(self.get_argument("cid"))
            game.create_clue(self.user, clue, card)
        elif cmd == Commands.PLAY_CARD:
            card = game.get_card(self.get_argument("cid"))
            game.play_card(self.user, card)
        elif cmd == Commands.CAST_VOTE:
            card = game.get_card(self.get_argument("cid"))
            game.cast_vote(self.user, card)
        elif cmd == Commands.KICK_PLAYER:
            puid = self.get_argument("puid")
            game.kick_player(self.application.users.get_user_by_puid(puid))
        else:
            raise APIError(Codes.ILLEGAL_RANGE, cmd)
Пример #2
0
    def post(self):
        try:
            card_set_indices = list(
                map(int, self.request.arguments["card_sets"]))
        except ValueError as exc:
            raise APIError(Codes.NOT_AN_INTEGER, exc)
        if min(card_set_indices) < 0 or max(card_set_indices) >= len(
                self.application.card_sets):
            raise APIError(Codes.ILLEGAL_RANGE, card_set_indices)
        card_sets = [self.application.card_sets[i] for i in card_set_indices]

        password = self.get_argument("password", "")  # not yet implemented
        if password:
            password = hash_obj(password)
        name = self.get_argument("name", "")
        if not name:
            name = "Game %d" % (len(self.application.games) + 1)

        max_score = self.get_argument("max_score")
        if not max_score:
            max_score = INFINITY
        try:
            max_score = int(max_score)
            max_players = int(self.get_argument("max_players"))
            max_clue_length = int(self.get_argument("max_clue_length"))
            cards_per_person = int(self.get_argument("cards_per_person"))
        except ValueError as exc:
            raise APIError(Codes.NOT_AN_INTEGER, exc)

        limits = self.application.limits
        if ((not limits.min_name <= len(name) <= limits.max_name) or
            (not limits.min_players <= max_players <= limits.max_players)
                or (not limits.min_score <= max_score <= limits.max_score)
                or (not limits.min_clue_length <= max_clue_length <=
                    limits.max_clue_length)):
            raise APIError(Codes.ILLEGAL_RANGE)

        game = Game(
            self.user,
            card_sets,
            password,
            name,
            max_players,
            max_score,
            max_clue_length,
            limits,
            cards_per_person,
        )
        self.application.games.append(game)
        self.application.save()
        self.write(str(len(self.application.games) - 1))
Пример #3
0
    def post(self):
        try:
            gid = int(self.get_argument("gid"))
        except ValueError as exc:
            raise APIError(Codes.NOT_AN_INTEGER, exc)

        try:
            game = self.application.games[gid]
        except IndexError:
            raise APIError(Codes.ILLEGAL_RANGE)

        if self.user != game.host:
            raise APIError(Codes.ILLEGAL_RANGE)

        self.application.games[gid].hide()
        self.write(json.dumps("ok"))
Пример #4
0
 def start_game(self):
     """Transitions from BEGIN to CLUE, or throws APIError."""
     if self.state != States.BEGIN:
         raise APIError(Codes.BEGIN_BAD_STATE)
     if len(self.players) < self.limits.min_players:
         raise APIError(Codes.NOT_ENOUGH_PLAYERS)
     random.shuffle(self.order)
     for user in self.players:
         for _ in range(self.cards_per_person):
             card = self.deck.deal()
             if card is None:
                 self.init_game()  # rewind the dealing
                 raise APIError(Codes.DECK_TOO_SMALL)
             self.players[user].deal(card)
     self.state = States.CLUE
     self.ping()
Пример #5
0
 def add_player(self, user, colour):
     """Adds a user with a given colour to the game, or throws APIError."""
     if self.state != States.BEGIN:
         raise APIError(Codes.BEGIN_BAD_STATE)
     if len(self.players) >= self.max_players:
         raise APIError(Codes.JOIN_FULL_ROOM)
     if not BunnyPalette.is_colour(colour):
         raise APIError(Codes.NOT_A_COLOUR, colour)
     if colour in list(self.colours.values()):
         raise APIError(Codes.COLOUR_TAKEN)
     if user in self.perma_banned:
         raise APIError(Codes.JOIN_BANNED)
     if not user in self.players:  # idempotent
         self.players[user] = Player(user)
         self.order.append(user)
     self.colours[user] = colour  # alow colour changing
Пример #6
0
 def create_clue(self, user, clue, card):
     """Transitions from CLUE to PLAY, or throws APIError."""
     if self.state != States.CLUE:
         raise APIError(Codes.CLUE_BAD_STATE)
     if user != self.clue_maker():
         raise APIError(Codes.CLUE_NOT_TURN)
     if len(clue) < self.limits.min_clue_length:
         raise APIError(Codes.CLUE_TOO_SHORT)
     if len(clue) > self.max_clue_length:
         raise APIError(Codes.CLUE_TOO_LONG)
     if not self.players[user].has_card(card):
         raise APIError(Codes.NOT_HAVE_CARD)
     self.round = Round(self.players, clue, self.clue_maker())
     self.round.play_card(user, card)
     self.players[user].deal(self.deck.deal())
     self.state = States.PLAY
     self.ping()
Пример #7
0
 def kick_player(self, user, is_permanent=False):
     """Kicks a user from the game, or throws APIError."""
     if not user in self.players:
         raise APIError(Codes.KICK_UNKNOWN_USER)
     if len(self.players) <= self.limits.min_players and self.state != States.BEGIN:
         raise APIError(Codes.NOT_ENOUGH_PLAYERS)
     if self.state in (States.PLAY, States.VOTE):
         raise APIError(Codes.KICK_BAD_STATE)
     self.players.pop(user)
     turn = self.order.index(user)
     self.order.remove(user)
     # Readjust turn in case game is currently running
     if self.turn > turn:
         self.turn -= 1
     self.turn %= len(self.players)
     if is_permanent:
         self.perma_banned.add(user)
Пример #8
0
 def play_card(self, user, card):
     """Makes the given user play a card, or throws APIError."""
     if self.state != States.PLAY:
         raise APIError(Codes.PLAY_BAD_STATE)
     if user == self.clue_maker():
         raise APIError(Codes.PLAY_NOT_TURN)
     if not user in self.players:
         raise APIError(Codes.PLAY_UNKNOWN_USER)
     if self.round.has_played(user):
         raise APIError(Codes.PLAY_ALREADY)
     if not self.players[user].has_card(card):
         raise APIError(Codes.NOT_HAVE_CARD)
     self.round.play_card(user, card)
     self.players[user].deal(self.deck.deal())
     if self.round.has_everyone_played():
         # Transition from PLAY to VOTE.
         self.round.cast_vote(self.clue_maker(),
                              self.round.user_to_card[self.clue_maker()])
         self.state = States.VOTE
     self.ping()
Пример #9
0
 def cast_vote(self, user, card):
     """Make the given user vote for a card, or throws APIError."""
     if self.state != States.VOTE:
         raise APIError(Codes.VOTE_BAD_STATE)
     if user == self.clue_maker():
         raise APIError(Codes.VOTE_NOT_TURN)
     if not user in self.players:
         raise APIError(Codes.VOTE_UNKNOWN_USER)
     if not self.round.has_card(card):
         raise APIError(Codes.VOTE_INVALID)
     if self.round.has_voted(user):
         raise APIError(Codes.VOTE_ALREADY)
     self.round.cast_vote(user, card)
     if self.round.has_everyone_voted():
         # Transition from VOTE to CLUE or END.
         self._do_scoring()
         self.turn = (self.turn + 1) % len(self.players)
         self.state = States.CLUE
         if self.deck.is_empty():
             self.state = States.END
         for p in self.players.values():
             if p.score >= self.max_score:
                 self.state = States.END
     self.ping()