diff options
author | Olivier Gayot <olivier.gayot@sigexec.com> | 2021-12-23 15:27:43 +0100 |
---|---|---|
committer | Olivier Gayot <olivier.gayot@sigexec.com> | 2021-12-23 23:15:21 +0100 |
commit | 82cd09e010783b81ec58145c7682f4b8da49ac85 (patch) | |
tree | 83b3e61aaa4befcd340a01b2fb147a2306bdb29e /swiftstory/game.py | |
parent | 1be5c49ae402b768f9206724abdd503c18933ae1 (diff) |
Use lowercase module names
Signed-off-by: Olivier Gayot <olivier.gayot@sigexec.com>
Diffstat (limited to 'swiftstory/game.py')
-rw-r--r-- | swiftstory/game.py | 218 |
1 files changed, 218 insertions, 0 deletions
diff --git a/swiftstory/game.py b/swiftstory/game.py new file mode 100644 index 0000000..cda3ddd --- /dev/null +++ b/swiftstory/game.py @@ -0,0 +1,218 @@ +import random + +from swiftstory.exception import WrongAction, JoinError +from swiftstory.player import Player +from swiftstory.board import Board +from swiftstory.status import error, success + + +class Game: + WAITING_NEW_JUDGE = 0 + WAITING_COLLECTION = 1 + WAITING_DESIGNATION = 2 + + def __init__(self, white_desc, black_desc): + white_pick = list(enumerate(white_desc)) + black_pick = list(enumerate(black_desc)) + + self.state = self.WAITING_NEW_JUDGE + + self.players = [] + + self.judge = None + + self.board = Board() + self.board.white_pick = white_pick + self.board.black_pick = black_pick + + random.shuffle(self.board.white_pick) + random.shuffle(self.board.black_pick) + + def try_join(self, client): + if len(self.players) >= 10: + raise JoinError('too many players in this game') + + cards = [] + + try: + for _ in range(10): + cards.append(self.board.pick_white_card()) + except IndexError: + raise JoinError('not enough white cards for player') + + player = Player(client) + + for card in cards: + player.receive_card(card) + + client.player = player + client.game = self + + self.players.append(player) + + for p in self.players: + if p is not player: + p.register_notification({'op': 'player_joined_game'}) + + cards = [(idx, desc) for idx, (_, desc) in player.cards.items()] + + if self.state is self.WAITING_NEW_JUDGE: + state = 'waiting_judge' + elif self.state is self.WAITING_COLLECTION: + state = 'waiting_collection' + else: + state = 'waiting_designation' + + return success({'cards': cards, 'game_state': state}) + + + def try_become_judge(self, player): + if self.state is not self.WAITING_NEW_JUDGE: + # TODO what if the judge has quit ? + raise WrongAction('Someone is judge already') + + self.judge = player + self.board.reveal_next_black_card() + + self.state = self.WAITING_COLLECTION + + for p in self.players: + if p is not player: + p.register_notification({'op': 'judge_designed'}) + + return self.try_view_black_card(player) + + + def try_play_card(self, player, card_id): + if self.state is not self.WAITING_COLLECTION: + raise WrongAction('Who asked you to play now ?!') + + if self.judge is player: + raise WrongAction('You\'re the judge, you silly') + elif player.has_played: + raise WrongAction('You already played, you dumb ass') + + try: + card = player.pop_card(card_id) + except IndexError: + raise WrongAction('Invalid card id') + + player.has_played = True + + self.board.play_card(player, card) + + self.judge.register_notification({'op': 'card_played'}) + + return success({'card_id': card_id}) + + + def try_collect_cards(self, player): + if self.state is not self.WAITING_COLLECTION: + raise WrongAction("Do you think it's the moment for collection !?") + + if self.judge is not player: + raise WrongAction('You\'re not the judge, you fool!') + + self.board.shuffle_played_cards() + + # we prevent the others to play + self.state = self.WAITING_DESIGNATION + + for p in self.players: + if p is not player: + p.register_notification({'op': 'cards_collected'}) + + return self.try_view_played_cards(player) + + + def try_designate_card(self, player, card_id): + if self.state is not self.WAITING_DESIGNATION: + raise WrongAction('Not now, moron !') + + if self.judge is not player: + raise WrongAction('Who do you think you are !?') + + if card_id is None and len(self.board.played_cards) > 0: + raise WrongAction('There are cards on the board, pick one !') + + if card_id is not None or len(self.board.played_cards) > 0: + # if there are cards on the board + # TODO check exception + try: + card, winner = self.board.played_cards[card_id] + except IndexError: + return error('Invalid card') + + winner.inc_score() + + # put the cards back in the deck + self.board.recycle_played_cards() + + # reset the state of the players + for p in self.players: + if p.has_played: + idx = p.receive_card(self.board.pick_white_card()) + + p.register_notification({ + 'op': 'received_card', + 'content': { + 'card': { + 'id': p.cards[idx][0], + 'desc': p.cards[idx][1], + }, + }, + }) + p.has_played = False + + self.judge = None + + for p in self.players: + if p is not player: + p.register_notification({'op': 'judge_needed'}) + + self.state = self.WAITING_NEW_JUDGE + + return success(None) + + def try_view_player_cards(self, player): + return success([(idx, desc) for idx, (_, desc) in player.cards.items()]) + + def try_view_played_cards(self, player): + if self.state is not self.WAITING_DESIGNATION: + raise WrongAction('Not now, moron !') + + return success([desc for (_, desc), _ in self.board.played_cards]) + + def try_view_black_card(self, player): + card = self.board.current_black_card + + if card is not None: + return success(card[1]) + + raise WrongAction('The black card has not been revealed yet') + + def disconnect(self, player): + player.client = None + + if self.judge is player: + self.judge = None + + for p in self.players: + p.register_notification({'op': 'judge_needed'}) + + for card, p in self.board.played_cards: + p.receive_card(card) + + p.register_notification({ + 'op': 'received_card', + 'content': { + 'card': { + 'id': card[0], + 'desc': card[1], + }, + }, + }) + p.has_played = False + + self.board.played_cards = [] + self.state = self.WAITING_NEW_JUDGE |