Mercurial > parpg-core
comparison src/parpg/dialogueactions.py @ 0:1fd2201f5c36
Initial commit of parpg-core.
author | M. George Hansen <technopolitica@gmail.com> |
---|---|
date | Sat, 14 May 2011 01:12:35 -0700 |
parents | |
children | 2e307c4f78e3 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:1fd2201f5c36 |
---|---|
1 # This file is part of PARPG. | |
2 # | |
3 # PARPG 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 3 of the License, or | |
6 # (at your option) any later version. | |
7 # | |
8 # PARPG 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 | |
14 # along with PARPG. If not, see <http://www.gnu.org/licenses/>. | |
15 """ | |
16 Provides classes used to implement dialogue logic and allow dialogues to have | |
17 external effects on the game state. | |
18 """ | |
19 import logging | |
20 | |
21 logger = logging.getLogger('dialogueaction') | |
22 | |
23 class DialogueAction(object): | |
24 """ | |
25 Abstract base class for subclasses that represent dialogue actions embedded | |
26 within a DialogueSection or DialogueResponse. | |
27 | |
28 Subclasses must define the keyword class variable and implement both the | |
29 __init__ and __call__ methods. | |
30 | |
31 @cvar keyword: keyword used by the L{DialogueParser} to recognize the | |
32 L{DialogueAction} in serialized L{Dialogues<Dialogues>}. | |
33 @type keyword: basestring | |
34 """ | |
35 logger = logging.getLogger('dialogueaction.DialogueAction') | |
36 registered_actions = {} | |
37 | |
38 @classmethod | |
39 def registerAction(cls, dialogue_action_type): | |
40 """ | |
41 Register a L{DialogueAction} subclass for easy reference. | |
42 | |
43 @param dialogue_action_type: dialogue action to register. | |
44 @type dialogue_action_type: L{DialogueAction} subclass | |
45 """ | |
46 cls.registered_actions[dialogue_action_type.keyword] = \ | |
47 dialogue_action_type | |
48 | |
49 def __init__(self, *args, **kwargs): | |
50 """ | |
51 Initialize a new L{DialogueAction} instance. | |
52 | |
53 @param args: positional arguments passed by the L{DialogueParser} after | |
54 reading a serialized L{Dialogue}. | |
55 @type args: list of objects | |
56 @param kwargs: keyword arguments passed by the L{DialogueParser} after | |
57 reading a serialized L{Dialogue}. | |
58 @type kwargs: dict of objects | |
59 """ | |
60 if (not hasattr(type(self), 'keyword')): | |
61 raise AttributeError('DialogueAction subclasses must define the ' | |
62 'keyword class variable.') | |
63 self.arguments = (args, kwargs) | |
64 | |
65 def __call__(self, game_state): | |
66 """ | |
67 Execute the L{DialogueAction}. | |
68 | |
69 @param game_state: variables and functions that make up the current | |
70 game state. | |
71 @type game_state: dict of objects | |
72 """ | |
73 raise NotImplementedError('subclasses of DialogueAction must ' | |
74 'override __call__') | |
75 | |
76 | |
77 class MeetAction(DialogueAction): | |
78 """ | |
79 L{DialogueAction} that adds an NPC to the list of NPCs known by the player. | |
80 """ | |
81 keyword = 'meet' | |
82 | |
83 def __init__(self, *args, **kwargs): | |
84 """ | |
85 Initialize a new L{MeetAction} instance. | |
86 | |
87 @param args: positional arguments. | |
88 @type args: list of objects | |
89 @param npc_id: identifier of the NPC that the player has met. | |
90 @type npc_id: basestring | |
91 @param kwargs: keyword arguments (not used). | |
92 @type kwargs: dict of objects | |
93 """ | |
94 DialogueAction.__init__(self, *args, **kwargs) | |
95 self.npc_id = args[0] | |
96 | |
97 def __call__(self, game_state): | |
98 """ | |
99 Add an NPC to the list of NPCs known by the player. | |
100 | |
101 @param game_state: variables and functions that make up the current | |
102 game state. | |
103 @type game_state: dict of objects | |
104 """ | |
105 npc_id = self.npc_id | |
106 # NOTE Technomage 2010-11-13: This print statement seems overly | |
107 # verbose, so I'm logging it as an INFO message instead. | |
108 # print("You've met {0}!".format(npc_id)) | |
109 self.logger.info("You've met {0}!".format(npc_id)) | |
110 game_state['pc'].meet(npc_id) | |
111 DialogueAction.registerAction(MeetAction) | |
112 | |
113 | |
114 class InventoryAction(DialogueAction): | |
115 """ | |
116 Abstract base class for L{DialogueActions<DialogueAction>} used to | |
117 manipulate the NPC's and the player's inventory. | |
118 """ | |
119 def __init__(self, *args, **kwargs): | |
120 """ | |
121 Initialize a new L{InventoryAction} instance. | |
122 | |
123 @param args: positional arguments. | |
124 @type args: list of objects | |
125 @param item_types: item types that should be manipulated. | |
126 @type item_types: list of basestrings | |
127 @param kwargs: keyword arguments. | |
128 @type kwargs: dict of objects | |
129 """ | |
130 DialogueAction.__init__(self, *args, **kwargs) | |
131 self.item_types = args | |
132 | |
133 | |
134 class TakeStuffAction(InventoryAction): | |
135 """ | |
136 L{InventoryAction} used to move items from the NPC's inventory to the | |
137 player's inventory. | |
138 """ | |
139 keyword = 'take_stuff' | |
140 | |
141 def __call__(self, game_state): | |
142 """ | |
143 Move items from the NPC's inventory to the player's inventory. | |
144 | |
145 @param game_state: variables and functions that make up the current | |
146 game state. | |
147 @type game_state: dict of objects | |
148 """ | |
149 item_types = self.item_types | |
150 for item_type in item_types: | |
151 item = game_state['npc'].inventory.findItem(item_type=item_type) | |
152 if (item): | |
153 game_state['npc'].give(item, game_state['pc']) | |
154 print("{0} gave you the {1}".format(game_state['npc'].name, | |
155 item_type)) | |
156 else: | |
157 print("{0} doesn't have the {1}".format(game_state['npc'].name, | |
158 item_type)) | |
159 DialogueAction.registerAction(TakeStuffAction) | |
160 | |
161 | |
162 class GiveStuffAction(InventoryAction): | |
163 """ | |
164 L{InventoryAction} used to move items from the player's inventory to the | |
165 NPC's inventory. | |
166 """ | |
167 keyword = 'give_stuff' | |
168 | |
169 def __call__(self, game_state): | |
170 """ | |
171 Move items from the player's inventory to the NPC's inventory. | |
172 | |
173 @param game_state: variables and functions that make up the current | |
174 game state. | |
175 @type game_state: dict of objects | |
176 """ | |
177 item_types = self.item_types | |
178 for item_type in item_types: | |
179 item = game_state['npc'].inventory.findItem(item_type = item_type) | |
180 if (item): | |
181 game_state['pc'].give(item, game_state['npc']) | |
182 print("You give the {0} to {1}".format(item_type, | |
183 game_state['npc'].name)) | |
184 else: | |
185 print("You don't have the {0}".format(item_type)) | |
186 DialogueAction.registerAction(GiveStuffAction) | |
187 | |
188 | |
189 class QuestAction(DialogueAction): | |
190 """ | |
191 Abstract base class for quest-related L{DialogueActions<DialogueAction>}. | |
192 """ | |
193 def __init__(self, *args, **kwargs): | |
194 """ | |
195 Initialize a new L{QuestAction} instance. | |
196 | |
197 @param args: positional arguments. | |
198 @type args: list of objects | |
199 @param quest_id: ID of the quest to manipulate. | |
200 @type quest_id: basestring | |
201 @param kwargs: keyword arguments (not used). | |
202 @type kwargs: dict of objects | |
203 """ | |
204 DialogueAction.__init__(self, *args, **kwargs) | |
205 self.quest_id = kwargs['quest'] if 'quest' in kwargs else args[0] | |
206 | |
207 | |
208 class StartQuestAction(QuestAction): | |
209 """L{QuestAction} used to activate a quest.""" | |
210 keyword = 'start_quest' | |
211 | |
212 def __call__(self, game_state): | |
213 """ | |
214 Activate a quest. | |
215 | |
216 @param game_state: variables and functions that make up the current | |
217 game state. | |
218 @type game_state: dict of objects | |
219 """ | |
220 quest_id = self.quest_id | |
221 print("You've picked up the \"{0}\" quest!".format(quest_id)) | |
222 game_state['quest'].activateQuest(quest_id) | |
223 DialogueAction.registerAction(StartQuestAction) | |
224 | |
225 | |
226 class CompleteQuestAction(QuestAction): | |
227 """ | |
228 L{QuestAction} used to mark a quest as successfully finished/completed. | |
229 """ | |
230 keyword = 'complete_quest' | |
231 | |
232 def __call__(self, game_state): | |
233 """ | |
234 Successfully complete a quest. | |
235 | |
236 @param game_state: variables and functions that make up the current | |
237 game state. | |
238 @type game_state: dict of objects | |
239 """ | |
240 quest_id = self.quest_id | |
241 print("You've finished the \"{0}\" quest".format(quest_id)) | |
242 game_state['quest'].finishQuest(quest_id) | |
243 DialogueAction.registerAction(CompleteQuestAction) | |
244 | |
245 | |
246 class FailQuestAction(QuestAction): | |
247 """L{QuestAction} used to fail an active quest.""" | |
248 keyword = 'fail_quest' | |
249 | |
250 def __call__(self, game_state): | |
251 """ | |
252 Fail an active quest. | |
253 | |
254 @param game_state: variables and functions that make up the current | |
255 game state. | |
256 @type game_state: dict of objects | |
257 """ | |
258 quest_id = self.quest_id | |
259 print("You've failed the \"{0}\" quest".format(quest_id)) | |
260 game_state['quest'].failQuest(quest_id) | |
261 DialogueAction.registerAction(FailQuestAction) | |
262 | |
263 | |
264 class RestartQuestAction(QuestAction): | |
265 """L{QuestAction} used to restart an active quest.""" | |
266 keyword = 'restart_quest' | |
267 | |
268 def __call__(self, game_state): | |
269 """ | |
270 Restart an active quest. | |
271 | |
272 @param game_state: variables and functions that make up the current | |
273 game state. | |
274 @type game_state: dict of objects | |
275 """ | |
276 quest_id = self.quest_id | |
277 print("You've restarted the \"{0}\" quest".format(quest_id)) | |
278 game_state['quest'].restartQuest(quest_id) | |
279 DialogueAction.registerAction(RestartQuestAction) | |
280 | |
281 | |
282 class QuestVariableAction(QuestAction): | |
283 """ | |
284 Base class for L{QuestActions<QuestAction>} that modify quest | |
285 variables. | |
286 """ | |
287 def __init__(self, *args, **kwargs): | |
288 """ | |
289 Initialize a new L{QuestVariableAction} instance. | |
290 | |
291 @param args: positional arguments (not used). | |
292 @type args: list of objects | |
293 @param kwargs: keyword arguments. | |
294 @type kwargs: dict of objects | |
295 @keyword quest: ID of the quest whose variable should be modified. | |
296 @type quest: basestring | |
297 @keyword variable: name of the quest variable to modify. | |
298 @type variable: basestring | |
299 @keyword value: new value that should be used to modify the quest | |
300 variable. | |
301 @type value: object | |
302 """ | |
303 QuestAction.__init__(self, *args, **kwargs) | |
304 self.variable_name = kwargs['variable'] | |
305 self.value = kwargs['value'] | |
306 | |
307 | |
308 class IncreaseQuestVariableAction(QuestVariableAction): | |
309 """ | |
310 L{QuestVariableAction} used to increase the value of a quest variable by a | |
311 set amount. | |
312 """ | |
313 keyword = 'increase_quest_variable' | |
314 | |
315 def __call__(self, game_state): | |
316 """ | |
317 Increase a quest variable by a set amount. | |
318 | |
319 @param game_state: variables and functions that make up the current | |
320 game state. | |
321 @type game_state: dict of objects | |
322 """ | |
323 quest_id = self.quest_id | |
324 variable_name = self.variable_name | |
325 value = self.value | |
326 print('Increased {0} by {1}'.format(variable_name, value)) | |
327 game_state['quest'][quest_id].increaseValue(variable_name, value) | |
328 DialogueAction.registerAction(IncreaseQuestVariableAction) | |
329 | |
330 | |
331 class DecreaseQuestVariableAction(QuestVariableAction): | |
332 """ | |
333 L{QuestVariableAction} used to decrease the value of a quest variable by a | |
334 set amount. | |
335 """ | |
336 keyword = 'decrease_quest_variable' | |
337 | |
338 def __call__(self, game_state): | |
339 """ | |
340 Decrease a quest variable by a set amount. | |
341 | |
342 @param game_state: variables and functions that make up the current | |
343 game state. | |
344 @type game_state: dict of objects | |
345 """ | |
346 quest_id = self.quest_id | |
347 variable_name = self.variable_name | |
348 value = self.value | |
349 print('Decreased {0} by {1}'.format(variable_name, value)) | |
350 game_state['quest'][quest_id].decreaseValue(variable_name, value) | |
351 DialogueAction.registerAction(DecreaseQuestVariableAction) | |
352 | |
353 | |
354 class SetQuestVariableAction(QuestVariableAction): | |
355 """ | |
356 L{QuestVariableAction} used to set the value of a quest variable. | |
357 """ | |
358 keyword = 'set_quest_variable' | |
359 | |
360 def __call__(self, game_state): | |
361 """ | |
362 Set the value of a quest variable. | |
363 | |
364 @param game_state: variables and functions that make up the current | |
365 game state. | |
366 @type game_state: dict of objects | |
367 """ | |
368 quest_id = self.quest_id | |
369 variable_name = self.variable_name | |
370 value = self.value | |
371 print('Set {0} to {1}'.format(variable_name, value)) | |
372 game_state['quest'][quest_id].setValue(variable_name, value) | |
373 DialogueAction.registerAction(SetQuestVariableAction) |