summaryrefslogtreecommitdiff
path: root/swiftstory/game.py
diff options
context:
space:
mode:
Diffstat (limited to 'swiftstory/game.py')
-rw-r--r--swiftstory/game.py218
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