Mercurial > parpg-core
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/parpg/dialogueactions.py Sat May 14 01:12:35 2011 -0700 @@ -0,0 +1,373 @@ +# This file is part of PARPG. +# +# PARPG is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# PARPG is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with PARPG. If not, see <http://www.gnu.org/licenses/>. +""" +Provides classes used to implement dialogue logic and allow dialogues to have +external effects on the game state. +""" +import logging + +logger = logging.getLogger('dialogueaction') + +class DialogueAction(object): + """ + Abstract base class for subclasses that represent dialogue actions embedded + within a DialogueSection or DialogueResponse. + + Subclasses must define the keyword class variable and implement both the + __init__ and __call__ methods. + + @cvar keyword: keyword used by the L{DialogueParser} to recognize the + L{DialogueAction} in serialized L{Dialogues<Dialogues>}. + @type keyword: basestring + """ + logger = logging.getLogger('dialogueaction.DialogueAction') + registered_actions = {} + + @classmethod + def registerAction(cls, dialogue_action_type): + """ + Register a L{DialogueAction} subclass for easy reference. + + @param dialogue_action_type: dialogue action to register. + @type dialogue_action_type: L{DialogueAction} subclass + """ + cls.registered_actions[dialogue_action_type.keyword] = \ + dialogue_action_type + + def __init__(self, *args, **kwargs): + """ + Initialize a new L{DialogueAction} instance. + + @param args: positional arguments passed by the L{DialogueParser} after + reading a serialized L{Dialogue}. + @type args: list of objects + @param kwargs: keyword arguments passed by the L{DialogueParser} after + reading a serialized L{Dialogue}. + @type kwargs: dict of objects + """ + if (not hasattr(type(self), 'keyword')): + raise AttributeError('DialogueAction subclasses must define the ' + 'keyword class variable.') + self.arguments = (args, kwargs) + + def __call__(self, game_state): + """ + Execute the L{DialogueAction}. + + @param game_state: variables and functions that make up the current + game state. + @type game_state: dict of objects + """ + raise NotImplementedError('subclasses of DialogueAction must ' + 'override __call__') + + +class MeetAction(DialogueAction): + """ + L{DialogueAction} that adds an NPC to the list of NPCs known by the player. + """ + keyword = 'meet' + + def __init__(self, *args, **kwargs): + """ + Initialize a new L{MeetAction} instance. + + @param args: positional arguments. + @type args: list of objects + @param npc_id: identifier of the NPC that the player has met. + @type npc_id: basestring + @param kwargs: keyword arguments (not used). + @type kwargs: dict of objects + """ + DialogueAction.__init__(self, *args, **kwargs) + self.npc_id = args[0] + + def __call__(self, game_state): + """ + Add an NPC to the list of NPCs known by the player. + + @param game_state: variables and functions that make up the current + game state. + @type game_state: dict of objects + """ + npc_id = self.npc_id + # NOTE Technomage 2010-11-13: This print statement seems overly + # verbose, so I'm logging it as an INFO message instead. +# print("You've met {0}!".format(npc_id)) + self.logger.info("You've met {0}!".format(npc_id)) + game_state['pc'].meet(npc_id) +DialogueAction.registerAction(MeetAction) + + +class InventoryAction(DialogueAction): + """ + Abstract base class for L{DialogueActions<DialogueAction>} used to + manipulate the NPC's and the player's inventory. + """ + def __init__(self, *args, **kwargs): + """ + Initialize a new L{InventoryAction} instance. + + @param args: positional arguments. + @type args: list of objects + @param item_types: item types that should be manipulated. + @type item_types: list of basestrings + @param kwargs: keyword arguments. + @type kwargs: dict of objects + """ + DialogueAction.__init__(self, *args, **kwargs) + self.item_types = args + + +class TakeStuffAction(InventoryAction): + """ + L{InventoryAction} used to move items from the NPC's inventory to the + player's inventory. + """ + keyword = 'take_stuff' + + def __call__(self, game_state): + """ + Move items from the NPC's inventory to the player's inventory. + + @param game_state: variables and functions that make up the current + game state. + @type game_state: dict of objects + """ + item_types = self.item_types + for item_type in item_types: + item = game_state['npc'].inventory.findItem(item_type=item_type) + if (item): + game_state['npc'].give(item, game_state['pc']) + print("{0} gave you the {1}".format(game_state['npc'].name, + item_type)) + else: + print("{0} doesn't have the {1}".format(game_state['npc'].name, + item_type)) +DialogueAction.registerAction(TakeStuffAction) + + +class GiveStuffAction(InventoryAction): + """ + L{InventoryAction} used to move items from the player's inventory to the + NPC's inventory. + """ + keyword = 'give_stuff' + + def __call__(self, game_state): + """ + Move items from the player's inventory to the NPC's inventory. + + @param game_state: variables and functions that make up the current + game state. + @type game_state: dict of objects + """ + item_types = self.item_types + for item_type in item_types: + item = game_state['npc'].inventory.findItem(item_type = item_type) + if (item): + game_state['pc'].give(item, game_state['npc']) + print("You give the {0} to {1}".format(item_type, + game_state['npc'].name)) + else: + print("You don't have the {0}".format(item_type)) +DialogueAction.registerAction(GiveStuffAction) + + +class QuestAction(DialogueAction): + """ + Abstract base class for quest-related L{DialogueActions<DialogueAction>}. + """ + def __init__(self, *args, **kwargs): + """ + Initialize a new L{QuestAction} instance. + + @param args: positional arguments. + @type args: list of objects + @param quest_id: ID of the quest to manipulate. + @type quest_id: basestring + @param kwargs: keyword arguments (not used). + @type kwargs: dict of objects + """ + DialogueAction.__init__(self, *args, **kwargs) + self.quest_id = kwargs['quest'] if 'quest' in kwargs else args[0] + + +class StartQuestAction(QuestAction): + """L{QuestAction} used to activate a quest.""" + keyword = 'start_quest' + + def __call__(self, game_state): + """ + Activate a quest. + + @param game_state: variables and functions that make up the current + game state. + @type game_state: dict of objects + """ + quest_id = self.quest_id + print("You've picked up the \"{0}\" quest!".format(quest_id)) + game_state['quest'].activateQuest(quest_id) +DialogueAction.registerAction(StartQuestAction) + + +class CompleteQuestAction(QuestAction): + """ + L{QuestAction} used to mark a quest as successfully finished/completed. + """ + keyword = 'complete_quest' + + def __call__(self, game_state): + """ + Successfully complete a quest. + + @param game_state: variables and functions that make up the current + game state. + @type game_state: dict of objects + """ + quest_id = self.quest_id + print("You've finished the \"{0}\" quest".format(quest_id)) + game_state['quest'].finishQuest(quest_id) +DialogueAction.registerAction(CompleteQuestAction) + + +class FailQuestAction(QuestAction): + """L{QuestAction} used to fail an active quest.""" + keyword = 'fail_quest' + + def __call__(self, game_state): + """ + Fail an active quest. + + @param game_state: variables and functions that make up the current + game state. + @type game_state: dict of objects + """ + quest_id = self.quest_id + print("You've failed the \"{0}\" quest".format(quest_id)) + game_state['quest'].failQuest(quest_id) +DialogueAction.registerAction(FailQuestAction) + + +class RestartQuestAction(QuestAction): + """L{QuestAction} used to restart an active quest.""" + keyword = 'restart_quest' + + def __call__(self, game_state): + """ + Restart an active quest. + + @param game_state: variables and functions that make up the current + game state. + @type game_state: dict of objects + """ + quest_id = self.quest_id + print("You've restarted the \"{0}\" quest".format(quest_id)) + game_state['quest'].restartQuest(quest_id) +DialogueAction.registerAction(RestartQuestAction) + + +class QuestVariableAction(QuestAction): + """ + Base class for L{QuestActions<QuestAction>} that modify quest + variables. + """ + def __init__(self, *args, **kwargs): + """ + Initialize a new L{QuestVariableAction} instance. + + @param args: positional arguments (not used). + @type args: list of objects + @param kwargs: keyword arguments. + @type kwargs: dict of objects + @keyword quest: ID of the quest whose variable should be modified. + @type quest: basestring + @keyword variable: name of the quest variable to modify. + @type variable: basestring + @keyword value: new value that should be used to modify the quest + variable. + @type value: object + """ + QuestAction.__init__(self, *args, **kwargs) + self.variable_name = kwargs['variable'] + self.value = kwargs['value'] + + +class IncreaseQuestVariableAction(QuestVariableAction): + """ + L{QuestVariableAction} used to increase the value of a quest variable by a + set amount. + """ + keyword = 'increase_quest_variable' + + def __call__(self, game_state): + """ + Increase a quest variable by a set amount. + + @param game_state: variables and functions that make up the current + game state. + @type game_state: dict of objects + """ + quest_id = self.quest_id + variable_name = self.variable_name + value = self.value + print('Increased {0} by {1}'.format(variable_name, value)) + game_state['quest'][quest_id].increaseValue(variable_name, value) +DialogueAction.registerAction(IncreaseQuestVariableAction) + + +class DecreaseQuestVariableAction(QuestVariableAction): + """ + L{QuestVariableAction} used to decrease the value of a quest variable by a + set amount. + """ + keyword = 'decrease_quest_variable' + + def __call__(self, game_state): + """ + Decrease a quest variable by a set amount. + + @param game_state: variables and functions that make up the current + game state. + @type game_state: dict of objects + """ + quest_id = self.quest_id + variable_name = self.variable_name + value = self.value + print('Decreased {0} by {1}'.format(variable_name, value)) + game_state['quest'][quest_id].decreaseValue(variable_name, value) +DialogueAction.registerAction(DecreaseQuestVariableAction) + + +class SetQuestVariableAction(QuestVariableAction): + """ + L{QuestVariableAction} used to set the value of a quest variable. + """ + keyword = 'set_quest_variable' + + def __call__(self, game_state): + """ + Set the value of a quest variable. + + @param game_state: variables and functions that make up the current + game state. + @type game_state: dict of objects + """ + quest_id = self.quest_id + variable_name = self.variable_name + value = self.value + print('Set {0} to {1}'.format(variable_name, value)) + game_state['quest'][quest_id].setValue(variable_name, value) +DialogueAction.registerAction(SetQuestVariableAction)