Added continent colors to template system
[pyrisk.git] / pyrisk / log.py
1 # Copyright (C) 2010 W. Trevor King <wking@drexel.edu>
2 #
3 # This program is free software; you can redistribute it and/or modify
4 # it under the terms of the GNU General Public License as published by
5 # the Free Software Foundation; either version 2 of the License, or
6 # (at your option) any later version.
7 #
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 # GNU General Public License for more details.
12 #
13 # You should have received a copy of the GNU General Public License along
14 # with this program; if not, write to the Free Software Foundation, Inc.,
15 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
16
17 """Define Logger class for saving and formatting game activity.
18 """
19
20 class Event (object):
21     """Base class for logged actions.
22     """
23     def __init__(self, message):
24         self.message = message
25     def __str__(self):
26         return self.message
27     def __repr__(self):
28         return self.__str__()
29
30 class Announcement (Event):
31     """A statement about game status.
32     """
33
34 class BeginGame (Announcement):
35     def __init__(self, players=[]):
36         # perhaps copy the list of players?
37         self.players = players
38         Announcement.__init__(self, 'Game started with %s' % self.players)
39
40 class EndGame (Announcement):
41     def __init__(self, players=[]):
42         self.players = players
43         Announcement.__init__(self, 'Game over')
44         # perhaps add turns-survived ranking
45
46 class Killed (Announcement):
47     def __init__(self, player, killer):
48         self.player = player
49         self.killer = killer
50         Announcement.__init__(
51             self, '%s killed by %s' % (self.player, self.killer))
52
53
54 class StartTurn (Announcement):
55     def __init__(self, player, players=[], world=None):
56         self.player = player
57         self.players = players
58         self.world = world
59         Announcement.__init__(
60             self,
61             "%s's turn (territory score: %s)"
62             % (self.player,
63                [(p,len(list(p.territories(self.world))))
64                 for p in self.players]))
65
66 class DealtCards (Announcement):
67     """A player recieves cards from the deck.
68     """
69     def __init__(self, player, num_cards, num_remaining):
70         self.player = player
71         self.num_cards = num_cards
72         self.num_remaining = num_remaining
73         Announcement.__init__(
74             self,
75             '%s dealt %d cards (%d remaining)'
76             % (self.player, self.num_cards, self.num_remaining))
77
78 class EarnsArmies (Announcement):
79     """A player recieves armies.
80     """
81     def __init__(self, player, prod=0, terr_prod={}, source='territories'):
82         self.player = player
83         self.prod = prod
84         self.terr_prod = terr_prod
85         self.source = source
86         if len(terr_prod) == 0:
87             msg = 'earns %d free armies from %s' % (self.prod, self.source)
88         elif self.prod == 0:
89             msg = 'earns %s territory armies from %s' % (self.terr_prod, self.source)
90         else:
91             msg = 'earns %d free armies and %s territory armies from %s' \
92                 % (self.prod, self.terr_prod, self.source)
93         Announcement.__init__(self, msg)
94
95
96 class PlayerAction (Event):
97     """Report a player decision and its result.
98     """
99     def __init__(self, player, message):
100         Event.__init__(self, message)
101         self.player = player
102     def __str__(self):
103         return '%s: %s' % (self.player, self.message)
104
105 class SelectTerritory (PlayerAction):
106     def __init__(self, player, territory):
107         self.territory = territory
108         PlayerAction.__init__(
109             self, player, 'selects %s' % self.territory)
110
111 class PlaceArmies (PlayerAction):
112     def __init__(self, player, placements):
113         self.placements = placements
114         PlayerAction.__init__(
115             self, player, 'places %s' % self.placements)
116
117 class PlayCards (PlayerAction, EarnsArmies):
118     def __init__(self, player, cards, prod=0, terr_prod={}, source='cards'):
119         self.cards = cards
120         EarnsArmies.__init__(
121             self, player, prod, terr_prod, source)
122         msg = self.message
123         PlayerAction.__init__(self, player, 'plays %s' % self.cards)
124         self.message += ', %s' % msg
125
126 class MoveArmies (PlayerAction):
127     def __init__(self, player, source, target, armies):
128         self.source = source
129         self.target = target
130         self.armies = armies
131         PlayerAction.__init__(
132         self, player, 'moves %d from %s to %s' % (armies, source, target))
133
134 class Attack (MoveArmies):
135     def __init__(self, source, target, s_dice, t_dice, s_dead, t_dead, armies=None):
136         if armies == None:
137             armies = len(s_dice)
138         MoveArmies.__init__(self, source.player, source, target, armies)
139         self.s_dice = s_dice
140         self.t_dice = t_dice
141         self.s_dead = s_dead
142         self.t_dead = t_dead
143         self.message = '%s attacks %s with %d:%d.  Deaths %d:%d.  Remaining %d:%d' \
144             % (self.source, self.target, len(self.s_dice), len(self.t_dice),
145                self.s_dead, self.t_dead,
146                self.source.armies, self.target.armies)
147
148 class Conquer (Attack):
149     def __init__(self, source, target, s_dice, t_dice, s_dead, t_dead):
150         Attack.__init__(self, source, target, s_dice, t_dice, s_dead, t_dead,
151                         armies=target.armies)
152         self.message = self.message.replace('attacks', 'conquers')
153
154 class Fortify (MoveArmies):
155     def __init__(self, source, target, armies):
156         MoveArmies.__init__(self, source.player, source, target, armies)
157         self.message = '%s fortifies %s with %d' \
158             % (self.source, self.target, self.armies)
159
160 class Logger (list):
161     """Log messages generated by risk.base.Engine.
162
163     Currently just a list, but it's a convenient hook if you need it.
164     """
165     def __call__(self, message):
166         self.append(message)