From: W. Trevor King Date: Fri, 26 Mar 2010 00:40:26 +0000 (-0400) Subject: Only call Player.report (prev. Player.phase_report) as final contact X-Git-Tag: 0.1~39 X-Git-Url: http://git.tremily.us/?p=pyrisk.git;a=commitdiff_plain;h=99aba974403edde2086e1c929146a831486c554f Only call Player.report (prev. Player.phase_report) as final contact --- diff --git a/risk/base.py b/risk/base.py index 8d8ef33..b63e6c2 100644 --- a/risk/base.py +++ b/risk/base.py @@ -251,26 +251,34 @@ class Player (ID_CmpMixin): if neighbor.player != self: yield t break - def phase_report(self, world, log): + def report(self, world, log): + """Send reports about death and game endings. + + These events mark the end of contact and require no change in + player status or response, so they get a special command + seperate from the usual phase_* family. The phase_* commands + in Player subclasses can notify the player (possibly by + calling report internally) if they feel so inclined. + """ print 'Reporting for %s:\n %s' \ % (self, '\n '.join(log[self._message_index:])) self._message_index = len(log) - def phase_select_territory(self, world): + def phase_select_territory(self, world, log): """Return the selected territory """ free_territories = [t for t in world.territories() if t.player == None] return random.sample(free_territories, 1)[0] - def phase_play_cards(self, world, play_required=True): + def phase_play_cards(self, world, log, play_required=True): if play_required == True: return random.sample(list(self.hand.possible()), 1)[0] - def phase_place_armies(self, world, remaining=1, this_round=1): + def phase_place_armies(self, world, log, remaining=1, this_round=1): """Both during setup and before each turn. Return {territory_name: num_armies, ...} """ t = random.sample(list(self.border_territories(world)), 1)[0] return {t.name: this_round} - def phase_attack(self, world): + def phase_attack(self, world, log): """Return list of (source, target, armies) tuples. Place None in the list to end this phase. """ @@ -284,14 +292,14 @@ class Player (ID_CmpMixin): if len(possible_attacks) == 0: return [None] return random.sample(possible_attacks, 1) # + [None] - def phase_support_attack(self, world, source, target): + def phase_support_attack(self, world, log, source, target): return source.armies-1 - def phase_fortify(self, world): + def phase_fortify(self, world, log): """Return list of (source, target, armies) tuples. Place None in the list to end this phase. """ return [None] - def phase_draw(self, cards=[]): + def phase_draw(self, world, log, cards=[]): """Only called if you earned a new card (or cards)""" self.hand.extend(cards) @@ -311,7 +319,7 @@ class Engine (ID_CmpMixin): self.play() self.log('Game over.') for p in self.players: - p.phase_report(self.world, self.log) + p.report(self.world, self.log) def setup(self): for p in self.players: p.alive = True @@ -332,18 +340,16 @@ class Engine (ID_CmpMixin): self.log("%s's turn (territory score: %s)" % (player, [(p,len(list(p.territories(self.world)))) for p in self.players])) - player.phase_report(self.world, self.log) self.play_cards_and_place_armies(player) captures = self.attack_phase(player) if captures > 0 and len(self.deck) > 0 and len(self.living_players()) > 1: - player.phase_draw([self.deck.pop()]) + player.phase_draw(self.world, self.log, [self.deck.pop()]) def select_territories(self): for t in self.world.territories(): t.player = None for i in range(len(list(self.world.territories()))): p = self.players[i % len(self.players)] - p.phase_report(self.world, self.log) - t = p.phase_select_territory(self.world) + t = p.phase_select_territory(self.world, self.log) if t.player != None: raise PlayerError('Cannot select %s owned by %s' % (t, t.player)) @@ -358,16 +364,14 @@ class Engine (ID_CmpMixin): assert min(s) == max(s)-1, 'Min %d, max %d' % (min(s), max(s)) for p,placed in zip(self.players, already_placed): if placed == min(s): - p.phase_report(self.world, self.log) self.player_place_armies(p, remaining, 1) remaining = self.world.initial_armies[len(self.players)] - max(s) while remaining > 0: for p in self.players: - p.phase_report(self.world, self.log) self.player_place_armies(p, remaining, 1) remaining -= 1 def player_place_armies(self, player, remaining=1, this_round=1): - placements = player.phase_place_armies(self.world, remaining, this_round) + placements = player.phase_place_armies(self.world, self.log, remaining, this_round) if sum(placements.values()) != this_round: raise PlayerError('Placing more than %d armies' % this_round) for ter_name,armies in placements.items(): @@ -387,12 +391,12 @@ class Engine (ID_CmpMixin): cards = [] for i in range(3): cards.append(self.deck.pop()) - p.phase_draw(cards) + p.phase_draw(self.world, self.log, cards) self.log('Initial hands dealt') def play_cards_and_place_armies(self, player, additional_armies=0): cards_required = len(player.hand) >= 5 cards = player.phase_play_cards( - self.world, play_required=cards_required) + self.world, self.log, play_required=cards_required) if cards_required == True and cards == None: raise PlayerError('You have %d >= 5 cards in your hand, you must play' % len(player.hand)) @@ -418,7 +422,7 @@ class Engine (ID_CmpMixin): def attack_phase(self, player): captures = 0 while True: - attacks = player.phase_attack(self.world) + attacks = player.phase_attack(self.world, self.log) for attack in attacks: if attack == None: return captures @@ -470,7 +474,7 @@ class Engine (ID_CmpMixin): source.armies -= remaining_attackers target.armies += remaining_attackers target.player = source.player - support = source.player.phase_support_attack(self.world, source, target) + support = source.player.phase_support_attack(self.world, self.log, source, target) if support < 0 or support >= source.armies: raise PlayerError('Cannot support from %s to %s with %d armies, only %d available' % (source, target, support, source.armies-1)) @@ -484,7 +488,7 @@ class Engine (ID_CmpMixin): self.play_cards_and_place_armies(killer) self.log('%s killed by %s' % (player, killer)) if len(self.living_players()) > 1: - player.phase_report(self.world, self.log) + player.report(self.world, self.log) # else the game is over, and killed will hear about this then. def living_players(self): return [p for p in self.players if p.alive == True]