Exemple #1
0
 def settle(self, players, result):
     if self.tag is None:
         raise GameError('Tag is undefined for rule %s.' %
                         self.__class__.__name__)
     for player in players:
         if not player.is_out and player.has_tag(self.tag):
             self.settle_tagged_player(player, players, result)
Exemple #2
0
 def get_alignment(cls, *roles):
     alignment = 0
     for role in roles:
         if role not in cls.ALIGNMENTS:
             raise GameError('Invalid role %s.' % role)
         alignment += cls.ALIGNMENTS[role]
     return alignment
Exemple #3
0
 def execute_action(self, action_name, targets, option=None):
     # Execute the current action and check if game is over.
     if not self.game.is_ongoing:
         raise GameError(
             'Cannot execute action because game is not ongoing.')
     action = self.get_current_action()
     if action.name != action_name:
         raise GameError('Invalid action name %s, expected %s.' %
                         (action_name, action.name))
     logger.info('About to execute %s...' % action)
     result = action.execute(self.game.player_list, targets, option)
     self.game.log_action_result(result)
     self.update_game_over()
     # Move to next action.
     if not self.game.is_over:
         self.move_to_next_action(result)
     self.save_game()
Exemple #4
0
 def get_tag(self, option):
     if option == self.OPTION_CURE and not self.is_cure_used:
         self.is_cure_used = True
         return Tag.CURED_BY_WITCH
     elif option == self.OPTION_POISON and not self.is_poison_used:
         self.is_poison_used = True
         return Tag.POISONED_BY_WITCH
     else:
         raise GameError('Invalid option for witch: %s' % option)
Exemple #5
0
 def start_game(self, force=False):
     # Check if game can be started.
     if self.game.is_ongoing and not force:
         raise GameError('Cannot start game %s: game is ongoing.' %
                         self.game)
     # Reset the game.
     logger.info('Resetting game...')
     self.reset_game()
     self.game.ensure_unused_players(self.get_num_unused_players())
     min_num_players, max_num_players = self.get_min_max_num_players()
     num_players = len(self.game.player_list)
     if not (min_num_players <= num_players <= max_num_players):
         raise GameError(
             'Cannot start game %s: there are %d players but requires [%d, %d].'
             % (self.game, num_players, min_num_players, max_num_players))
     # Assign roles to players randomly.
     player_list = list(self.game.player_list)
     logger.info('Assigning roles to players...')
     random.shuffle(player_list)
     for role in self.get_role_list_on_stage():
         assigned_player = None
         for player in player_list:
             if player.twin is None or self.get_alignment(
                     player.twin.role, role) != 0:
                 player.role = role
                 player.save()
                 assigned_player = player
                 break
         assert assigned_player is not None
         player_list.remove(assigned_player)
     for player in player_list:
         player.role = self.get_civilian_role()
         player.save()
     # Initialize action list.
     logger.info('Initializing action list...')
     self.action_list = self.action_list_class.create_initial(
         self.get_role_list_on_stage())
     # Update game state.
     logger.info('Updating game state...')
     self.game.round = 1
     self.game.is_over = False
     self.save_game()
Exemple #6
0
 def execute(self, players, targets, option):
     """
     Executes this action.
     """
     # Perform some checks before executing this action.
     if not self.is_executable(players):
         raise GameError('%s is not executable.' % self.name)
     min_num_targets, max_num_targets = self.get_min_max_num_targets()
     if not (min_num_targets <= len(targets) <= max_num_targets):
         raise GameError(
             '%s should be executed on [%d, %d] targets but got %d.' %
             (self.name, min_num_targets, max_num_targets, len(targets)))
     for target in targets:
         if not self.is_executable_on(target):
             raise GameError('%s is not executable on %s.' %
                             (self.name, target))
     # Execute this action.
     result = ActionResult(self.name)
     self.execute_with_result(players, targets, option, result)
     return result
Exemple #7
0
 def skip(self, players):
     """
     Skips this action. Only non-executable action can be skipped.
     """
     # Perform some checks before skipping this action.
     if self.is_executable(players):
         raise GameError('%s is executable thus cannot be skipped.' %
                         self.name)
     # Skip this action.
     result = ActionResult(self.name)
     result.log('Skipped', visibility=self.role)
     return result
Exemple #8
0
 def load_json_data(cls, json_data):
     if not json_data:
         return cls()
     # Load actions.
     actions = []
     list_data = json_data.get('_list', [])
     for action_data in list_data:
         class_name = action_data.pop('_name')
         action_class = next((clas for clas in cls.action_classes
                              if clas.__name__ == class_name), None)
         if action_class is None:
             raise GameError('Invalid action class name: %s' % class_name)
         action = action_class(**action_data)
         actions.append(action)
     # Load index.
     index = json_data.get('index', 0)
     # Recreate action list.
     return cls(actions, index)
Exemple #9
0
 def execute_with_result(self, players, targets, option, result):
     """
     Executes this action and fills the result. By default, this method adds the action tag
     to all the target players (tag should not be None).
     """
     if not targets:
         result.log('%s did not select anyone' % self.role,
                    visibility=self.role)
     else:
         tag = self.get_tag(option)
         if not tag:
             raise GameError('Tag is undefined for %s.' % self.name)
         for target in targets:
             target.add_tag(tag)
             text = '%s tagged %s with %s' % (self.role, target, tag)
             answer = self.get_answer(target)
             if answer is not None:
                 text += ': %s' % answer
             result.log(text, visibility=self.role)
Exemple #10
0
 def current(self):
     if not (0 <= self.index < len(self)):
         raise GameError('Action index out of bound: %d' % self.index)
     return self[self.index]