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.
"""
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)
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
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))
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():
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))
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
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))
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]