1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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
31 """
32 Mock object representing the player character.
33 """
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
56 return npc in self.known_npcs
57
58
60 """Mock object representing a 'beer' item."""
61 quality = 3
62
63
65 """Mock box object than can be opened or closed."""
67 """
68 Initialize a new {MockBox} instance.
69
70 @ivar opened: whether the L{MockBox} has been "opened".
71 """
72 self.opened = False
73
75 """Set the opened state of the L{MockBox} to True."""
76 self.opened = True
77
79 """Set the opened state of the L{MockBox} to False."""
80 self.opened = False
81
82
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
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
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
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
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
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