annotate skaapsteker/dialogue.py @ 632:0675f390653c

Initial port to Python 3 and Pygame 2.
author Simon Cross <hodgestar@gmail.com>
date Fri, 20 Jan 2023 20:01:06 +0100
parents a91b2e4400a5
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
612
a91b2e4400a5 Fallback to using simplejson if json does not exist (this appears to be all that is needed to add Python2.5 compatibility).
Simon Cross <hodgestar@gmail.com>
parents: 557
diff changeset
1 try:
a91b2e4400a5 Fallback to using simplejson if json does not exist (this appears to be all that is needed to add Python2.5 compatibility).
Simon Cross <hodgestar@gmail.com>
parents: 557
diff changeset
2 import json
a91b2e4400a5 Fallback to using simplejson if json does not exist (this appears to be all that is needed to add Python2.5 compatibility).
Simon Cross <hodgestar@gmail.com>
parents: 557
diff changeset
3 except ImportError:
a91b2e4400a5 Fallback to using simplejson if json does not exist (this appears to be all that is needed to add Python2.5 compatibility).
Simon Cross <hodgestar@gmail.com>
parents: 557
diff changeset
4 import simplejson as json
153
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
5
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
6 from . import data
557
e648501c2eea victory scene hacked in
Adrianna Pińska <adrianna.pinska@gmail.com>
parents: 553
diff changeset
7 from .engine import OpenDialog, AddSpriteEvent, ChangeScene
153
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
8
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
9
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
10 class DSM(object):
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
11 """Dialogue State Machine!
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
12
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
13 Parameters
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
14 ----------
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
15 json_filename : str
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
16 Path to file under data/ that contains JSON description
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
17 of state machine.
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
18 world : object
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
19 Something to allow states to introspect the game state with.
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
20 """
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
21
217
fcc5eca8eaca Add explicit starting state to avoid it magically appearing later.
Simon Cross <hodgestar@gmail.com>
parents: 216
diff changeset
22 def __init__(self, name, world, json_filename, state):
331
45755c143813 Save npc state to world when a state transition occurs (fixes monk dialogue tree resetting bug).
Simon Cross <hodgestar@gmail.com>
parents: 302
diff changeset
23 self.name = name
217
fcc5eca8eaca Add explicit starting state to avoid it magically appearing later.
Simon Cross <hodgestar@gmail.com>
parents: 216
diff changeset
24 self.state = state
153
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
25 self.world = world
331
45755c143813 Save npc state to world when a state transition occurs (fixes monk dialogue tree resetting bug).
Simon Cross <hodgestar@gmail.com>
parents: 302
diff changeset
26 self._me = getattr(self.world.npcs, name)
153
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
27 self.states = AttrDict()
632
0675f390653c Initial port to Python 3 and Pygame 2.
Simon Cross <hodgestar@gmail.com>
parents: 612
diff changeset
28 src = json.loads(data.load(json_filename).read())
0675f390653c Initial port to Python 3 and Pygame 2.
Simon Cross <hodgestar@gmail.com>
parents: 612
diff changeset
29 for state, state_src in src.items():
153
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
30 pseudo_path = [json_filename, state]
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
31 self.states[state] = DsmState(state, state_src, pseudo_path)
217
fcc5eca8eaca Add explicit starting state to avoid it magically appearing later.
Simon Cross <hodgestar@gmail.com>
parents: 216
diff changeset
32 assert self.state in self.states, "DSM must have start state %r" % (self.state,)
153
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
33
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
34 def get_state(self):
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
35 return self.states[self.state]
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
36
251
432f6997d306 More hooking up of interacting with NPCs.
Simon Cross <hodgestar@gmail.com>
parents: 246
diff changeset
37 def has_text(self):
286
0dbb50d07764 Poke the current state before checking to see if there is text in case the world has changed and it is time for the state machine to move on.
Simon Cross <hodgestar@gmail.com>
parents: 285
diff changeset
38 self.poke()
251
432f6997d306 More hooking up of interacting with NPCs.
Simon Cross <hodgestar@gmail.com>
parents: 246
diff changeset
39 return bool(self.states[self.state].text)
432f6997d306 More hooking up of interacting with NPCs.
Simon Cross <hodgestar@gmail.com>
parents: 246
diff changeset
40
302
78220c989e6a Add supporting for flicking between speaking NPCs.
Simon Cross <hodgestar@gmail.com>
parents: 291
diff changeset
41 def _switch_dialogue_to(self, npc_name):
78220c989e6a Add supporting for flicking between speaking NPCs.
Simon Cross <hodgestar@gmail.com>
parents: 291
diff changeset
42 """Switch dialogue to another npc."""
78220c989e6a Add supporting for flicking between speaking NPCs.
Simon Cross <hodgestar@gmail.com>
parents: 291
diff changeset
43 OpenDialog.post(npc_name)
78220c989e6a Add supporting for flicking between speaking NPCs.
Simon Cross <hodgestar@gmail.com>
parents: 291
diff changeset
44
490
0eade58a71b9 Support item dropping (specifically tails). Have monk drop tail.
Simon Cross <hodgestar@gmail.com>
parents: 483
diff changeset
45 def _drop_item(self, item, shift=(1, 0)):
476
1c05b6c2b971 Start of drop item support.
Simon Cross <hodgestar@gmail.com>
parents: 331
diff changeset
46 """Create a tail of the given type."""
490
0eade58a71b9 Support item dropping (specifically tails). Have monk drop tail.
Simon Cross <hodgestar@gmail.com>
parents: 483
diff changeset
47 to_level = self._me.level
0eade58a71b9 Support item dropping (specifically tails). Have monk drop tail.
Simon Cross <hodgestar@gmail.com>
parents: 483
diff changeset
48 to_pos = self._me.pos
0eade58a71b9 Support item dropping (specifically tails). Have monk drop tail.
Simon Cross <hodgestar@gmail.com>
parents: 483
diff changeset
49 to_pos = to_pos[0] + shift[0], to_pos[1] + shift[1]
0eade58a71b9 Support item dropping (specifically tails). Have monk drop tail.
Simon Cross <hodgestar@gmail.com>
parents: 483
diff changeset
50 gamestate = self.world.gamestate()
0eade58a71b9 Support item dropping (specifically tails). Have monk drop tail.
Simon Cross <hodgestar@gmail.com>
parents: 483
diff changeset
51 sprite = gamestate.create_item_sprite(item, to_level=to_level, to_pos=to_pos)
0eade58a71b9 Support item dropping (specifically tails). Have monk drop tail.
Simon Cross <hodgestar@gmail.com>
parents: 483
diff changeset
52 AddSpriteEvent.post(sprite)
476
1c05b6c2b971 Start of drop item support.
Simon Cross <hodgestar@gmail.com>
parents: 331
diff changeset
53
557
e648501c2eea victory scene hacked in
Adrianna Pińska <adrianna.pinska@gmail.com>
parents: 553
diff changeset
54 def _end_game(self):
e648501c2eea victory scene hacked in
Adrianna Pińska <adrianna.pinska@gmail.com>
parents: 553
diff changeset
55 """End the game"""
e648501c2eea victory scene hacked in
Adrianna Pińska <adrianna.pinska@gmail.com>
parents: 553
diff changeset
56 from .cutscene import VictoryCutScene
e648501c2eea victory scene hacked in
Adrianna Pińska <adrianna.pinska@gmail.com>
parents: 553
diff changeset
57 ChangeScene.post(VictoryCutScene(None, None))
e648501c2eea victory scene hacked in
Adrianna Pińska <adrianna.pinska@gmail.com>
parents: 553
diff changeset
58
521
5a8a7f17597d Add support for 'if': '...' to dialogue choices.
Simon Cross <hodgestar@gmail.com>
parents: 490
diff changeset
59 def _make_locals(self):
153
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
60 my_locals = {
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
61 "state": self.states,
193
897eec397cbb Fix state checks for hattori, ichiro, kaneda and kumiko. In the process provide easier access to other npcs.
Simon Cross <hodgestar@gmail.com>
parents: 190
diff changeset
62 "world": self.world,
897eec397cbb Fix state checks for hattori, ichiro, kaneda and kumiko. In the process provide easier access to other npcs.
Simon Cross <hodgestar@gmail.com>
parents: 190
diff changeset
63 "npcs": self.world.npcs,
302
78220c989e6a Add supporting for flicking between speaking NPCs.
Simon Cross <hodgestar@gmail.com>
parents: 291
diff changeset
64 "switch_to": self._switch_dialogue_to,
476
1c05b6c2b971 Start of drop item support.
Simon Cross <hodgestar@gmail.com>
parents: 331
diff changeset
65 "drop_item": self._drop_item,
557
e648501c2eea victory scene hacked in
Adrianna Pińska <adrianna.pinska@gmail.com>
parents: 553
diff changeset
66 "end_game": self._end_game,
153
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
67 }
521
5a8a7f17597d Add support for 'if': '...' to dialogue choices.
Simon Cross <hodgestar@gmail.com>
parents: 490
diff changeset
68 return my_locals
5a8a7f17597d Add support for 'if': '...' to dialogue choices.
Simon Cross <hodgestar@gmail.com>
parents: 490
diff changeset
69
5a8a7f17597d Add support for 'if': '...' to dialogue choices.
Simon Cross <hodgestar@gmail.com>
parents: 490
diff changeset
70 def choices(self):
5a8a7f17597d Add support for 'if': '...' to dialogue choices.
Simon Cross <hodgestar@gmail.com>
parents: 490
diff changeset
71 my_locals = self._make_locals()
5a8a7f17597d Add support for 'if': '...' to dialogue choices.
Simon Cross <hodgestar@gmail.com>
parents: 490
diff changeset
72 state = self.states[self.state]
5a8a7f17597d Add support for 'if': '...' to dialogue choices.
Simon Cross <hodgestar@gmail.com>
parents: 490
diff changeset
73 return state.choices(my_locals)
5a8a7f17597d Add support for 'if': '...' to dialogue choices.
Simon Cross <hodgestar@gmail.com>
parents: 490
diff changeset
74
5a8a7f17597d Add support for 'if': '...' to dialogue choices.
Simon Cross <hodgestar@gmail.com>
parents: 490
diff changeset
75 def event(self, ev):
5a8a7f17597d Add support for 'if': '...' to dialogue choices.
Simon Cross <hodgestar@gmail.com>
parents: 490
diff changeset
76 my_locals = self._make_locals()
153
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
77 my_locals.update(ev.items)
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
78 state = self.states[self.state]
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
79 next_state = state.event(my_locals)
246
8dee25fd070d Fix some npc-test and dialogue bugs.
Simon Cross <hodgestar@gmail.com>
parents: 233
diff changeset
80 if next_state is not None and next_state.name in self.states:
216
023eea4ad4a5 Add support for trigger world changes when entering and exiting dialog states.
Simon Cross <hodgestar@gmail.com>
parents: 196
diff changeset
81 self.states[self.state].leave(my_locals)
153
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
82 self.state = next_state.name
331
45755c143813 Save npc state to world when a state transition occurs (fixes monk dialogue tree resetting bug).
Simon Cross <hodgestar@gmail.com>
parents: 302
diff changeset
83 self._me.state = self.state
216
023eea4ad4a5 Add support for trigger world changes when entering and exiting dialog states.
Simon Cross <hodgestar@gmail.com>
parents: 196
diff changeset
84 self.states[self.state].enter(my_locals)
153
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
85
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
86 def choice(self, i):
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
87 self.event(DsmEvent(choice=i))
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
88
285
71f15f6e9274 Hook up auto_next dialogue events.
Simon Cross <hodgestar@gmail.com>
parents: 251
diff changeset
89 def auto_next(self):
71f15f6e9274 Hook up auto_next dialogue events.
Simon Cross <hodgestar@gmail.com>
parents: 251
diff changeset
90 self.event(DsmEvent(auto_next=True))
71f15f6e9274 Hook up auto_next dialogue events.
Simon Cross <hodgestar@gmail.com>
parents: 251
diff changeset
91
286
0dbb50d07764 Poke the current state before checking to see if there is text in case the world has changed and it is time for the state machine to move on.
Simon Cross <hodgestar@gmail.com>
parents: 285
diff changeset
92 def poke(self):
0dbb50d07764 Poke the current state before checking to see if there is text in case the world has changed and it is time for the state machine to move on.
Simon Cross <hodgestar@gmail.com>
parents: 285
diff changeset
93 # poke the current state to see if it feels like making
0dbb50d07764 Poke the current state before checking to see if there is text in case the world has changed and it is time for the state machine to move on.
Simon Cross <hodgestar@gmail.com>
parents: 285
diff changeset
94 # a transition.
0dbb50d07764 Poke the current state before checking to see if there is text in case the world has changed and it is time for the state machine to move on.
Simon Cross <hodgestar@gmail.com>
parents: 285
diff changeset
95 self.event(DsmEvent(poke=True))
0dbb50d07764 Poke the current state before checking to see if there is text in case the world has changed and it is time for the state machine to move on.
Simon Cross <hodgestar@gmail.com>
parents: 285
diff changeset
96
153
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
97
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
98 class AttrDict(dict):
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
99
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
100 def __getattr__(self, name):
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
101 if name not in self:
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
102 raise AttributeError("No attribute %r" % (name,))
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
103 return self[name]
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
104
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
105
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
106 class DsmEvent(object):
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
107
286
0dbb50d07764 Poke the current state before checking to see if there is text in case the world has changed and it is time for the state machine to move on.
Simon Cross <hodgestar@gmail.com>
parents: 285
diff changeset
108 def __init__(self, choice=None, auto_next=False, poke=False):
153
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
109 self.items = {
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
110 "choice": choice,
285
71f15f6e9274 Hook up auto_next dialogue events.
Simon Cross <hodgestar@gmail.com>
parents: 251
diff changeset
111 "auto_next": auto_next,
286
0dbb50d07764 Poke the current state before checking to see if there is text in case the world has changed and it is time for the state machine to move on.
Simon Cross <hodgestar@gmail.com>
parents: 285
diff changeset
112 "poke": poke,
153
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
113 }
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
114
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
115
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
116 class DsmState(object):
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
117 """State within a DSM.
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
118 """
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
119
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
120 def __init__(self, name, state_src, base_path):
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
121 self.name = name
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
122 self.text = state_src.get("text", None)
521
5a8a7f17597d Add support for 'if': '...' to dialogue choices.
Simon Cross <hodgestar@gmail.com>
parents: 490
diff changeset
123 self._choices = []
153
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
124 self.triggers = []
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
125
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
126 choices = state_src.get("choices", [])
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
127 for i, choice in enumerate(choices):
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
128 pseudo_path = base_path + ["choice-%d" % i]
521
5a8a7f17597d Add support for 'if': '...' to dialogue choices.
Simon Cross <hodgestar@gmail.com>
parents: 490
diff changeset
129 if "if" in choice:
5a8a7f17597d Add support for 'if': '...' to dialogue choices.
Simon Cross <hodgestar@gmail.com>
parents: 490
diff changeset
130 choice_if = compile(choice["if"],
5a8a7f17597d Add support for 'if': '...' to dialogue choices.
Simon Cross <hodgestar@gmail.com>
parents: 490
diff changeset
131 "<%s>" % ":".join(pseudo_path + ["if"]),
5a8a7f17597d Add support for 'if': '...' to dialogue choices.
Simon Cross <hodgestar@gmail.com>
parents: 490
diff changeset
132 "eval")
5a8a7f17597d Add support for 'if': '...' to dialogue choices.
Simon Cross <hodgestar@gmail.com>
parents: 490
diff changeset
133 else:
5a8a7f17597d Add support for 'if': '...' to dialogue choices.
Simon Cross <hodgestar@gmail.com>
parents: 490
diff changeset
134 choice_if = None
5a8a7f17597d Add support for 'if': '...' to dialogue choices.
Simon Cross <hodgestar@gmail.com>
parents: 490
diff changeset
135 self._choices.append((i, choice["text"], choice_if))
153
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
136 next_state_code = choice.get("next", None)
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
137 if next_state_code is not None:
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
138 self.triggers.append(
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
139 Trigger("choice == %d" % i, next_state_code, pseudo_path))
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
140
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
141 events = state_src.get("events", [])
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
142 for i, event in enumerate(events):
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
143 pseudo_path = base_path + ["event-%d" % i]
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
144 self.triggers.append(Trigger(event["matches"], event["next"],
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
145 pseudo_path))
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
146
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
147 auto_next = state_src.get("auto_next", None)
291
04be4219742b Add support for auto_next_text to give the auto_next effect but with a different prompt.
Simon Cross <hodgestar@gmail.com>
parents: 286
diff changeset
148 self.auto_next_text = state_src.get("auto_next_text", None)
285
71f15f6e9274 Hook up auto_next dialogue events.
Simon Cross <hodgestar@gmail.com>
parents: 251
diff changeset
149 self.auto_next = False
153
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
150 if auto_next is not None:
285
71f15f6e9274 Hook up auto_next dialogue events.
Simon Cross <hodgestar@gmail.com>
parents: 251
diff changeset
151 self.auto_next = True
521
5a8a7f17597d Add support for 'if': '...' to dialogue choices.
Simon Cross <hodgestar@gmail.com>
parents: 490
diff changeset
152 assert not self._choices, "%s: auto_next and choices are not compatible" % ":".join(base_path)
153
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
153 pseudo_path = base_path + ["auto_next"]
285
71f15f6e9274 Hook up auto_next dialogue events.
Simon Cross <hodgestar@gmail.com>
parents: 251
diff changeset
154 self.triggers.append(Trigger("""auto_next""", auto_next, pseudo_path))
153
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
155
216
023eea4ad4a5 Add support for trigger world changes when entering and exiting dialog states.
Simon Cross <hodgestar@gmail.com>
parents: 196
diff changeset
156 on_entry = state_src.get("on_entry", None)
023eea4ad4a5 Add support for trigger world changes when entering and exiting dialog states.
Simon Cross <hodgestar@gmail.com>
parents: 196
diff changeset
157 if on_entry is not None:
023eea4ad4a5 Add support for trigger world changes when entering and exiting dialog states.
Simon Cross <hodgestar@gmail.com>
parents: 196
diff changeset
158 self.on_entry = compile(on_entry,
023eea4ad4a5 Add support for trigger world changes when entering and exiting dialog states.
Simon Cross <hodgestar@gmail.com>
parents: 196
diff changeset
159 "<%s>" % ":".join(base_path + ["on_entry"]),
023eea4ad4a5 Add support for trigger world changes when entering and exiting dialog states.
Simon Cross <hodgestar@gmail.com>
parents: 196
diff changeset
160 "exec")
233
8ea658969f47 Fix on_entry and on_exit handling.
Simon Cross <hodgestar@gmail.com>
parents: 217
diff changeset
161 else:
8ea658969f47 Fix on_entry and on_exit handling.
Simon Cross <hodgestar@gmail.com>
parents: 217
diff changeset
162 self.on_entry = None
216
023eea4ad4a5 Add support for trigger world changes when entering and exiting dialog states.
Simon Cross <hodgestar@gmail.com>
parents: 196
diff changeset
163
023eea4ad4a5 Add support for trigger world changes when entering and exiting dialog states.
Simon Cross <hodgestar@gmail.com>
parents: 196
diff changeset
164 on_exit = state_src.get("on_exit", None)
023eea4ad4a5 Add support for trigger world changes when entering and exiting dialog states.
Simon Cross <hodgestar@gmail.com>
parents: 196
diff changeset
165 if on_exit is not None:
023eea4ad4a5 Add support for trigger world changes when entering and exiting dialog states.
Simon Cross <hodgestar@gmail.com>
parents: 196
diff changeset
166 self.on_exit = compile(on_exit,
023eea4ad4a5 Add support for trigger world changes when entering and exiting dialog states.
Simon Cross <hodgestar@gmail.com>
parents: 196
diff changeset
167 "<%s>" % ":".join(base_path + ["on_exit"]),
023eea4ad4a5 Add support for trigger world changes when entering and exiting dialog states.
Simon Cross <hodgestar@gmail.com>
parents: 196
diff changeset
168 "exec")
233
8ea658969f47 Fix on_entry and on_exit handling.
Simon Cross <hodgestar@gmail.com>
parents: 217
diff changeset
169 else:
8ea658969f47 Fix on_entry and on_exit handling.
Simon Cross <hodgestar@gmail.com>
parents: 217
diff changeset
170 self.on_exit = None
216
023eea4ad4a5 Add support for trigger world changes when entering and exiting dialog states.
Simon Cross <hodgestar@gmail.com>
parents: 196
diff changeset
171
153
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
172 def __repr__(self):
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
173 return "<%r name=%r>" % (self.__class__.__name__, self.name)
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
174
521
5a8a7f17597d Add support for 'if': '...' to dialogue choices.
Simon Cross <hodgestar@gmail.com>
parents: 490
diff changeset
175 def choices(self, my_locals):
5a8a7f17597d Add support for 'if': '...' to dialogue choices.
Simon Cross <hodgestar@gmail.com>
parents: 490
diff changeset
176 for i, text, choice_if in self._choices:
5a8a7f17597d Add support for 'if': '...' to dialogue choices.
Simon Cross <hodgestar@gmail.com>
parents: 490
diff changeset
177 if choice_if is None:
5a8a7f17597d Add support for 'if': '...' to dialogue choices.
Simon Cross <hodgestar@gmail.com>
parents: 490
diff changeset
178 yield i, text
5a8a7f17597d Add support for 'if': '...' to dialogue choices.
Simon Cross <hodgestar@gmail.com>
parents: 490
diff changeset
179 elif eval(choice_if, {}, my_locals.copy()):
5a8a7f17597d Add support for 'if': '...' to dialogue choices.
Simon Cross <hodgestar@gmail.com>
parents: 490
diff changeset
180 yield i, text
5a8a7f17597d Add support for 'if': '...' to dialogue choices.
Simon Cross <hodgestar@gmail.com>
parents: 490
diff changeset
181
153
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
182 def event(self, my_locals):
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
183 for trigger in self.triggers:
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
184 next_state = trigger.fire(my_locals)
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
185 if next_state is not None:
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
186 return next_state
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
187
216
023eea4ad4a5 Add support for trigger world changes when entering and exiting dialog states.
Simon Cross <hodgestar@gmail.com>
parents: 196
diff changeset
188 def enter(self, my_locals):
233
8ea658969f47 Fix on_entry and on_exit handling.
Simon Cross <hodgestar@gmail.com>
parents: 217
diff changeset
189 if self.on_entry is not None:
8ea658969f47 Fix on_entry and on_exit handling.
Simon Cross <hodgestar@gmail.com>
parents: 217
diff changeset
190 exec(self.on_entry, {}, my_locals.copy())
216
023eea4ad4a5 Add support for trigger world changes when entering and exiting dialog states.
Simon Cross <hodgestar@gmail.com>
parents: 196
diff changeset
191
023eea4ad4a5 Add support for trigger world changes when entering and exiting dialog states.
Simon Cross <hodgestar@gmail.com>
parents: 196
diff changeset
192 def leave(self, my_locals):
233
8ea658969f47 Fix on_entry and on_exit handling.
Simon Cross <hodgestar@gmail.com>
parents: 217
diff changeset
193 if self.on_exit is not None:
8ea658969f47 Fix on_entry and on_exit handling.
Simon Cross <hodgestar@gmail.com>
parents: 217
diff changeset
194 exec(self.on_exit, {}, my_locals.copy())
216
023eea4ad4a5 Add support for trigger world changes when entering and exiting dialog states.
Simon Cross <hodgestar@gmail.com>
parents: 196
diff changeset
195
153
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
196
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
197 class Trigger(object):
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
198 """Matches DSM events and triggers state transitions.
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
199 """
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
200
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
201 def __init__(self, matches_code, next_state_code, pseudo_path):
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
202 self._matches = compile(matches_code,
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
203 "<%s>" % ":".join(pseudo_path + ["match"]),
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
204 "eval")
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
205 self._next_state = compile(next_state_code,
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
206 "<%s>" % ":".join(pseudo_path + ["next"]),
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
207 "eval")
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
208
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
209 def fire(self, my_locals):
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
210 if eval(self._matches, {}, my_locals.copy()):
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
211 return eval(self._next_state, {}, my_locals.copy())
704d23022f09 Start of dialogue tree / NPC state machine support.
Simon Cross <hodgestar@gmail.com>
parents:
diff changeset
212 return None