Mercurial > parpg-core
comparison src/parpg/dialogue.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 |
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 contain and organize dialogue data for use within | |
17 in-game dialogues between the player character and NPCs. | |
18 """ | |
19 try: | |
20 from collections import OrderedDict | |
21 except ImportError: | |
22 # Python version 2.4-2.6 doesn't have the OrderedDict | |
23 from parpg.common.ordereddict import OrderedDict | |
24 | |
25 class Dialogue(object): | |
26 """ | |
27 Represents a complete dialogue and acts as a container for the dialogue | |
28 data belonging to a particular NPC. | |
29 """ | |
30 __slots__ = ['npc_name', 'avatar_path', 'default_greeting', | |
31 'greetings', 'sections'] | |
32 | |
33 def __init__(self, npc_name, avatar_path, default_greeting, greetings=None, | |
34 sections=None): | |
35 """ | |
36 Initialize a new L{Dialogue} instance. | |
37 | |
38 @param npc_name: name displayed for the NPC in the dialogue. | |
39 @type npc_name: basestring | |
40 @param avatar_path: path to the image that should be displayed as the | |
41 NPC's avatar. | |
42 @type avatar_path: basestring | |
43 @param default_greeting: section of dialogue that should be | |
44 displayed when the dialogue is first initiated and no other start | |
45 sections are available. | |
46 @type default_greeting: L{DialogueSection} | |
47 @param greetings: sections of dialogue defining the conditions | |
48 under which each should be displayed when the dialogue is first | |
49 initiated. | |
50 @type greetings: list of | |
51 L{RootDialogueSections<DialogueGreeting>} | |
52 @param sections: sections of dialogue that make up this | |
53 L{Dialogue} instance. | |
54 @type sections: list of L{DialogueSections<DialogueSection>} | |
55 """ | |
56 self.npc_name = npc_name | |
57 self.avatar_path = avatar_path | |
58 self.default_greeting = default_greeting | |
59 self.greetings = greetings if greetings is not None else [] | |
60 self.sections = OrderedDict() | |
61 all_sections = [default_greeting] | |
62 if (greetings is not None): | |
63 all_sections += greetings | |
64 if (sections is not None): | |
65 all_sections += sections | |
66 if (__debug__): | |
67 section_ids = [section.id for section in all_sections] | |
68 for section in all_sections: | |
69 # Sanity check: All DialogueResponses should have next_section_id | |
70 # attributes that refer to valid DialogueSections in the Dialogue. | |
71 if (__debug__): | |
72 for response in section.responses: | |
73 assert response.next_section_id in section_ids + \ | |
74 ['end', 'back'], ('"{0}" does not refer to a ' | |
75 'DialogueSection in this Dialogue')\ | |
76 .format(response.next_section_id) | |
77 self.sections[section.id] = section | |
78 | |
79 def __str__(self): | |
80 """Return the string representation of a L{Dialogue} instance.""" | |
81 string_representation = 'Dialogue(npc_id={0.npc_name})'.format(self) | |
82 return string_representation | |
83 | |
84 | |
85 class DialogueNode(object): | |
86 """ | |
87 Abstract base class that represents a node or related group of attributes | |
88 within a Dialogue. | |
89 """ | |
90 def __init__(self, text, actions=None): | |
91 """ | |
92 Initialize a new L{DialogueNode} instance. | |
93 | |
94 @param text: textual content of the L{DialogueNode}. | |
95 @type text: basestring | |
96 @param actions: dialogue actions associated with the L{DialogueNode}. | |
97 @type actions: list of L{DialogueActions<DialogueAction>} | |
98 """ | |
99 self.text = text | |
100 self.actions = actions or [] | |
101 | |
102 | |
103 class DialogueSection(DialogueNode): | |
104 """DialogueNode that represents a distinct section of the dialogue.""" | |
105 __slots__ = ['id', 'text', 'responses', 'actions'] | |
106 | |
107 def __init__(self, id_, text, responses=None, actions=None): | |
108 """ | |
109 Initialize a new L{DialogueSection} instance. | |
110 | |
111 @param id_: named used to uniquely identify the L{DialogueSection} | |
112 within a L{Dialogue}. | |
113 @type id_: basestring | |
114 @param text: text displayed as the NPC's part of the L{Dialogue}. | |
115 @type text: basestring | |
116 @param responses: possible responses that the player can choose from. | |
117 @type responses: list of L{DialogueResponses<DialogueResponse>} | |
118 @param actions: dialogue actions that should be executed when the | |
119 L{DialogueSection} is reached. | |
120 @type actions: list of L{DialogueActions<DialogueAction>} | |
121 """ | |
122 DialogueNode.__init__(self, text=text, actions=actions) | |
123 self.id = id_ | |
124 if (responses is not None): | |
125 self.responses = list(responses) | |
126 | |
127 | |
128 class DialogueGreeting(DialogueSection): | |
129 """ | |
130 Represents a root section of dialogue in a L{Dialogue} along with the | |
131 conditional statement used to determine the whether this section should be | |
132 displayed first upon dialogue initiation. | |
133 | |
134 @ivar id: Name used to uniquely identify the L{DialogueSection} to which | |
135 the L{DialogueRootSectionReference} points. | |
136 @type id: basestring | |
137 @ivar condition: Boolean Python expression used to determine if the | |
138 L{DialogueSection} referenced is a valid starting section. | |
139 @type condition: basestring | |
140 """ | |
141 __slots__ = ['id', 'condition', 'text', 'actions', 'responses'] | |
142 | |
143 def __init__(self, id_, condition, text, responses=None, actions=None): | |
144 """ | |
145 Initialize a new L{DialogueGreeting} instance. | |
146 | |
147 @param id_: named used to uniquely identify the L{DialogueSection} | |
148 within a L{Dialogue}. | |
149 @type id_: basestring | |
150 @param condition: Boolean Python expression used to determine if this | |
151 root dialogue section should be displayed. | |
152 @type condition: basestring | |
153 @param text: text displayed as the NPC's part of the L{Dialogue}. | |
154 @type text: basestring | |
155 @param responses: possible responses that the player can choose from. | |
156 @type responses: list of L{DialogueResponses<DialogueResponse>} | |
157 @param actions: dialogue actions that should be executed when the | |
158 L{DialogueSection} is reached. | |
159 @type actions: list of L{DialogueActions<DialogueAction>} | |
160 """ | |
161 DialogueSection.__init__(self, id_=id_, text=text, responses=responses, | |
162 actions=actions) | |
163 self.condition = condition | |
164 | |
165 | |
166 class DialogueResponse(DialogueNode): | |
167 """ | |
168 L{DialogueNode} that represents one possible player response to a | |
169 particular L{DialogueSection}. | |
170 """ | |
171 __slots__ = ['text', 'actions', 'condition', 'next_section_id'] | |
172 | |
173 def __init__(self, text, next_section_id, actions=None, condition=None): | |
174 """ | |
175 Initialize a new L{DialogueResponse} instance. | |
176 | |
177 @param text: text displayed as the content of the player's response. | |
178 @type text: basestring | |
179 @param next_section_id: ID of the L{DialogueSection} that should be | |
180 jumped to if this response is chosen by the player. | |
181 @type next_section_id: basestring | |
182 @param actions: dialogue actions that should be executed if this | |
183 response is chosen by the player. | |
184 @type actions: list of L{DialogueActions<DialogueAction>} | |
185 @param condition: Python expression that when evaluated determines | |
186 whether the L{DialogueResponse} should be displayed to the player | |
187 as a valid response. | |
188 @type condition: basestring | |
189 """ | |
190 DialogueNode.__init__(self, text=text, actions=actions) | |
191 self.condition = condition | |
192 self.next_section_id = next_section_id |