source: trunk/game/scripts/dialogue.py @ 709

Revision 709, 8.1 KB checked in by technomage, 9 years ago (diff)

Patch by Technomage

  • Got rid of an annoying print statement in scripts/dialogue.py that printed all dialogue sections upon load;
  • Property svn:eol-style set to native
Line 
1#!/usr/bin/env python
2#
3#   This file is part of PARPG.
4#
5#   PARPG is free software: you can redistribute it and/or modify
6#   it under the terms of the GNU General Public License as published by
7#   the Free Software Foundation, either version 3 of the License, or
8#   (at your option) any later version.
9#
10#   PARPG is distributed in the hope that it will be useful,
11#   but WITHOUT ANY WARRANTY; without even the implied warranty of
12#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13#   GNU General Public License for more details.
14#
15#   You should have received a copy of the GNU General Public License
16#   along with PARPG.  If not, see <http://www.gnu.org/licenses/>.
17"""
18Provides classes used to contain and organize dialogue data for use within
19in-game dialogues between the player character and NPCs.
20"""
21try:
22    from collections import OrderedDict
23except ImportError:
24    # Python version 2.4-2.6 doesn't have the OrderedDict
25    from scripts.common.ordereddict import OrderedDict
26
27class Dialogue(object):
28    """
29    Represents a complete dialogue and acts as a container for the dialogue
30    data belonging to a particular NPC.
31    """
32    __slots__ = ['npc_name', 'avatar_path', 'default_greeting',
33                 'greetings', 'sections']
34   
35    def __init__(self, npc_name, avatar_path, default_greeting, greetings=None,
36                 sections=None):
37        """
38        Initialize a new L{Dialogue} instance.
39       
40        @param npc_name: name displayed for the NPC in the dialogue.
41        @type npc_name: basestring
42        @param avatar_path: path to the image that should be displayed as the
43            NPC's avatar.
44        @type avatar_path: basestring
45        @param default_greeting: section of dialogue that should be
46            displayed when the dialogue is first initiated and no other start
47            sections are available.
48        @type default_greeting: L{DialogueSection}
49        @param greetings: sections of dialogue defining the conditions
50            under which each should be displayed when the dialogue is first
51            initiated.
52        @type greetings: list of
53            L{RootDialogueSections<DialogueGreeting>}
54        @param sections: sections of dialogue that make up this
55            L{Dialogue} instance.
56        @type sections: list of L{DialogueSections<DialogueSection>}
57        """
58        self.npc_name = npc_name
59        self.avatar_path = avatar_path
60        self.default_greeting = default_greeting
61        self.greetings = greetings if greetings is not None else []
62        self.sections = OrderedDict()
63        all_sections = [default_greeting]
64        if (greetings is not None):
65            all_sections += greetings
66        if (sections is not None):
67            all_sections += sections
68        if (__debug__):
69            section_ids = [section.id for section in all_sections]
70        for section in all_sections:
71            # Sanity check: All DialogueResponses should have next_section_id
72            # attributes that refer to valid DialogueSections in the Dialogue.
73            if (__debug__):
74                for response in section.responses:
75                    assert response.next_section_id in section_ids + \
76                        ['end', 'back'], ('"{0}" does not refer to a ' 
77                                          'DialogueSection in this Dialogue')\
78                        .format(response.next_section_id)
79            self.sections[section.id] = section
80   
81    def __str__(self):
82        """Return the string representation of a L{Dialogue} instance."""
83        string_representation = 'Dialogue(npc_id={0.npc_name})'.format(self)
84        return string_representation
85
86
87class DialogueNode(object):
88    """
89    Abstract base class that represents a node or related group of attributes
90    within a Dialogue.
91    """
92    def __init__(self, text, actions=None):
93        """
94        Initialize a new L{DialogueNode} instance.
95       
96        @param text: textual content of the L{DialogueNode}.
97        @type text: basestring
98        @param actions: dialogue actions associated with the L{DialogueNode}.
99        @type actions: list of L{DialogueActions<DialogueAction>}
100        """
101        self.text = text
102        self.actions = actions or []
103
104
105class DialogueSection(DialogueNode):
106    """DialogueNode that represents a distinct section of the dialogue."""
107    __slots__ = ['id', 'text', 'responses', 'actions']
108   
109    def __init__(self, id_, text, responses=None, actions=None):
110        """
111        Initialize a new L{DialogueSection} instance.
112       
113        @param id_: named used to uniquely identify the L{DialogueSection}
114            within a L{Dialogue}.
115        @type id_: basestring
116        @param text: text displayed as the NPC's part of the L{Dialogue}.
117        @type text: basestring
118        @param responses: possible responses that the player can choose from.
119        @type responses: list of L{DialogueResponses<DialogueResponse>}
120        @param actions: dialogue actions that should be executed when the
121            L{DialogueSection} is reached.
122        @type actions: list of L{DialogueActions<DialogueAction>}
123        """
124        DialogueNode.__init__(self, text=text, actions=actions)
125        self.id = id_
126        if (responses is not None):
127            self.responses = list(responses)
128
129
130class DialogueGreeting(DialogueSection):
131    """
132    Represents a root section of dialogue in a L{Dialogue} along with the
133    conditional statement used to determine the whether this section should be
134    displayed first upon dialogue initiation.
135   
136    @ivar id: Name used to uniquely identify the L{DialogueSection} to which
137        the L{DialogueRootSectionReference} points.
138    @type id: basestring
139    @ivar condition: Boolean Python expression used to determine if the
140        L{DialogueSection} referenced is a valid starting section.
141    @type condition: basestring
142    """
143    __slots__ = ['id', 'condition', 'text', 'actions', 'responses']
144   
145    def __init__(self, id_, condition, text, responses=None, actions=None):
146        """
147        Initialize a new L{DialogueGreeting} instance.
148       
149        @param id_: named used to uniquely identify the L{DialogueSection}
150            within a L{Dialogue}.
151        @type id_: basestring
152        @param condition: Boolean Python expression used to determine if this
153            root dialogue section should be displayed.
154        @type condition: basestring
155        @param text: text displayed as the NPC's part of the L{Dialogue}.
156        @type text: basestring
157        @param responses: possible responses that the player can choose from.
158        @type responses: list of L{DialogueResponses<DialogueResponse>}
159        @param actions: dialogue actions that should be executed when the
160            L{DialogueSection} is reached.
161        @type actions: list of L{DialogueActions<DialogueAction>}
162        """
163        DialogueSection.__init__(self, id_=id_, text=text, responses=responses,
164                                 actions=actions)
165        self.condition = condition
166
167
168class DialogueResponse(DialogueNode):
169    """
170    L{DialogueNode} that represents one possible player response to a
171    particular L{DialogueSection}.
172    """
173    __slots__ = ['text', 'actions', 'condition', 'next_section_id']
174   
175    def __init__(self, text, next_section_id, actions=None, condition=None):
176        """
177        Initialize a new L{DialogueResponse} instance.
178       
179        @param text: text displayed as the content of the player's response.
180        @type text: basestring
181        @param next_section_id: ID of the L{DialogueSection} that should be
182            jumped to if this response is chosen by the player.
183        @type next_section_id: basestring
184        @param actions: dialogue actions that should be executed if this
185            response is chosen by the player.
186        @type actions: list of L{DialogueActions<DialogueAction>}
187        @param condition: Python expression that when evaluated determines
188            whether the L{DialogueResponse} should be displayed to the player
189            as a valid response.
190        @type condition: basestring
191        """
192        DialogueNode.__init__(self, text=text, actions=actions)
193        self.condition = condition
194        self.next_section_id = next_section_id
Note: See TracBrowser for help on using the repository browser.