git @ Cat's Eye Technologies The-Swallows / 6e903da
Now that the new Editor knows their job, retire the old one. Cat's Eye Technologies 9 years ago
3 changed file(s) with 17 addition(s) and 169 deletion(s). Raw diff Collapse all Expand all
1111 sys.path.insert(0, join(dirname(realpath(sys.argv[0])), '..', 'src'))
1212
1313 # now we can:
14 from swallows.engine.events import LegacyPublisher
14 from swallows.engine.events import Publisher
1515 from swallows.engine.objects import Location, ProperLocation, Male, Female
1616
1717 ### world ###
3737
3838 ### main ###
3939
40 publisher = LegacyPublisher(
40 publisher = Publisher(
4141 characters=(
4242 tweedledee,
4343 tweedledum,
1010 sys.path.insert(0, join(dirname(realpath(sys.argv[0])), '..', 'src'))
1111
1212 # now we can:
13 from swallows.engine.events import LegacyPublisher
13 from swallows.engine.events import Publisher
1414 from swallows.story.characters import MaleCharacter
1515 from swallows.story.world import (
1616 alice, bob, house,
3131
3232 ### main ###
3333
34 publisher = LegacyPublisher(
34 publisher = Publisher(
3535 characters=(
3636 alice,
3737 bob,
77 # TODO
88
99 # Diction:
10 # the event-accumulation framework could use rewriting at some point.
11 # eliminate identical duplicate sentences
12 # Bob is in the dining room & "Bob made his way to the dining room" ->
13 # "Bob wandered around for a bit, then came back to the dining room"
14 # a better solution for "Bob was in the kitchen" at the start of a paragraph;
10 # - eliminate identical duplicate sentences
11 # - Bob is in the dining room & "Bob made his way to the dining room" ->
12 # "Bob wandered around for a bit, then came back to the dining room"
13 # - comvert "Bob went to the shed. Bob saw Alice." into
14 # "Bob went to the shed, where he saw Alice."
15 # - a better solution for "Bob was in the kitchen" at the start of a paragraph;
1516 # this might include significant memories Bob acquired in the last
1617 # paragraph -- such as finding a revolver in the bed
17 # paragraphs should not always be the same number of events. variety!
18 # the Editor should take all the events in the chapter, and decide where
19 # paragraph breaks should go. this is difficult, because syncing up
20 # Bob's and Alice's events. timestamps?
21 # at least, the Editor should record "rich events", which include information
22 # about the main (acting) character, and where the audience last saw them
23 # use indef art when they have no memory of an item that they see
24 # dramatic irony would be really nice, but hard to pull off. Well, a certain
25 # amount happens naturally now, with character pov. but more could be done
26 # "Chapter 3. _In which Bob hides the stolen jewels in the mailbox, etc_" --
27 # i.e. chapter summaries -- that's a little too fancy to hope for, but with
28 # a sufficiently smart Editor it could be done
18 # - use indef art when they have no memory of an item that they see
19 # - dramatic irony would be really nice, but hard to pull off. Well, a certain
20 # amount happens naturally now, with character pov. but more could be done
21 # - "Chapter 3. _In which Bob hides the stolen jewels in the mailbox, etc_" --
22 # i.e. chapter summaries -- that's a little too fancy to hope for, but with
23 # a sufficiently smart Editor it could be done
2924
3025 ### EVENTS ###
3126
10398 oblivion = Oblivion()
10499
105100
106 # 'diction engine' -- almost exactly like a peephole optimizer -- convert
107 # "Bob went to the shed. Bob saw Alice." into
108 # "Bob went to the shed, where he saw Alice."
109 # btw, it doesn't do that exact example yet.
110 # btw, we currently get a new editor for every paragraph
111 class LegacyEditor(object):
112 """The LegacyEditor is remarkably similar to the _peephole optimizer_ in
113 compiler construction. Instead of replacing sequences of instructions
114 with more efficient but semantically equivalent sequences of
115 instructions, it replaces sequences of sentences with more readable
116 but semantically equivalent sequences of sentences.
117
118 """
119 MEMORY = 1
120
121 def __init__(self):
122 self.character = None
123 self.character_location = {}
124 self.events = []
125
126 def read(self, event):
127 if len(self.events) < self.__class__.MEMORY:
128 self.events.append(event)
129 return
130
131 character = event.participants[0]
132 # update our idea of their location
133 self.character_location[character.name] = character.location
134 # todo: check our idea of their location vs where they are,
135 # but that won't matter until an editor looks at more than one
136 # paragraph anyway
137
138 if character == self.character: # same character doing stuff
139 if event.phrase.startswith('<1>'):
140 event.phrase = '<he-1>' + event.phrase[3:]
141
142 if (self.events[-1].phrase == '<1> made <his-1> way to <2>' and
143 event.phrase == '<1> went to <2>'):
144 self.events[-1].participants[1] = event.participants[1]
145 elif (self.events[-1].phrase == '<1> went to <2>' and
146 event.phrase == '<1> went to <2>'):
147 self.events[-1].phrase = '<1> made <his-1> way to <2>'
148 self.events[-1].participants[1] = event.participants[1]
149 elif (self.events[-1].phrase == '<he-1> made <his-1> way to <2>' and
150 event.phrase == '<he-1> went to <2>'):
151 self.events[-1].participants[1] = event.participants[1]
152 elif (self.events[-1].phrase == '<he-1> went to <2>' and
153 event.phrase == '<he-1> went to <2>'):
154 self.events[-1].phrase = '<he-1> made <his-1> way to <2>'
155 self.events[-1].participants[1] = event.participants[1]
156 else:
157 self.events.append(event)
158 else: # new character doing stuff
159 self.character = character
160 self.events.append(event)
161
162
163 class LegacyPublisher(object):
164 """Publisher which uses the old Event/Editor framework.
165
166 Will probably go away eventually, but nice to have as a reference
167 while working on the new Event/Editor framework.
168
169 """
170 def __init__(self, **kwargs):
171 self.characters = kwargs.get('characters')
172 self.setting = kwargs.get('setting')
173 self.friffery = kwargs.get('friffery', False)
174 self.debug = kwargs.get('debug', False)
175 self.title = kwargs.get('title', "Untitled")
176 self.chapters = kwargs.get('chapters', 16)
177 self.paragraphs_per_chapter = kwargs.get('paragraphs_per_chapter', 25)
178
179 def publish(self):
180 print self.title
181 print "=" * len(self.title)
182 print
183
184 for chapter in range(1, self.chapters+1):
185 print "Chapter %d." % chapter
186 print "-----------"
187 print
188
189 for character in self.characters:
190 # don't continue a conversation from the previous chapter, please
191 character.topic = None
192 character.place_in(pick(self.setting))
193
194 for paragraph in range(1, self.paragraphs_per_chapter+1):
195 for character in self.characters:
196 character.collector = EventCollector()
197
198 # we alternate pov like so:
199 pov_actor = (self.characters)[(paragraph - 1) % len(self.characters)]
200
201 for actor in self.characters:
202 # this is hacky & won't work for >2 characters:
203 if self.characters[0].location is not self.characters[1].location:
204 actor.emit("<1> was in <2>", [actor, actor.location])
205
206 while len(pov_actor.collector.events) < 20:
207 for actor in self.characters:
208 actor.live()
209
210 if self.friffery:
211 if paragraph == 1:
212 choice = random.randint(0, 3)
213 if choice == 0:
214 sys.stdout.write("It was raining. ")
215 if choice == 1:
216 sys.stdout.write("It was snowing. ")
217 if choice == 2:
218 sys.stdout.write("The sun was shining. ")
219 if choice == 3:
220 sys.stdout.write("The day was overcast and humid. ")
221 elif not str(c.events[0]).startswith("'"):
222 choice = random.randint(0, 8)
223 if choice == 0:
224 sys.stdout.write("Later on, ")
225 if choice == 1:
226 sys.stdout.write("Suddenly, ")
227 if choice == 2:
228 sys.stdout.write("After a moment's consideration, ")
229 if choice == 3:
230 sys.stdout.write("Feeling anxious, ")
231
232 if self.debug:
233 for character in self.characters:
234 print "%s'S POV:" % character.name.upper()
235 for event in character.collector.events:
236 print str(event)
237 print
238 character.dump_memory()
239 print
240 print "- - - - -"
241 print
242
243 if not self.debug:
244 editor = LegacyEditor()
245 for event in pov_actor.collector.events:
246 editor.read(event)
247 for event in editor.events:
248 sys.stdout.write(str(event) + " ")
249 #sys.stdout.write("\n")
250 print
251 print
252
253
254101 ### the new stuff ###
102
255103
256104 class Editor(object):
257105 """The Editor is remarkably similar to the _peephole optimizer_ in