Module dialogue_demo
[hide private]
[frames] | no frames]

Source Code for Module dialogue_demo

  1  #!/usr/bin/env python2 
  2  #   This file is part of PARPG. 
  3  # 
  4  #   PARPG is free software: you can redistribute it and/or modify 
  5  #   it under the terms of the GNU General Public License as published by 
  6  #   the Free Software Foundation, either version 3 of the License, or 
  7  #   (at your option) any later version. 
  8  # 
  9  #   PARPG is distributed in the hope that it will be useful, 
 10  #   but WITHOUT ANY WARRANTY; without even the implied warranty of 
 11  #   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 12  #   GNU General Public License for more details. 
 13  # 
 14  #   You should have received a copy of the GNU General Public License 
 15  #   along with PARPG.  If not, see <http://www.gnu.org/licenses/>. 
 16  """ 
 17  A very simple demonstration of the dialogue engine used for testing dialogue 
 18  files. 
 19  """ 
 20  import logging 
 21  import os 
 22  import sys 
 23  from optparse import OptionParser 
 24   
 25  from parpg.dialogueparsers import YamlDialogueParser 
 26  from parpg.dialogueprocessor import DialogueProcessor 
 27  from parpg.quest_engine import QuestEngine 
 28  from parpg.settings import Settings 
 29   
30 -class MockPlayerCharacter(object):
31 """ 32 Mock object representing the player character. 33 """
34 - def __init__(self):
35 """ 36 Initialize a new L{MockPlayerCharacter} instance. 37 38 @ivar inventory: set of items carried by the L{MockPlayerCharacter}. 39 @ivar known_npcs: set of IDs for the NPCs the player has met. 40 """ 41 self.inventory = set(['beer']) 42 self.known_npcs = set()
43
44 - def meet(self, npc_id):
45 """ 46 Add an NPC to the list of NPCs known by the player. 47 48 @param npc: ID of the NPC to add. 49 @type npc: str 50 """ 51 if npc_id in self.known_npcs: 52 raise RuntimeError("I already know {0}".format(npc_id)) 53 self.known_npcs.add(npc_id)
54
55 - def met(self, npc):
56 return npc in self.known_npcs
57 58
59 -class MockBeer(object):
60 """Mock object representing a 'beer' item.""" 61 quality = 3
62 63
64 -class MockBox(object):
65 """Mock box object than can be opened or closed."""
66 - def __init__(self):
67 """ 68 Initialize a new {MockBox} instance. 69 70 @ivar opened: whether the L{MockBox} has been "opened". 71 """ 72 self.opened = False
73
74 - def open(self):
75 """Set the opened state of the L{MockBox} to True.""" 76 self.opened = True
77
78 - def close(self):
79 """Set the opened state of the L{MockBox} to False.""" 80 self.opened = False
81 82
83 -def selectDialogueFile(settings):
84 """ 85 List all YAML dialogue files in the dialogue directory and prompt the user 86 to select one for testing. 87 """ 88 dialogue_dir = os.path.join(settings.system_path, 89 settings.parpg.DialoguesPath) 90 dialogue_files = [file_name for file_name in os.listdir(dialogue_dir) 91 if file_name.endswith('.yaml')] 92 for index, file_name in enumerate(dialogue_files): 93 print('{0} - {1}'.format(index, file_name)) 94 while True: 95 str_input = raw_input("> ") 96 try: 97 choice_n = int(str_input) 98 selected_file_name = dialogue_files[choice_n] 99 except (ValueError, IndexError): 100 print(('"{0}" is an invalid selection, please choose a number ' 101 'between 0 and {1}').format(str_input, 102 len(dialogue_files) - 1)) 103 continue 104 else: 105 break 106 107 selected_file_path = os.path.join(dialogue_dir, selected_file_name) 108 return selected_file_path
109
110 -def chooseReply(dialogue_responses):
111 """ 112 Prompt the user to choose a L{DialogueResponse} from a list of valid 113 responses. 114 115 @param dialogue_responses: valid responses to choose from 116 @type dialogue_responses: list of L{DialogueResponses} 117 """ 118 while (True): 119 print('Available responses:') 120 for index, response in enumerate(dialogue_responses): 121 print('{0} - {1}'.format(index, response.text)) 122 try: 123 chosen_response_n = int(raw_input('Choose a response number> ')) 124 chosen_response = dialogue_responses[chosen_response_n] 125 except (ValueError, IndexError): 126 print(('\ninvalid response, please enter an integer between 0 ' 127 'and {0}').format(len(dialogue_responses) - 1)) 128 else: 129 break 130 131 return chosen_response
132
133 -def processDialogue(dialogue, game_state):
134 """ 135 Process a L{Dialogue} until the user selects a response that ends it. 136 137 @param dialogue: dialogue data to process. 138 @type dialogue: L{Dialogue} 139 @param game_state: objects that should be made available for response 140 conditional testing. 141 @type game_state: dict of objects 142 """ 143 npc_name = dialogue.npc_name 144 dialogue_processor = DialogueProcessor(dialogue, game_state) 145 dialogue_processor.initiateDialogue() 146 while dialogue_processor.in_dialogue: 147 responses = dialogue_processor.continueDialogue() 148 current_dialogue_section = \ 149 dialogue_processor.getCurrentDialogueSection() 150 dialogue_text = current_dialogue_section.text 151 # Indent dialogue text after the first line. 152 dialogue_text = dialogue_text.replace('\n', '\n ') 153 print('\n{0}: {1}'.format(npc_name, dialogue_text)) 154 chosen_reply = chooseReply(responses) 155 dialogue_processor.reply(chosen_reply)
156
157 -def main():
158 parser = OptionParser(description='Script for testing dialogue files') 159 parser.add_option('-s', '--settings', nargs=2, 160 dest='paths', default=['.'], 161 help='One or more paths to load settings from') 162 parser.add_option('-f', '--logfile', 163 help='Name of log file to save to') 164 parser.add_option('-l', '--loglevel', default='critical', 165 help='desired output level for log file') 166 167 opts, args = parser.parse_args() 168 169 settings = Settings(*opts.paths) 170 171 levels = {'debug': logging.DEBUG, 172 'info': logging.INFO, 173 'warning': logging.WARNING, 174 'error': logging.ERROR, 175 'critical': logging.CRITICAL} 176 177 #TODO: setup formating 178 logging.basicConfig(filename=opts.logfile, level=levels[opts.loglevel]) 179 logger = logging.getLogger('dialogue_demo') 180 181 try: 182 dialogue_file_path = args[0] 183 except IndexError: 184 logger.info('No dialogue file provided, generating a list..') 185 dialogue_file_path = selectDialogueFile(settings) 186 187 game_state = { 188 'quest': QuestEngine('quests'), 189 'pc': MockPlayerCharacter(), 190 'box': MockBox(), 191 'beer': MockBeer() 192 } 193 dialogue_parser = YamlDialogueParser() 194 with file(dialogue_file_path, 'r') as dialogue_file: 195 dialogue = dialogue_parser.load(dialogue_file) 196 processDialogue(dialogue, game_state)
197 198 if __name__ == "__main__": 199 main() 200