1
0
Fork 0
mirror of https://github.com/ganelson/inform.git synced 2024-07-05 08:34:22 +03:00
inform7/docs/if-module/3-scn.html
2019-04-13 18:58:43 +01:00

1696 lines
185 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>3/sc</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="Content-Language" content="en-gb">
<link href="inweb.css" rel="stylesheet" rev="stylesheet" type="text/css">
</head>
<body>
<!--Weave of '3/scn' generated by 7-->
<ul class="crumbs"><li><a href="../webs.html">&#9733;</a></li><li><a href="index.html">if</a></li><li><a href="index.html#3">Chapter 3: Space and Time</a></li><li><b>Scenes</b></li></ul><p class="purpose">Scenes are periods of time during play: at any given moment, several may be going on, or none. They are started and stopped when certain conditions are met, or by virtue of having been anchored together.</p>
<ul class="toc"><li><a href="#SP1">&#167;1. Definitions</a></li><li><a href="#SP7">&#167;7. Plugin calls</a></li><li><a href="#SP12">&#167;12. Scene structures</a></li><li><a href="#SP14">&#167;14. Creating and parsing ends</a></li><li><a href="#SP15">&#167;15. Scene end rulebooks</a></li><li><a href="#SP16">&#167;16. Anchors</a></li><li><a href="#SP25">&#167;25. Scene-changing machinery at run-time</a></li><li><a href="#SP29">&#167;29. More SCENES output</a></li><li><a href="#SP30">&#167;30. During clauses</a></li></ul><hr class="tocbar">
<p class="inwebparagraph"><a id="SP1"></a><b>&#167;1. Definitions. </b></p>
<p class="inwebparagraph"><a id="SP2"></a><b>&#167;2. </b>Scenes are gated intervals of time, but there are more than two gates: for
while there is only one past, there are many possible futures. These gates
are called "ends" in the code below, and are numbered end 0 (the beginning),
end 1 (the usual end), and then any named ends ("ends badly" or "ends
triumphantly", for instance, might be ends 2 and 3). Each end has a condition
which can cause it, or can be "anchored" to any number of ends of other
scenes &mdash; to express which, the <code class="display"><span class="extract">scene_connector</span></code> structure is used.
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="constant">MAX_SCENE_ENDS</span><span class="plain"> 32 </span> <span class="comment">this must exceed 31</span>
</pre>
<pre class="display">
<span class="reserved">typedef</span><span class="plain"> </span><span class="reserved">struct</span><span class="plain"> </span><span class="reserved">scene_connector</span><span class="plain"> {</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">scene</span><span class="plain"> *</span><span class="identifier">connect_to</span><span class="plain">; </span> <span class="comment">scene connected to</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">end</span><span class="plain">; </span> <span class="comment">end number: see above</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">scene_connector</span><span class="plain"> *</span><span class="identifier">next</span><span class="plain">; </span> <span class="comment">next in list of connectors for a scene end</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">where_said</span><span class="plain">; </span> <span class="comment">where this linkage was specified in source</span>
<span class="plain">} </span><span class="reserved">scene_connector</span><span class="plain">;</span>
<span class="reserved">typedef</span><span class="plain"> </span><span class="reserved">struct</span><span class="plain"> </span><span class="reserved">scene</span><span class="plain"> {</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">as_instance</span><span class="plain">; </span> <span class="comment">the constant for the name of the scene</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">once_only</span><span class="plain">; </span> <span class="comment">cannot repeat during play</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">start_of_play</span><span class="plain">; </span> <span class="comment">if begins when play begins</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">marker</span><span class="plain">; </span> <span class="comment">used to detect potentially infinite recursion when scene changes occur</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">no_ends</span><span class="plain">; </span> <span class="comment">how many ends the scene has</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">wording</span><span class="plain"> </span><span class="identifier">end_names</span><span class="plain">[</span><span class="constant">MAX_SCENE_ENDS</span><span class="plain">]; </span> <span class="comment">for ends 2, 3, ...: e.g. "badly"</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">rulebook</span><span class="plain"> *</span><span class="identifier">end_rulebook</span><span class="plain">[</span><span class="constant">MAX_SCENE_ENDS</span><span class="plain">]; </span> <span class="comment">rules to apply then</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">anchor_condition</span><span class="plain">[</span><span class="constant">MAX_SCENE_ENDS</span><span class="plain">];</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">scene_connector</span><span class="plain"> *</span><span class="identifier">anchor_scene</span><span class="plain">[</span><span class="constant">MAX_SCENE_ENDS</span><span class="plain">]; </span> <span class="comment">linked list</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">indexed</span><span class="plain">; </span> <span class="comment">temporary storage during Scenes index creation</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">scene_declared_at</span><span class="plain">; </span> <span class="comment">where defined</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">anchor_condition_set</span><span class="plain">[</span><span class="constant">MAX_SCENE_ENDS</span><span class="plain">]; </span> <span class="comment">where set</span>
<span class="identifier">MEMORY_MANAGEMENT</span>
<span class="plain">} </span><span class="reserved">scene</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The structure scene_connector is accessed in 2/ri, 3/em, 3/tm2, 3/ts, 4/act, 4/anl, 4/ap, 4/nap, 5/tfg, 5/gl and here.</p>
<p class="endnote">The structure scene is accessed in 3/tm2 and here.</p>
<p class="inwebparagraph"><a id="SP3"></a><b>&#167;3. </b>The following either/or property needs some compiler support:
</p>
<pre class="display">
<span class="identifier">property</span><span class="plain"> *</span><span class="identifier">P_recurring</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP4"></a><b>&#167;4. </b>And so does the one special scene:
</p>
<pre class="display">
<span class="reserved">scene</span><span class="plain"> *</span><span class="identifier">SC_entire_game</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP5"></a><b>&#167;5. </b>Scenes are similarly numbered and stored in their own kind:
actually, they are for practical purposes a built-in enumeration kind.
</p>
<pre class="display">
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">K_scene</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP6"></a><b>&#167;6. </b>At run-time, we need to store information about the current state of each
scene: whether it is currently playing or not, when the last change occurred,
and so on. This data is stored in I6 arrays as follows:
</p>
<p class="inwebparagraph">First, each scene has a unique ID number, used as an index <code class="display"><span class="extract">X</span></code> to these arrays.
This ID number is what is stored as an I6 value for the kind of value <code class="display"><span class="extract">scene</span></code>,
and it agrees with the allocation ID for the I7 scene structure.
</p>
<p class="inwebparagraph"><code class="display"><span class="extract">scene_status--&gt;X</span></code> is 0 if the scene is not playing, but may do so in future;
1 if the scene is playing; or 2 if the scene is not playing and will never
play again.
</p>
<p class="inwebparagraph"><code class="display"><span class="extract">scene_started--&gt;X</span></code> is the value of <code class="display"><span class="extract">the_time</span></code> when the scene last started,
or 0 if it has never started.
</p>
<p class="inwebparagraph"><code class="display"><span class="extract">scene_ended--&gt;X</span></code> is the value of <code class="display"><span class="extract">the_time</span></code> when the scene last ended,
or 0 if it has never ended. (The "starting" end does not count as ending
for this purpose.)
</p>
<p class="inwebparagraph"><code class="display"><span class="extract">scene_endings--&gt;X</span></code> is a bitmap recording which ends have been used,
including bit 1 which records whether the scene has started.
</p>
<p class="inwebparagraph"><code class="display"><span class="extract">scene_latest_ending--&gt;X</span></code> holds the end number of the most recent ending
(or 0 if the scene has never ended).
</p>
<p class="inwebparagraph"><a id="SP7"></a><b>&#167;7. Plugin calls. </b></p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">PL::Scenes::start</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="identifier">PLUGIN_REGISTER</span><span class="plain">(</span><span class="identifier">PLUGIN_NEW_PROPERTY_NOTIFY</span><span class="plain">, </span><span class="functiontext">PL::Scenes::scenes_new_property_notify</span><span class="plain">);</span>
<span class="identifier">PLUGIN_REGISTER</span><span class="plain">(</span><span class="identifier">PLUGIN_NEW_INSTANCE_NOTIFY</span><span class="plain">, </span><span class="functiontext">PL::Scenes::scenes_new_named_instance_notify</span><span class="plain">);</span>
<span class="identifier">PLUGIN_REGISTER</span><span class="plain">(</span><span class="identifier">PLUGIN_NEW_BASE_KIND_NOTIFY</span><span class="plain">, </span><span class="functiontext">PL::Scenes::scenes_new_base_kind_notify</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function PL::Scenes::start appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP8"></a><b>&#167;8. </b>To detect "scene" and "recurring":
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">PL::Scenes::scenes_new_base_kind_notify</span><span class="plain">(</span><span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">new_base</span><span class="plain">, </span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">name</span><span class="plain">, </span><span class="identifier">wording</span><span class="plain"> </span><span class="identifier">W</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Str::eq_wide_string</span><span class="plain">(</span><span class="identifier">name</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"SCENE_TY"</span><span class="plain">)) {</span>
<span class="identifier">K_scene</span><span class="plain"> = </span><span class="identifier">new_base</span><span class="plain">; </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function PL::Scenes::scenes_new_base_kind_notify is used in <a href="#SP7">&#167;7</a>.</p>
<p class="inwebparagraph"><a id="SP9"></a><b>&#167;9. </b>This is a property name to do with scenes which Inform provides special
support for; it recognises the English name when it is defined by the
Standard Rules. (So there is no need to translate this to other languages.)
</p>
<pre class="display">
<span class="plain">&lt;</span><span class="identifier">notable</span><span class="plain">-</span><span class="reserved">scene</span><span class="plain">-</span><span class="identifier">properties</span><span class="plain">&gt; ::=</span>
<span class="identifier">recurring</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP10"></a><b>&#167;10. </b></p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">PL::Scenes::scenes_new_property_notify</span><span class="plain">(</span><span class="identifier">property</span><span class="plain"> *</span><span class="identifier">prn</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (&lt;</span><span class="identifier">notable</span><span class="plain">-</span><span class="reserved">scene</span><span class="plain">-</span><span class="identifier">properties</span><span class="plain">&gt;(</span><span class="identifier">prn</span><span class="plain">-</span><span class="element">&gt;name</span><span class="plain">)) {</span>
<span class="reserved">switch</span><span class="plain"> (&lt;&lt;</span><span class="identifier">r</span><span class="plain">&gt;&gt;) {</span>
<span class="reserved">case</span><span class="plain"> 0: </span><span class="identifier">P_recurring</span><span class="plain"> = </span><span class="identifier">prn</span><span class="plain">; </span><span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function PL::Scenes::scenes_new_property_notify is used in <a href="#SP7">&#167;7</a>.</p>
<p class="inwebparagraph"><a id="SP11"></a><b>&#167;11. </b>Scene structures are automatically created whenever a new instance of the
kind "scene" is created, and this is where that happens.
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">PL::Scenes::scenes_new_named_instance_notify</span><span class="plain">(</span><span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">I</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">K_scene</span><span class="plain">) &amp;&amp; (</span><span class="identifier">Kinds::Compare::eq</span><span class="plain">(</span><span class="identifier">Instances::to_kind</span><span class="plain">(</span><span class="identifier">I</span><span class="plain">), </span><span class="identifier">K_scene</span><span class="plain">))) {</span>
<span class="functiontext">PL::Scenes::new_scene</span><span class="plain">(</span><span class="identifier">I</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function PL::Scenes::scenes_new_named_instance_notify is used in <a href="#SP7">&#167;7</a>.</p>
<p class="inwebparagraph"><a id="SP12"></a><b>&#167;12. Scene structures. </b>As we've seen, the following is called whenever a new instance of "scene"
is created:
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">PL::Scenes::new_scene</span><span class="plain">(</span><span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">I</span><span class="plain">) {</span>
<span class="reserved">scene</span><span class="plain"> *</span><span class="identifier">sc</span><span class="plain"> = </span><span class="identifier">CREATE</span><span class="plain">(</span><span class="reserved">scene</span><span class="plain">);</span>
&lt;<span class="cwebmacro">Connect the scene structure to the instance</span> <span class="cwebmacronumber">12.3</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Initialise the scene structure</span> <span class="cwebmacronumber">12.1</span>&gt;<span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function PL::Scenes::new_scene is used in <a href="#SP11">&#167;11</a>.</p>
<p class="inwebparagraph"><a id="SP12_1"></a><b>&#167;12.1. </b>A scene begins with two ends, 0 (beginning) and 1 (standard end).
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Initialise the scene structure</span> <span class="cwebmacronumber">12.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">sc</span><span class="plain">-</span><span class="element">&gt;once_only</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="identifier">sc</span><span class="plain">-</span><span class="element">&gt;indexed</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="identifier">sc</span><span class="plain">-</span><span class="element">&gt;no_ends</span><span class="plain"> = 2;</span>
<span class="identifier">sc</span><span class="plain">-</span><span class="element">&gt;start_of_play</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="identifier">sc</span><span class="plain">-</span><span class="element">&gt;scene_declared_at</span><span class="plain"> = </span><span class="identifier">current_sentence</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">end</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">end</span><span class="plain">=0; </span><span class="identifier">end</span><span class="plain">&lt;</span><span class="identifier">sc</span><span class="plain">-</span><span class="element">&gt;no_ends</span><span class="plain">; </span><span class="identifier">end</span><span class="plain">++) {</span>
<span class="identifier">sc</span><span class="plain">-</span><span class="element">&gt;anchor_condition</span><span class="plain">[</span><span class="identifier">end</span><span class="plain">] = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">sc</span><span class="plain">-</span><span class="element">&gt;anchor_scene</span><span class="plain">[</span><span class="identifier">end</span><span class="plain">] = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="functiontext">PL::Scenes::new_scene_rulebook</span><span class="plain">(</span><span class="identifier">sc</span><span class="plain">, </span><span class="identifier">end</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP12">&#167;12</a>.</p>
<p class="inwebparagraph"><a id="SP12_2"></a><b>&#167;12.2. </b>This is a scene name which Inform provides special support for; it recognises
the English name when it is defined by the Standard Rules. (So there is no need
to translate this to other languages.)
</p>
<pre class="display">
<span class="plain">&lt;</span><span class="identifier">notable</span><span class="plain">-</span><span class="identifier">scenes</span><span class="plain">&gt; ::=</span>
<span class="identifier">entire</span><span class="plain"> </span><span class="identifier">game</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP12_3"></a><b>&#167;12.3. </b><code class="display">
&lt;<span class="cwebmacrodefn">Connect the scene structure to the instance</span> <span class="cwebmacronumber">12.3</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">sc</span><span class="plain">-</span><span class="element">&gt;as_instance</span><span class="plain"> = </span><span class="identifier">I</span><span class="plain">;</span>
<span class="identifier">Instances::set_connection</span><span class="plain">(</span><span class="identifier">I</span><span class="plain">, </span><span class="identifier">STORE_POINTER_scene</span><span class="plain">(</span><span class="identifier">sc</span><span class="plain">));</span>
<span class="identifier">wording</span><span class="plain"> </span><span class="identifier">W</span><span class="plain"> = </span><span class="identifier">Instances::get_name</span><span class="plain">(</span><span class="identifier">I</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (&lt;</span><span class="identifier">notable</span><span class="plain">-</span><span class="identifier">scenes</span><span class="plain">&gt;(</span><span class="identifier">W</span><span class="plain">)) </span><span class="identifier">SC_entire_game</span><span class="plain"> = </span><span class="identifier">sc</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP12">&#167;12</a>.</p>
<p class="inwebparagraph"><a id="SP13"></a><b>&#167;13. </b>So we sometimes want to be able to get from an instance to its scene structure.
</p>
<pre class="display">
<span class="reserved">scene</span><span class="plain"> *</span><span class="functiontext">PL::Scenes::from_named_constant</span><span class="plain">(</span><span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">I</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">K_scene</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">K</span><span class="plain"> = </span><span class="identifier">Instances::to_kind</span><span class="plain">(</span><span class="identifier">I</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Kinds::Compare::eq</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">, </span><span class="identifier">K_scene</span><span class="plain">))</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">RETRIEVE_POINTER_scene</span><span class="plain">(</span><span class="identifier">Instances::get_connection</span><span class="plain">(</span><span class="identifier">I</span><span class="plain">));</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">wording</span><span class="plain"> </span><span class="functiontext">PL::Scenes::get_name</span><span class="plain">(</span><span class="reserved">scene</span><span class="plain"> *</span><span class="identifier">sc</span><span class="plain">) {</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">Instances::get_name</span><span class="plain">(</span><span class="identifier">sc</span><span class="plain">-</span><span class="element">&gt;as_instance</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function PL::Scenes::from_named_constant is used in <a href="#SP22_1">&#167;22.1</a>, <a href="#SP31">&#167;31</a>.</p>
<p class="endnote">The function PL::Scenes::get_name is used in 3/tm2 (<a href="3-tm2.html#SP1_5_1_1">&#167;1.5.1.1</a>).</p>
<p class="inwebparagraph"><a id="SP14"></a><b>&#167;14. Creating and parsing ends. </b></p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">PL::Scenes::parse_scene_end_name</span><span class="plain">(</span><span class="reserved">scene</span><span class="plain"> *</span><span class="identifier">sc</span><span class="plain">, </span><span class="identifier">wording</span><span class="plain"> </span><span class="identifier">EW</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">create</span><span class="plain">) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain">=2; </span><span class="identifier">i</span><span class="plain">&lt;</span><span class="identifier">sc</span><span class="plain">-</span><span class="element">&gt;no_ends</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Wordings::match</span><span class="plain">(</span><span class="identifier">EW</span><span class="plain">, </span><span class="identifier">sc</span><span class="plain">-</span><span class="element">&gt;end_names</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]))</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">create</span><span class="plain">) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">end</span><span class="plain"> = </span><span class="identifier">sc</span><span class="plain">-</span><span class="element">&gt;no_ends</span><span class="plain">++;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">max</span><span class="plain"> = 31;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">VirtualMachines::is_16_bit</span><span class="plain">()) </span><span class="identifier">max</span><span class="plain"> = 15;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">end</span><span class="plain"> &gt;= </span><span class="identifier">max</span><span class="plain">) </span>&lt;<span class="cwebmacro">Issue a too-many-ends problem message</span> <span class="cwebmacronumber">14.1</span>&gt;
<span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">sc</span><span class="plain">-</span><span class="element">&gt;end_names</span><span class="plain">[</span><span class="identifier">end</span><span class="plain">] = </span><span class="identifier">EW</span><span class="plain">;</span>
<span class="functiontext">PL::Scenes::new_scene_rulebook</span><span class="plain">(</span><span class="identifier">sc</span><span class="plain">, </span><span class="identifier">end</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">end</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> -1;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function PL::Scenes::parse_scene_end_name is used in <a href="#SP23">&#167;23</a>.</p>
<p class="inwebparagraph"><a id="SP14_1"></a><b>&#167;14.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Issue a too-many-ends problem message</span> <span class="cwebmacronumber">14.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">Problems::Issue::sentence_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_ScenesWithTooManyEnds</span><span class="plain">),</span>
<span class="string">"this scene now has too many different ways to end"</span><span class="plain">,</span>
<span class="string">"and will need to be simplified. (We can have up to 15 ends to a scene "</span>
<span class="string">"if the project format is for the Z-machine, and 31 for Glulx: see the "</span>
<span class="string">"project's Settings panel. Note that the ordinary 'begins' and 'ends' "</span>
<span class="string">"count as two of those, so you can only name up to 13 or 29 more specific "</span>
<span class="string">"ways for the scene to end.)"</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP14">&#167;14</a>.</p>
<p class="inwebparagraph"><a id="SP15"></a><b>&#167;15. Scene end rulebooks. </b></p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">PL::Scenes::new_scene_rulebook</span><span class="plain">(</span><span class="reserved">scene</span><span class="plain"> *</span><span class="identifier">sc</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">end</span><span class="plain">) {</span>
<span class="identifier">wording</span><span class="plain"> </span><span class="identifier">RW</span><span class="plain"> = </span><span class="identifier">EMPTY_WORDING</span><span class="plain">, </span><span class="identifier">AW</span><span class="plain"> = </span><span class="identifier">EMPTY_WORDING</span><span class="plain">;</span>
&lt;<span class="cwebmacro">Compose a name and alternate name for the new scene end rulebook</span> <span class="cwebmacronumber">15.1</span>&gt;<span class="plain">;</span>
<span class="identifier">rulebook</span><span class="plain"> *</span><span class="identifier">rb</span><span class="plain"> = </span><span class="identifier">Rulebooks::new_automatic</span><span class="plain">(</span><span class="identifier">RW</span><span class="plain">, </span><span class="identifier">K_action_name</span><span class="plain">,</span>
<span class="identifier">NO_OUTCOME</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">, </span><span class="identifier">Hierarchy::local_package</span><span class="plain">(</span><span class="identifier">RULEBOOKS_HAP</span><span class="plain">));</span>
<span class="identifier">Rulebooks::set_alt_name</span><span class="plain">(</span><span class="identifier">rb</span><span class="plain">, </span><span class="identifier">AW</span><span class="plain">);</span>
<span class="identifier">sc</span><span class="plain">-</span><span class="element">&gt;end_rulebook</span><span class="plain">[</span><span class="identifier">end</span><span class="plain">] = </span><span class="identifier">rb</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">end</span><span class="plain"> &gt;= 2) </span>&lt;<span class="cwebmacro">Define phrases detecting whether or not the scene has ended this way</span> <span class="cwebmacronumber">15.2</span>&gt;<span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function PL::Scenes::new_scene_rulebook is used in <a href="#SP12_1">&#167;12.1</a>, <a href="#SP14">&#167;14</a>.</p>
<p class="inwebparagraph"><a id="SP15_1"></a><b>&#167;15.1. </b>For example, if a scene is called "Banquet Entertainment" and it ends
"merrily", then the rulebook has two names: "when Banquet Entertainment
ends merrily" and "when the Banquet Entertainment ends merrily".
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Compose a name and alternate name for the new scene end rulebook</span> <span class="cwebmacronumber">15.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">wording</span><span class="plain"> </span><span class="identifier">NW</span><span class="plain"> = </span><span class="identifier">Instances::get_name</span><span class="plain">(</span><span class="identifier">sc</span><span class="plain">-</span><span class="element">&gt;as_instance</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">);</span>
<span class="identifier">feed_t</span><span class="plain"> </span><span class="identifier">id</span><span class="plain"> = </span><span class="identifier">Feeds::begin</span><span class="plain">();</span>
<span class="identifier">Feeds::feed_text_expanding_strings</span><span class="plain">(</span><span class="identifier">L</span><span class="string">"when"</span><span class="plain">);</span>
<span class="identifier">Feeds::feed_wording</span><span class="plain">(</span><span class="identifier">NW</span><span class="plain">);</span>
<span class="identifier">Feeds::feed_text_expanding_strings</span><span class="plain">((</span><span class="identifier">end</span><span class="plain">==0)?</span><span class="identifier">L</span><span class="string">"begins"</span><span class="plain">:</span><span class="identifier">L</span><span class="string">"ends"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">end</span><span class="plain"> &gt;= 2) </span><span class="identifier">Feeds::feed_wording</span><span class="plain">(</span><span class="identifier">sc</span><span class="plain">-</span><span class="element">&gt;end_names</span><span class="plain">[</span><span class="identifier">end</span><span class="plain">]);</span>
<span class="identifier">RW</span><span class="plain"> = </span><span class="identifier">Feeds::end</span><span class="plain">(</span><span class="identifier">id</span><span class="plain">);</span>
<span class="identifier">id</span><span class="plain"> = </span><span class="identifier">Feeds::begin</span><span class="plain">();</span>
<span class="identifier">Feeds::feed_text_expanding_strings</span><span class="plain">(</span><span class="identifier">L</span><span class="string">"when the"</span><span class="plain">);</span>
<span class="identifier">NW</span><span class="plain"> = </span><span class="identifier">Instances::get_name</span><span class="plain">(</span><span class="identifier">sc</span><span class="plain">-</span><span class="element">&gt;as_instance</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">);</span>
<span class="identifier">Feeds::feed_wording</span><span class="plain">(</span><span class="identifier">NW</span><span class="plain">);</span>
<span class="identifier">Feeds::feed_text_expanding_strings</span><span class="plain">((</span><span class="identifier">end</span><span class="plain">==0)?</span><span class="identifier">L</span><span class="string">"begins"</span><span class="plain">:</span><span class="identifier">L</span><span class="string">"ends"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">end</span><span class="plain"> &gt;= 2) </span><span class="identifier">Feeds::feed_wording</span><span class="plain">(</span><span class="identifier">sc</span><span class="plain">-</span><span class="element">&gt;end_names</span><span class="plain">[</span><span class="identifier">end</span><span class="plain">]);</span>
<span class="identifier">AW</span><span class="plain"> = </span><span class="identifier">Feeds::end</span><span class="plain">(</span><span class="identifier">id</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP15">&#167;15</a>.</p>
<p class="inwebparagraph"><a id="SP15_2"></a><b>&#167;15.2. </b><code class="display">
&lt;<span class="cwebmacrodefn">Define phrases detecting whether or not the scene has ended this way</span> <span class="cwebmacronumber">15.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">wording</span><span class="plain"> </span><span class="identifier">NW</span><span class="plain"> = </span><span class="identifier">Instances::get_name</span><span class="plain">(</span><span class="identifier">sc</span><span class="plain">-</span><span class="element">&gt;as_instance</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">);</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">i6_code</span><span class="plain">);</span>
<span class="identifier">feed_t</span><span class="plain"> </span><span class="identifier">id</span><span class="plain"> = </span><span class="identifier">Feeds::begin</span><span class="plain">();</span>
<span class="identifier">Feeds::feed_text_expanding_strings</span><span class="plain">(</span><span class="identifier">L</span><span class="string">"To decide if (S - "</span><span class="plain">);</span>
<span class="identifier">Feeds::feed_wording</span><span class="plain">(</span><span class="identifier">NW</span><span class="plain">);</span>
<span class="identifier">Feeds::feed_text_expanding_strings</span><span class="plain">(</span><span class="identifier">L</span><span class="string">") ended "</span><span class="plain">);</span>
<span class="identifier">Feeds::feed_wording</span><span class="plain">(</span><span class="identifier">sc</span><span class="plain">-</span><span class="element">&gt;end_names</span><span class="plain">[</span><span class="identifier">end</span><span class="plain">]);</span>
<span class="identifier">Sentences::make_node</span><span class="plain">(</span><span class="identifier">Feeds::end</span><span class="plain">(</span><span class="identifier">id</span><span class="plain">), </span><span class="character">':'</span><span class="plain">);</span>
<span class="identifier">id</span><span class="plain"> = </span><span class="identifier">Feeds::begin</span><span class="plain">();</span>
<span class="identifier">Str::clear</span><span class="plain">(</span><span class="identifier">i6_code</span><span class="plain">);</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">i6_code</span><span class="plain">, </span><span class="string">" (- (scene_latest_ending--&gt;%d == %d) -) "</span><span class="plain">,</span>
<span class="identifier">sc</span><span class="plain">-&gt;</span><span class="identifier">allocation_id</span><span class="plain">, </span><span class="identifier">end</span><span class="plain">);</span>
<span class="identifier">Feeds::feed_stream_expanding_strings</span><span class="plain">(</span><span class="identifier">i6_code</span><span class="plain">);</span>
<span class="identifier">Sentences::make_node</span><span class="plain">(</span><span class="identifier">Feeds::end</span><span class="plain">(</span><span class="identifier">id</span><span class="plain">), </span><span class="character">'.'</span><span class="plain">);</span>
<span class="identifier">id</span><span class="plain"> = </span><span class="identifier">Feeds::begin</span><span class="plain">();</span>
<span class="identifier">Feeds::feed_text_expanding_strings</span><span class="plain">(</span><span class="identifier">L</span><span class="string">"To decide if (S - "</span><span class="plain">);</span>
<span class="identifier">Feeds::feed_wording</span><span class="plain">(</span><span class="identifier">NW</span><span class="plain">);</span>
<span class="identifier">Feeds::feed_text_expanding_strings</span><span class="plain">(</span><span class="identifier">L</span><span class="string">") did not end "</span><span class="plain">);</span>
<span class="identifier">Feeds::feed_wording</span><span class="plain">(</span><span class="identifier">sc</span><span class="plain">-</span><span class="element">&gt;end_names</span><span class="plain">[</span><span class="identifier">end</span><span class="plain">]);</span>
<span class="identifier">Sentences::make_node</span><span class="plain">(</span><span class="identifier">Feeds::end</span><span class="plain">(</span><span class="identifier">id</span><span class="plain">), </span><span class="character">':'</span><span class="plain">);</span>
<span class="identifier">id</span><span class="plain"> = </span><span class="identifier">Feeds::begin</span><span class="plain">();</span>
<span class="identifier">Str::clear</span><span class="plain">(</span><span class="identifier">i6_code</span><span class="plain">);</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">i6_code</span><span class="plain">, </span><span class="string">" (- (scene_latest_ending--&gt;%d ~= 0 or %d) -) "</span><span class="plain">,</span>
<span class="identifier">sc</span><span class="plain">-&gt;</span><span class="identifier">allocation_id</span><span class="plain">, </span><span class="identifier">end</span><span class="plain">);</span>
<span class="identifier">Feeds::feed_stream_expanding_strings</span><span class="plain">(</span><span class="identifier">i6_code</span><span class="plain">);</span>
<span class="identifier">Sentences::make_node</span><span class="plain">(</span><span class="identifier">Feeds::end</span><span class="plain">(</span><span class="identifier">id</span><span class="plain">), </span><span class="character">'.'</span><span class="plain">);</span>
<span class="identifier">Sentences::RuleSubtrees::register_recently_lexed_phrases</span><span class="plain">();</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">i6_code</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP15">&#167;15</a>.</p>
<p class="inwebparagraph"><a id="SP16"></a><b>&#167;16. Anchors. </b>These are joins between the endings of different scenes, and there are two
assertion sentences to create them. This handles the special meaning "X
begins when...".
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">PL::Scenes::begins_when_SMF</span><span class="plain">(</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">task</span><span class="plain">, </span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">V</span><span class="plain">, </span><span class="identifier">wording</span><span class="plain"> *</span><span class="identifier">NPs</span><span class="plain">) {</span>
<span class="identifier">wording</span><span class="plain"> </span><span class="identifier">SW</span><span class="plain"> = (</span><span class="identifier">NPs</span><span class="plain">)?(</span><span class="identifier">NPs</span><span class="plain">[0]):</span><span class="identifier">EMPTY_WORDING</span><span class="plain">;</span>
<span class="identifier">wording</span><span class="plain"> </span><span class="identifier">OW</span><span class="plain"> = (</span><span class="identifier">NPs</span><span class="plain">)?(</span><span class="identifier">NPs</span><span class="plain">[1]):</span><span class="identifier">EMPTY_WORDING</span><span class="plain">;</span>
<span class="reserved">switch</span><span class="plain"> (</span><span class="identifier">task</span><span class="plain">) { </span> <span class="comment">"The Ballroom Scene begins when..."</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">ACCEPT_SMFT</span><span class="plain">:</span>
<span class="identifier">ParseTree::annotate_int</span><span class="plain">(</span><span class="identifier">V</span><span class="plain">, </span><span class="identifier">verb_id_ANNOT</span><span class="plain">, </span><span class="identifier">SPECIAL_MEANING_VB</span><span class="plain">);</span>
<span class="plain">&lt;</span><span class="identifier">nounphrase</span><span class="plain">&gt;(</span><span class="identifier">OW</span><span class="plain">);</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">O</span><span class="plain"> = &lt;&lt;</span><span class="identifier">rp</span><span class="plain">&gt;&gt;;</span>
<span class="plain">&lt;</span><span class="identifier">nounphrase</span><span class="plain">&gt;(</span><span class="identifier">SW</span><span class="plain">);</span>
<span class="identifier">V</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain"> = &lt;&lt;</span><span class="identifier">rp</span><span class="plain">&gt;&gt;;</span>
<span class="identifier">V</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain"> = </span><span class="identifier">O</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">TRAVERSE1_SMFT</span><span class="plain">:</span>
<span class="functiontext">PL::Scenes::new_scene_anchor</span><span class="plain">(</span><span class="identifier">V</span><span class="plain">, 1, 0);</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">TRAVERSE2_SMFT</span><span class="plain">:</span>
<span class="functiontext">PL::Scenes::new_scene_anchor</span><span class="plain">(</span><span class="identifier">V</span><span class="plain">, 2, 0);</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function PL::Scenes::begins_when_SMF appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP17"></a><b>&#167;17. </b>This handles the special meaning "X ends when...", which sometimes takes
two noun phrases and sometimes three.
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">PL::Scenes::ends_when_SMF</span><span class="plain">(</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">task</span><span class="plain">, </span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">V</span><span class="plain">, </span><span class="identifier">wording</span><span class="plain"> *</span><span class="identifier">NPs</span><span class="plain">) {</span>
<span class="identifier">wording</span><span class="plain"> </span><span class="identifier">SW</span><span class="plain"> = (</span><span class="identifier">NPs</span><span class="plain">)?(</span><span class="identifier">NPs</span><span class="plain">[0]):</span><span class="identifier">EMPTY_WORDING</span><span class="plain">;</span>
<span class="identifier">wording</span><span class="plain"> </span><span class="identifier">OW</span><span class="plain"> = (</span><span class="identifier">NPs</span><span class="plain">)?(</span><span class="identifier">NPs</span><span class="plain">[1]):</span><span class="identifier">EMPTY_WORDING</span><span class="plain">;</span>
<span class="identifier">wording</span><span class="plain"> </span><span class="identifier">O2W</span><span class="plain"> = (</span><span class="identifier">NPs</span><span class="plain">)?(</span><span class="identifier">NPs</span><span class="plain">[2]):</span><span class="identifier">EMPTY_WORDING</span><span class="plain">;</span>
<span class="reserved">switch</span><span class="plain"> (</span><span class="identifier">task</span><span class="plain">) { </span> <span class="comment">"The Ballroom Scene ends when..."</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">ACCEPT_SMFT</span><span class="plain">:</span>
<span class="identifier">ParseTree::annotate_int</span><span class="plain">(</span><span class="identifier">V</span><span class="plain">, </span><span class="identifier">verb_id_ANNOT</span><span class="plain">, </span><span class="identifier">SPECIAL_MEANING_VB</span><span class="plain">);</span>
<span class="plain">&lt;</span><span class="identifier">nounphrase</span><span class="plain">&gt;(</span><span class="identifier">OW</span><span class="plain">);</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">O</span><span class="plain"> = &lt;&lt;</span><span class="identifier">rp</span><span class="plain">&gt;&gt;;</span>
<span class="plain">&lt;</span><span class="identifier">nounphrase</span><span class="plain">&gt;(</span><span class="identifier">SW</span><span class="plain">);</span>
<span class="identifier">V</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain"> = &lt;&lt;</span><span class="identifier">rp</span><span class="plain">&gt;&gt;;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Wordings::nonempty</span><span class="plain">(</span><span class="identifier">O2W</span><span class="plain">)) {</span>
<span class="plain">&lt;</span><span class="identifier">nounphrase</span><span class="plain">&gt;(</span><span class="identifier">O2W</span><span class="plain">);</span>
<span class="identifier">V</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain"> = &lt;&lt;</span><span class="identifier">rp</span><span class="plain">&gt;&gt;;</span>
<span class="identifier">V</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain"> = </span><span class="identifier">O</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">V</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain"> = </span><span class="identifier">O</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">TRAVERSE1_SMFT</span><span class="plain">:</span>
<span class="functiontext">PL::Scenes::new_scene_anchor</span><span class="plain">(</span><span class="identifier">V</span><span class="plain">, 1, 1);</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">TRAVERSE2_SMFT</span><span class="plain">:</span>
<span class="functiontext">PL::Scenes::new_scene_anchor</span><span class="plain">(</span><span class="identifier">V</span><span class="plain">, 2, 1);</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function PL::Scenes::ends_when_SMF appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP18"></a><b>&#167;18. </b></p>
<pre class="display">
<span class="reserved">scene</span><span class="plain"> *</span><span class="identifier">scene_end_of_which_parsed</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP19"></a><b>&#167;19. </b>Sentences giving scene boundaries have a simple form:
</p>
<blockquote>
<p>The Ballroom Dance begins when the Hallway Greeting ends.</p>
</blockquote>
<blockquote>
<p>The Ballroom Dance ends dramatically when we have dropped the glass slipper.</p>
</blockquote>
<p class="inwebparagraph">The sentence has a subject noun phrase (here "Ballroom Dance") and an
object NP: "the Hallway Greeting ends" or "we have dropped the glass
slipper" are the object NPs here. We will call the optional part,
"dramatically" in this example, the adverb, though it doesn't actually
have to be worded as one.
</p>
<p class="inwebparagraph">The subject is simple: it has to be a scene name.
</p>
<pre class="display">
<span class="plain">&lt;</span><span class="reserved">scene</span><span class="plain">-</span><span class="identifier">ends</span><span class="plain">-</span><span class="identifier">sentence</span><span class="plain">-</span><span class="identifier">subject</span><span class="plain">&gt; ::=</span>
<span class="plain">&lt;</span><span class="reserved">scene</span><span class="plain">-</span><span class="identifier">name</span><span class="plain">&gt; | ==&gt; </span><span class="identifier">TRUE</span><span class="plain">; *</span><span class="identifier">XP</span><span class="plain"> = </span><span class="identifier">RP</span><span class="plain">[1]</span>
<span class="plain">... ==&gt; </span>&lt;<span class="cwebmacro">Issue PM_ScenesOnly problem</span> <span class="cwebmacronumber">19.1</span>&gt;
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP19_1"></a><b>&#167;19.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Issue PM_ScenesOnly problem</span> <span class="cwebmacronumber">19.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="plain">*</span><span class="identifier">X</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="identifier">Problems::Issue::sentence_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_ScenesOnly</span><span class="plain">),</span>
<span class="string">"'begins when' and 'ends when' can only be applied to scenes"</span><span class="plain">,</span>
<span class="string">"which have already been defined with a sentence like 'The final "</span>
<span class="string">"confrontation is a scene.'"</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP19">&#167;19</a>.</p>
<p class="inwebparagraph"><a id="SP20"></a><b>&#167;20. </b>The adverb, if present, always matches, since the scene end is created
if it doesn't already exist:
</p>
<pre class="display">
<span class="plain">&lt;</span><span class="reserved">scene</span><span class="plain">-</span><span class="identifier">ends</span><span class="plain">-</span><span class="identifier">sentence</span><span class="plain">-</span><span class="identifier">adverb</span><span class="plain">&gt; ::=</span>
<span class="plain">&lt;</span><span class="reserved">scene</span><span class="plain">-</span><span class="identifier">end</span><span class="plain">-</span><span class="identifier">name</span><span class="plain">-</span><span class="identifier">creating</span><span class="plain">&gt; ==&gt; </span><span class="identifier">R</span><span class="plain">[1]</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP21"></a><b>&#167;21. </b>The following is elementary enough, but we want to be careful because
there are possible ambiguities: the condition might contain the word "ends"
in a different context, for instance, and could still be valid in that case.
</p>
<pre class="display">
<span class="plain">&lt;</span><span class="reserved">scene</span><span class="plain">-</span><span class="identifier">ends</span><span class="plain">-</span><span class="identifier">sentence</span><span class="plain">-</span><span class="identifier">object</span><span class="plain">&gt; ::=</span>
<span class="plain">&lt;</span><span class="identifier">text</span><span class="plain">-</span><span class="identifier">including</span><span class="plain">-</span><span class="identifier">a</span><span class="plain">-</span><span class="identifier">calling</span><span class="plain">&gt; | ==&gt; </span>&lt;<span class="cwebmacro">Issue PM_ScenesDisallowCalled problem</span> <span class="cwebmacronumber">21.1</span>&gt;
<span class="identifier">play</span><span class="plain"> </span><span class="identifier">begins</span><span class="plain"> | ==&gt; -1</span>
<span class="identifier">play</span><span class="plain"> </span><span class="identifier">ends</span><span class="plain"> | ==&gt; </span>&lt;<span class="cwebmacro">Issue PM_ScenesNotPlay problem</span> <span class="cwebmacronumber">21.2</span>&gt;
<span class="plain">&lt;</span><span class="reserved">scene</span><span class="plain">-</span><span class="identifier">name</span><span class="plain">&gt; </span><span class="identifier">begins</span><span class="plain"> | ==&gt; 0; &lt;&lt;</span><span class="reserved">scene</span><span class="plain">:</span><span class="identifier">named</span><span class="plain">&gt;&gt; = </span><span class="identifier">RP</span><span class="plain">[1]</span>
<span class="plain">&lt;</span><span class="reserved">scene</span><span class="plain">-</span><span class="identifier">name</span><span class="plain">&gt; </span><span class="identifier">ends</span><span class="plain"> | ==&gt; 1; &lt;&lt;</span><span class="reserved">scene</span><span class="plain">:</span><span class="identifier">named</span><span class="plain">&gt;&gt; = </span><span class="identifier">RP</span><span class="plain">[1]</span>
<span class="plain">&lt;</span><span class="reserved">scene</span><span class="plain">-</span><span class="identifier">name</span><span class="plain">&gt; </span><span class="identifier">ends</span><span class="plain"> &lt;</span><span class="reserved">scene</span><span class="plain">-</span><span class="identifier">end</span><span class="plain">-</span><span class="identifier">name</span><span class="plain">&gt; | ==&gt; </span><span class="identifier">R</span><span class="plain">[2]; &lt;&lt;</span><span class="reserved">scene</span><span class="plain">:</span><span class="identifier">named</span><span class="plain">&gt;&gt; = </span><span class="identifier">RP</span><span class="plain">[1]</span>
<span class="plain">&lt;</span><span class="reserved">scene</span><span class="plain">-</span><span class="identifier">name</span><span class="plain">&gt; </span><span class="identifier">ends</span><span class="plain"> ... | ==&gt; </span>&lt;<span class="cwebmacro">Issue PM_ScenesUnknownEnd problem</span> <span class="cwebmacronumber">21.3</span>&gt;
<span class="plain">&lt;</span><span class="identifier">s</span><span class="plain">-</span><span class="identifier">condition</span><span class="plain">&gt; ==&gt; -2; &lt;&lt;</span><span class="identifier">parse_node</span><span class="plain">:</span><span class="identifier">cond</span><span class="plain">&gt;&gt; = </span><span class="identifier">RP</span><span class="plain">[1]</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP21_1"></a><b>&#167;21.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Issue PM_ScenesDisallowCalled problem</span> <span class="cwebmacronumber">21.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="plain">*</span><span class="identifier">X</span><span class="plain"> = -1;</span>
<span class="identifier">Problems::Issue::sentence_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_ScenesDisallowCalled</span><span class="plain">),</span>
<span class="string">"'(called ...)' is not allowed within conditions for a scene to begin or end"</span><span class="plain">,</span>
<span class="string">"since calling gives only a temporary name to something, for the purpose "</span>
<span class="string">"of further instructions which immediately follow in. Here there is no room "</span>
<span class="string">"for such further instructions, so a calling would have no effect. Anyway - "</span>
<span class="string">"not allowed!"</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP21">&#167;21</a>.</p>
<p class="inwebparagraph"><a id="SP21_2"></a><b>&#167;21.2. </b><code class="display">
&lt;<span class="cwebmacrodefn">Issue PM_ScenesNotPlay problem</span> <span class="cwebmacronumber">21.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="plain">*</span><span class="identifier">X</span><span class="plain"> = -1;</span>
<span class="identifier">Problems::Issue::sentence_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_ScenesNotPlay</span><span class="plain">),</span>
<span class="string">"'play' is not really a scene"</span><span class="plain">,</span>
<span class="string">"so although you can write '... when play begins' you cannot write '... "</span>
<span class="string">"when play ends'. But there's no need to do so, anyway. When play ends, "</span>
<span class="string">"all scenes end."</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP21">&#167;21</a>.</p>
<p class="inwebparagraph"><a id="SP21_3"></a><b>&#167;21.3. </b><code class="display">
&lt;<span class="cwebmacrodefn">Issue PM_ScenesUnknownEnd problem</span> <span class="cwebmacronumber">21.3</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="plain">*</span><span class="identifier">X</span><span class="plain"> = -1;</span>
<span class="identifier">Problems::Issue::sentence_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_ScenesUnknownEnd</span><span class="plain">),</span>
<span class="string">"that's not one of the known ends for that scene"</span><span class="plain">,</span>
<span class="string">"which must be declared with something like 'Confrontation ends happily "</span>
<span class="string">"when...' or 'Confrontation ends tragically when...'."</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP21">&#167;21</a>.</p>
<p class="inwebparagraph"><a id="SP22"></a><b>&#167;22. </b>Where the following filters instance names to allow those of scenes only,
and also internally converts the result:
</p>
<pre class="display">
<span class="plain">&lt;</span><span class="reserved">scene</span><span class="plain">-</span><span class="identifier">name</span><span class="plain">&gt; ::=</span>
<span class="plain">&lt;</span><span class="identifier">definite</span><span class="plain">-</span><span class="identifier">article</span><span class="plain">&gt; &lt;</span><span class="reserved">scene</span><span class="plain">-</span><span class="identifier">name</span><span class="plain">-</span><span class="identifier">unarticled</span><span class="plain">&gt; | ==&gt; </span><span class="identifier">R</span><span class="plain">[2]; *</span><span class="identifier">XP</span><span class="plain"> = </span><span class="identifier">RP</span><span class="plain">[2]</span>
<span class="plain">&lt;</span><span class="reserved">scene</span><span class="plain">-</span><span class="identifier">name</span><span class="plain">-</span><span class="identifier">unarticled</span><span class="plain">&gt; ==&gt; </span><span class="identifier">R</span><span class="plain">[1]; *</span><span class="identifier">XP</span><span class="plain"> = </span><span class="identifier">RP</span><span class="plain">[1]</span>
<span class="plain">&lt;</span><span class="reserved">scene</span><span class="plain">-</span><span class="identifier">name</span><span class="plain">-</span><span class="identifier">unarticled</span><span class="plain">&gt; ::=</span>
<span class="plain">&lt;</span><span class="identifier">instance</span><span class="plain">-</span><span class="identifier">of</span><span class="plain">-</span><span class="identifier">non</span><span class="plain">-</span><span class="identifier">object</span><span class="plain">&gt; ==&gt; </span>&lt;<span class="cwebmacro">Convert instance result to scene result, if possible</span> <span class="cwebmacronumber">22.1</span>&gt;
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP22_1"></a><b>&#167;22.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Convert instance result to scene result, if possible</span> <span class="cwebmacronumber">22.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">I</span><span class="plain"> = &lt;&lt;</span><span class="identifier">rp</span><span class="plain">&gt;&gt;;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Instances::of_kind</span><span class="plain">(</span><span class="identifier">I</span><span class="plain">, </span><span class="identifier">K_scene</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">*</span><span class="identifier">XP</span><span class="plain"> = </span><span class="functiontext">PL::Scenes::from_named_constant</span><span class="plain">(</span><span class="identifier">I</span><span class="plain">);</span>
<span class="identifier">scene_end_of_which_parsed</span><span class="plain"> = *</span><span class="identifier">XP</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP22">&#167;22</a>.</p>
<p class="inwebparagraph"><a id="SP23"></a><b>&#167;23. </b>Lastly, scene end names are parsed by these internals. They are identical
except that the creating case will create a new end if need be so that it
never fails.
</p>
<pre class="display">
<span class="plain">&lt;</span><span class="reserved">scene</span><span class="plain">-</span><span class="identifier">end</span><span class="plain">-</span><span class="identifier">name</span><span class="plain">&gt; </span><span class="identifier">internal</span><span class="plain"> {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">end</span><span class="plain"> = </span><span class="functiontext">PL::Scenes::parse_scene_end_name</span><span class="plain">(</span><span class="identifier">scene_end_of_which_parsed</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">end</span><span class="plain"> &lt; 0) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">*</span><span class="identifier">X</span><span class="plain"> = </span><span class="identifier">end</span><span class="plain">; </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">&lt;</span><span class="reserved">scene</span><span class="plain">-</span><span class="identifier">end</span><span class="plain">-</span><span class="identifier">name</span><span class="plain">-</span><span class="identifier">creating</span><span class="plain">&gt; </span><span class="identifier">internal</span><span class="plain"> {</span>
<span class="plain">*</span><span class="identifier">X</span><span class="plain"> = </span><span class="functiontext">PL::Scenes::parse_scene_end_name</span><span class="plain">(</span><span class="identifier">scene_end_of_which_parsed</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">, </span><span class="identifier">TRUE</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP24"></a><b>&#167;24. </b>In a sentence like
</p>
<blockquote>
<p>The Ballroom Dance begins when the Hallway Greeting ends.</p>
</blockquote>
<p class="inwebparagraph">we will call "the Ballroom Dance begins" this end, and "the Hallway Greeting
ends" the other end.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">PL::Scenes::new_scene_anchor</span><span class="plain">(</span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">p</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">phase</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">given_end</span><span class="plain">) {</span>
<span class="reserved">scene</span><span class="plain"> *</span><span class="identifier">this_scene</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">; </span> <span class="comment">scene whose end is being caused: must be set</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">end</span><span class="plain"> = -1; </span> <span class="comment">end which is being anchored: must be set</span>
<span class="reserved">scene</span><span class="plain"> *</span><span class="identifier">other_scene</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">; </span> <span class="comment">Either: another scene whose end it connects to</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">other_end</span><span class="plain"> = -1; </span> <span class="comment">and which end it is...</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">external_condition</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">; </span> <span class="comment">Or: an absolute condition...</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">when_play_begins</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">; </span> <span class="comment">Or: anchor to the start of play</span>
<span class="identifier">wording</span><span class="plain"> </span><span class="identifier">SW</span><span class="plain"> = </span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">); </span> <span class="comment">scene name</span>
<span class="identifier">wording</span><span class="plain"> </span><span class="identifier">EW</span><span class="plain"> = </span><span class="identifier">EMPTY_WORDING</span><span class="plain">; </span> <span class="comment">end name, if any</span>
<span class="identifier">wording</span><span class="plain"> </span><span class="identifier">CW</span><span class="plain"> = </span><span class="identifier">EMPTY_WORDING</span><span class="plain">; </span> <span class="comment">condition for end to occur</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">) {</span>
<span class="identifier">EW</span><span class="plain"> = </span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">);</span>
<span class="identifier">CW</span><span class="plain"> = </span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">);</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">CW</span><span class="plain"> = </span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">);</span>
<span class="plain">}</span>
&lt;<span class="cwebmacro">Parse the scene and end to be anchored</span> <span class="cwebmacronumber">24.4</span>&gt;<span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">this_scene</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) || (</span><span class="identifier">end</span><span class="plain"> &lt; 0)) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"scene misparsed"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">phase</span><span class="plain"> == 2) {</span>
&lt;<span class="cwebmacro">Parse which form of anchor we have</span> <span class="cwebmacronumber">24.5</span>&gt;<span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">this_scene</span><span class="plain"> == </span><span class="identifier">SC_entire_game</span><span class="plain">) &amp;&amp; (</span><span class="identifier">external_condition</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">)) {</span>
<span class="identifier">Problems::Issue::sentence_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_EntireGameHardwired</span><span class="plain">),</span>
<span class="string">"the special 'Entire Game' scene cannot have its start or end modified"</span><span class="plain">,</span>
<span class="string">"because it is a built-in scene designed to be going on whenever there "</span>
<span class="string">"is play going on in the story."</span><span class="plain">);</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">when_play_begins</span><span class="plain">)</span>
&lt;<span class="cwebmacro">Connect this end to the start of play</span> <span class="cwebmacronumber">24.1</span>&gt;
<span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">other_scene</span><span class="plain">)</span>
&lt;<span class="cwebmacro">Connect this end to an end of another scene</span> <span class="cwebmacronumber">24.3</span>&gt;
<span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">external_condition</span><span class="plain">)</span>
&lt;<span class="cwebmacro">Make this an external scene end condition</span> <span class="cwebmacronumber">24.2</span>&gt;
<span class="reserved">else</span><span class="plain"> </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"failed to obtain an anchor condition"</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function PL::Scenes::new_scene_anchor is used in <a href="#SP16">&#167;16</a>, <a href="#SP17">&#167;17</a>.</p>
<p class="inwebparagraph"><a id="SP24_1"></a><b>&#167;24.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Connect this end to the start of play</span> <span class="cwebmacronumber">24.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">this_scene</span><span class="plain">-</span><span class="element">&gt;start_of_play</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP24">&#167;24</a>.</p>
<p class="inwebparagraph"><a id="SP24_2"></a><b>&#167;24.2. </b><code class="display">
&lt;<span class="cwebmacrodefn">Make this an external scene end condition</span> <span class="cwebmacronumber">24.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">this_scene</span><span class="plain">-</span><span class="element">&gt;anchor_condition</span><span class="plain">[</span><span class="identifier">end</span><span class="plain">])</span>
<span class="identifier">Problems::Issue::sentence_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_ScenesOversetEnd</span><span class="plain">),</span>
<span class="string">"you have already told me a condition for when that happens"</span><span class="plain">,</span>
<span class="string">"and although a scene can be linked to the beginning or ending "</span>
<span class="string">"of any number of other scenes, it can only have a single "</span>
<span class="string">"condition such as 'when the player is in the Dining Car' "</span>
<span class="string">"to trigger it from outside the scene machinery."</span><span class="plain">);</span>
<span class="identifier">this_scene</span><span class="plain">-</span><span class="element">&gt;anchor_condition</span><span class="plain">[</span><span class="identifier">end</span><span class="plain">] = </span><span class="identifier">external_condition</span><span class="plain">;</span>
<span class="identifier">this_scene</span><span class="plain">-</span><span class="element">&gt;anchor_condition_set</span><span class="plain">[</span><span class="identifier">end</span><span class="plain">] = </span><span class="identifier">current_sentence</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP24">&#167;24</a>.</p>
<p class="inwebparagraph"><a id="SP24_3"></a><b>&#167;24.3. </b><code class="display">
&lt;<span class="cwebmacrodefn">Connect this end to an end of another scene</span> <span class="cwebmacronumber">24.3</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">scene_connector</span><span class="plain"> *</span><span class="identifier">scon</span><span class="plain"> = </span><span class="identifier">CREATE</span><span class="plain">(</span><span class="reserved">scene_connector</span><span class="plain">);</span>
<span class="identifier">scon</span><span class="plain">-</span><span class="element">&gt;connect_to</span><span class="plain"> = </span><span class="identifier">other_scene</span><span class="plain">;</span>
<span class="identifier">scon</span><span class="plain">-</span><span class="element">&gt;end</span><span class="plain"> = </span><span class="identifier">other_end</span><span class="plain">;</span>
<span class="identifier">scon</span><span class="plain">-</span><span class="element">&gt;where_said</span><span class="plain"> = </span><span class="identifier">current_sentence</span><span class="plain">;</span>
<span class="identifier">scon</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain"> = </span><span class="identifier">this_scene</span><span class="plain">-</span><span class="element">&gt;anchor_scene</span><span class="plain">[</span><span class="identifier">end</span><span class="plain">];</span>
<span class="identifier">this_scene</span><span class="plain">-</span><span class="element">&gt;anchor_scene</span><span class="plain">[</span><span class="identifier">end</span><span class="plain">] = </span><span class="identifier">scon</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP24">&#167;24</a>.</p>
<p class="inwebparagraph"><a id="SP24_4"></a><b>&#167;24.4. </b><code class="display">
&lt;<span class="cwebmacrodefn">Parse the scene and end to be anchored</span> <span class="cwebmacronumber">24.4</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="plain">&lt;</span><span class="reserved">scene</span><span class="plain">-</span><span class="identifier">ends</span><span class="plain">-</span><span class="identifier">sentence</span><span class="plain">-</span><span class="identifier">subject</span><span class="plain">&gt;(</span><span class="identifier">SW</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (&lt;&lt;</span><span class="identifier">r</span><span class="plain">&gt;&gt; == </span><span class="identifier">FALSE</span><span class="plain">) </span><span class="reserved">return</span><span class="plain">;</span>
<span class="identifier">this_scene</span><span class="plain"> = &lt;&lt;</span><span class="identifier">rp</span><span class="plain">&gt;&gt;;</span>
<span class="identifier">scene_end_of_which_parsed</span><span class="plain"> = </span><span class="identifier">this_scene</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Wordings::nonempty</span><span class="plain">(</span><span class="identifier">EW</span><span class="plain">)) {</span>
<span class="plain">&lt;</span><span class="reserved">scene</span><span class="plain">-</span><span class="identifier">ends</span><span class="plain">-</span><span class="identifier">sentence</span><span class="plain">-</span><span class="identifier">adverb</span><span class="plain">&gt;(</span><span class="identifier">EW</span><span class="plain">);</span>
<span class="identifier">end</span><span class="plain"> = &lt;&lt;</span><span class="identifier">r</span><span class="plain">&gt;&gt;;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="identifier">end</span><span class="plain"> = </span><span class="identifier">given_end</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">end</span><span class="plain"> &lt; 0) </span><span class="reserved">return</span><span class="plain">; </span> <span class="comment">to recover from any parsing Problems</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP24">&#167;24</a>.</p>
<p class="inwebparagraph"><a id="SP24_5"></a><b>&#167;24.5. </b><code class="display">
&lt;<span class="cwebmacrodefn">Parse which form of anchor we have</span> <span class="cwebmacronumber">24.5</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (&lt;</span><span class="reserved">scene</span><span class="plain">-</span><span class="identifier">ends</span><span class="plain">-</span><span class="identifier">sentence</span><span class="plain">-</span><span class="identifier">object</span><span class="plain">&gt;(</span><span class="identifier">CW</span><span class="plain">)) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">end</span><span class="plain"> = &lt;&lt;</span><span class="identifier">r</span><span class="plain">&gt;&gt;;</span>
<span class="reserved">switch</span><span class="plain"> (</span><span class="identifier">end</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> -2: </span><span class="identifier">external_condition</span><span class="plain"> = &lt;&lt;</span><span class="identifier">parse_node</span><span class="plain">:</span><span class="identifier">cond</span><span class="plain">&gt;&gt;; </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> -1: </span><span class="identifier">when_play_begins</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">; </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">default</span><span class="plain">: </span><span class="identifier">other_end</span><span class="plain"> = </span><span class="identifier">end</span><span class="plain">; </span><span class="identifier">other_scene</span><span class="plain"> = &lt;&lt;</span><span class="reserved">scene</span><span class="plain">:</span><span class="identifier">named</span><span class="plain">&gt;&gt;; </span><span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="identifier">external_condition</span><span class="plain"> = </span><span class="identifier">Specifications::new_UNKNOWN</span><span class="plain">(</span><span class="identifier">CW</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP24">&#167;24</a>.</p>
<p class="inwebparagraph"><a id="SP25"></a><b>&#167;25. Scene-changing machinery at run-time. </b>So what are scenes for? Well, they have two uses. One is that the end rulebooks
are run when ends occur, which is a convenient way to time events. The
following generates the necessary code to (a) detect when a scene end occurs,
and (b) act upon it. This is all handled by the following I6 routine.
</p>
<p class="inwebparagraph">There is one argument, <code class="display"><span class="extract">chs</span></code>: the number of iterations so far. Iterations occur
because each set of scene changes could change the circumstances in such a
way that other scene changes are now required (through external conditions,
not through anchors); we don't want this to lock up, so we will cap recursion.
Within the routine, a second local variable, <code class="display"><span class="extract">ch</span></code>, is a flag indicating
whether any change in status has or has not occurred.
</p>
<p class="inwebparagraph">There is no significance to the return value.
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="constant">MAX_SCENE_CHANGE_ITERATION</span><span class="plain"> 20</span>
</pre>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">PL::Scenes::DetectSceneChange_routine</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="identifier">inter_name</span><span class="plain"> *</span><span class="identifier">iname</span><span class="plain"> = </span><span class="identifier">Hierarchy::find</span><span class="plain">(</span><span class="identifier">DETECTSCENECHANGE_HL</span><span class="plain">);</span>
<span class="identifier">packaging_state</span><span class="plain"> </span><span class="identifier">save</span><span class="plain"> = </span><span class="identifier">Routines::begin</span><span class="plain">(</span><span class="identifier">iname</span><span class="plain">);</span>
<span class="identifier">inter_symbol</span><span class="plain"> *</span><span class="identifier">self</span><span class="plain"> = </span><span class="identifier">InterNames::to_symbol</span><span class="plain">(</span><span class="identifier">iname</span><span class="plain">);</span>
<span class="identifier">inter_symbol</span><span class="plain"> *</span><span class="identifier">chs_s</span><span class="plain"> = </span><span class="identifier">LocalVariables::add_internal_local_c_as_symbol</span><span class="plain">(</span><span class="identifier">I</span><span class="string">"chs"</span><span class="plain">, </span><span class="string">"count of changes made"</span><span class="plain">);</span>
<span class="identifier">inter_symbol</span><span class="plain"> *</span><span class="identifier">ch_s</span><span class="plain"> = </span><span class="identifier">LocalVariables::add_internal_local_c_as_symbol</span><span class="plain">(</span><span class="identifier">I</span><span class="string">"ch"</span><span class="plain">, </span><span class="string">"flag: change made"</span><span class="plain">);</span>
<span class="identifier">inter_symbol</span><span class="plain"> *</span><span class="identifier">CScene_l</span><span class="plain"> = </span><span class="identifier">Emit::reserve_label</span><span class="plain">(</span><span class="identifier">I</span><span class="string">".CScene"</span><span class="plain">);</span>
<span class="reserved">scene</span><span class="plain"> *</span><span class="identifier">sc</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">sc</span><span class="plain">, </span><span class="reserved">scene</span><span class="plain">) </span>&lt;<span class="cwebmacro">Compile code detecting the ends of a specific scene</span> <span class="cwebmacronumber">25.2</span>&gt;<span class="plain">;</span>
<span class="identifier">Emit::place_label</span><span class="plain">(</span><span class="identifier">CScene_l</span><span class="plain">, </span><span class="identifier">TRUE</span><span class="plain">);</span>
&lt;<span class="cwebmacro">Add the scene-change tail</span> <span class="cwebmacronumber">25.1</span>&gt;<span class="plain">;</span>
<span class="identifier">Routines::end</span><span class="plain">(</span><span class="identifier">save</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function PL::Scenes::DetectSceneChange_routine appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP25_1"></a><b>&#167;25.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Add the scene-change tail</span> <span class="cwebmacronumber">25.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">Emit::inv_primitive</span><span class="plain">(</span><span class="identifier">if_interp</span><span class="plain">);</span>
<span class="identifier">Emit::down</span><span class="plain">();</span>
<span class="identifier">Emit::inv_primitive</span><span class="plain">(</span><span class="identifier">gt_interp</span><span class="plain">);</span>
<span class="identifier">Emit::down</span><span class="plain">();</span>
<span class="identifier">Emit::val_symbol</span><span class="plain">(</span><span class="identifier">K_value</span><span class="plain">, </span><span class="identifier">chs_s</span><span class="plain">);</span>
<span class="identifier">Emit::val</span><span class="plain">(</span><span class="identifier">K_number</span><span class="plain">, </span><span class="identifier">LITERAL_IVAL</span><span class="plain">, (</span><span class="identifier">inter_t</span><span class="plain">) </span><span class="constant">MAX_SCENE_CHANGE_ITERATION</span><span class="plain">);</span>
<span class="identifier">Emit::up</span><span class="plain">();</span>
<span class="identifier">Emit::code</span><span class="plain">();</span>
<span class="identifier">Emit::down</span><span class="plain">();</span>
<span class="identifier">Emit::inv_primitive</span><span class="plain">(</span><span class="identifier">print_interp</span><span class="plain">);</span>
<span class="identifier">Emit::down</span><span class="plain">();</span>
<span class="identifier">Emit::val_text</span><span class="plain">(</span><span class="identifier">I</span><span class="string">"&gt;--&gt; The scene change machinery is stuck.\</span><span class="plain">n</span><span class="string">"</span><span class="plain">);</span>
<span class="identifier">Emit::up</span><span class="plain">();</span>
<span class="identifier">Emit::rtrue</span><span class="plain">();</span>
<span class="identifier">Emit::up</span><span class="plain">();</span>
<span class="identifier">Emit::up</span><span class="plain">();</span>
<span class="identifier">Emit::inv_primitive</span><span class="plain">(</span><span class="identifier">if_interp</span><span class="plain">);</span>
<span class="identifier">Emit::down</span><span class="plain">();</span>
<span class="identifier">Emit::inv_primitive</span><span class="plain">(</span><span class="identifier">gt_interp</span><span class="plain">);</span>
<span class="identifier">Emit::down</span><span class="plain">();</span>
<span class="identifier">Emit::val_symbol</span><span class="plain">(</span><span class="identifier">K_value</span><span class="plain">, </span><span class="identifier">ch_s</span><span class="plain">);</span>
<span class="identifier">Emit::val</span><span class="plain">(</span><span class="identifier">K_number</span><span class="plain">, </span><span class="identifier">LITERAL_IVAL</span><span class="plain">, 0);</span>
<span class="identifier">Emit::up</span><span class="plain">();</span>
<span class="identifier">Emit::code</span><span class="plain">();</span>
<span class="identifier">Emit::down</span><span class="plain">();</span>
<span class="identifier">Emit::inv_call</span><span class="plain">(</span><span class="identifier">self</span><span class="plain">);</span>
<span class="identifier">Emit::down</span><span class="plain">();</span>
<span class="identifier">Emit::inv_primitive</span><span class="plain">(</span><span class="identifier">preincrement_interp</span><span class="plain">);</span>
<span class="identifier">Emit::down</span><span class="plain">();</span>
<span class="identifier">Emit::ref_symbol</span><span class="plain">(</span><span class="identifier">K_value</span><span class="plain">, </span><span class="identifier">chs_s</span><span class="plain">);</span>
<span class="identifier">Emit::up</span><span class="plain">();</span>
<span class="identifier">Emit::up</span><span class="plain">();</span>
<span class="identifier">Emit::up</span><span class="plain">();</span>
<span class="identifier">Emit::up</span><span class="plain">();</span>
<span class="identifier">Emit::rfalse</span><span class="plain">();</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP25">&#167;25</a>.</p>
<p class="inwebparagraph"><a id="SP25_2"></a><b>&#167;25.2. </b>Recall that ends numbered 1, 2, 3, ... are all ways for the scene to end,
so they are only checked if its status is currently running; end 0 is the
beginning, checked only if it isn't. We give priority to the higher end
numbers so that more abstruse ways to end take precedence over less.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Compile code detecting the ends of a specific scene</span> <span class="cwebmacronumber">25.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">Emit::inv_primitive</span><span class="plain">(</span><span class="identifier">if_interp</span><span class="plain">);</span>
<span class="identifier">Emit::down</span><span class="plain">();</span>
<span class="identifier">Emit::inv_primitive</span><span class="plain">(</span><span class="identifier">eq_interp</span><span class="plain">);</span>
<span class="identifier">Emit::down</span><span class="plain">();</span>
<span class="identifier">Emit::inv_primitive</span><span class="plain">(</span><span class="identifier">lookup_interp</span><span class="plain">);</span>
<span class="identifier">Emit::down</span><span class="plain">();</span>
<span class="identifier">Emit::val_iname</span><span class="plain">(</span><span class="identifier">K_object</span><span class="plain">, </span><span class="identifier">Hierarchy::find</span><span class="plain">(</span><span class="identifier">SCENE_STATUS_HL</span><span class="plain">));</span>
<span class="identifier">Emit::val</span><span class="plain">(</span><span class="identifier">K_number</span><span class="plain">, </span><span class="identifier">LITERAL_IVAL</span><span class="plain">, (</span><span class="identifier">inter_t</span><span class="plain">) </span><span class="identifier">sc</span><span class="plain">-&gt;</span><span class="identifier">allocation_id</span><span class="plain">);</span>
<span class="identifier">Emit::up</span><span class="plain">();</span>
<span class="identifier">Emit::val</span><span class="plain">(</span><span class="identifier">K_number</span><span class="plain">, </span><span class="identifier">LITERAL_IVAL</span><span class="plain">, 1);</span>
<span class="identifier">Emit::up</span><span class="plain">();</span>
<span class="identifier">Emit::code</span><span class="plain">();</span>
<span class="identifier">Emit::down</span><span class="plain">();</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">end</span><span class="plain">=</span><span class="identifier">sc</span><span class="plain">-</span><span class="element">&gt;no_ends</span><span class="plain">-1; </span><span class="identifier">end</span><span class="plain">&gt;=1; </span><span class="identifier">end</span><span class="plain">--)</span>
<span class="functiontext">PL::Scenes::test_scene_end</span><span class="plain">(</span><span class="identifier">sc</span><span class="plain">, </span><span class="identifier">end</span><span class="plain">, </span><span class="identifier">ch_s</span><span class="plain">, </span><span class="identifier">CScene_l</span><span class="plain">);</span>
<span class="identifier">Emit::up</span><span class="plain">();</span>
<span class="identifier">Emit::up</span><span class="plain">();</span>
<span class="identifier">Emit::inv_primitive</span><span class="plain">(</span><span class="identifier">if_interp</span><span class="plain">);</span>
<span class="identifier">Emit::down</span><span class="plain">();</span>
<span class="identifier">Emit::inv_primitive</span><span class="plain">(</span><span class="identifier">eq_interp</span><span class="plain">);</span>
<span class="identifier">Emit::down</span><span class="plain">();</span>
<span class="identifier">Emit::inv_primitive</span><span class="plain">(</span><span class="identifier">lookup_interp</span><span class="plain">);</span>
<span class="identifier">Emit::down</span><span class="plain">();</span>
<span class="identifier">Emit::val_iname</span><span class="plain">(</span><span class="identifier">K_object</span><span class="plain">, </span><span class="identifier">Hierarchy::find</span><span class="plain">(</span><span class="identifier">SCENE_STATUS_HL</span><span class="plain">));</span>
<span class="identifier">Emit::val</span><span class="plain">(</span><span class="identifier">K_number</span><span class="plain">, </span><span class="identifier">LITERAL_IVAL</span><span class="plain">, (</span><span class="identifier">inter_t</span><span class="plain">) </span><span class="identifier">sc</span><span class="plain">-&gt;</span><span class="identifier">allocation_id</span><span class="plain">);</span>
<span class="identifier">Emit::up</span><span class="plain">();</span>
<span class="identifier">Emit::val</span><span class="plain">(</span><span class="identifier">K_number</span><span class="plain">, </span><span class="identifier">LITERAL_IVAL</span><span class="plain">, 0);</span>
<span class="identifier">Emit::up</span><span class="plain">();</span>
<span class="identifier">Emit::code</span><span class="plain">();</span>
<span class="identifier">Emit::down</span><span class="plain">();</span>
<span class="functiontext">PL::Scenes::test_scene_end</span><span class="plain">(</span><span class="identifier">sc</span><span class="plain">, 0, </span><span class="identifier">ch_s</span><span class="plain">, </span><span class="identifier">CScene_l</span><span class="plain">);</span>
<span class="identifier">Emit::up</span><span class="plain">();</span>
<span class="identifier">Emit::up</span><span class="plain">();</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP25">&#167;25</a>.</p>
<p class="inwebparagraph"><a id="SP26"></a><b>&#167;26. </b>Individual ends are tested here. There are actually three ways an end can
occur: at start of play (for end 0 only), when an I7 condition holds, or when
another end to which it is anchored also ends. But we only check the first
two, because the third way will be taken care of by the consequences code
below.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">PL::Scenes::test_scene_end</span><span class="plain">(</span><span class="reserved">scene</span><span class="plain"> *</span><span class="identifier">sc</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">end</span><span class="plain">, </span><span class="identifier">inter_symbol</span><span class="plain"> *</span><span class="identifier">ch_s</span><span class="plain">, </span><span class="identifier">inter_symbol</span><span class="plain"> *</span><span class="identifier">CScene_l</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">end</span><span class="plain"> == 0) &amp;&amp; (</span><span class="identifier">sc</span><span class="plain">-</span><span class="element">&gt;start_of_play</span><span class="plain">)) {</span>
<span class="identifier">Emit::inv_primitive</span><span class="plain">(</span><span class="identifier">if_interp</span><span class="plain">);</span>
<span class="identifier">Emit::down</span><span class="plain">();</span>
<span class="identifier">Emit::inv_primitive</span><span class="plain">(</span><span class="identifier">eq_interp</span><span class="plain">);</span>
<span class="identifier">Emit::down</span><span class="plain">();</span>
<span class="identifier">Emit::inv_primitive</span><span class="plain">(</span><span class="identifier">bitwiseand_interp</span><span class="plain">);</span>
<span class="identifier">Emit::down</span><span class="plain">();</span>
<span class="identifier">Emit::inv_primitive</span><span class="plain">(</span><span class="identifier">lookup_interp</span><span class="plain">);</span>
<span class="identifier">Emit::down</span><span class="plain">();</span>
<span class="identifier">Emit::val_iname</span><span class="plain">(</span><span class="identifier">K_object</span><span class="plain">, </span><span class="identifier">Hierarchy::find</span><span class="plain">(</span><span class="identifier">SCENE_ENDINGS_HL</span><span class="plain">));</span>
<span class="identifier">Emit::val</span><span class="plain">(</span><span class="identifier">K_number</span><span class="plain">, </span><span class="identifier">LITERAL_IVAL</span><span class="plain">, (</span><span class="identifier">inter_t</span><span class="plain">) </span><span class="identifier">sc</span><span class="plain">-&gt;</span><span class="identifier">allocation_id</span><span class="plain">);</span>
<span class="identifier">Emit::up</span><span class="plain">();</span>
<span class="identifier">Emit::val</span><span class="plain">(</span><span class="identifier">K_number</span><span class="plain">, </span><span class="identifier">LITERAL_IVAL</span><span class="plain">, 1);</span>
<span class="identifier">Emit::up</span><span class="plain">();</span>
<span class="identifier">Emit::val</span><span class="plain">(</span><span class="identifier">K_number</span><span class="plain">, </span><span class="identifier">LITERAL_IVAL</span><span class="plain">, 0);</span>
<span class="identifier">Emit::up</span><span class="plain">();</span>
<span class="identifier">Emit::code</span><span class="plain">();</span>
<span class="identifier">Emit::down</span><span class="plain">();</span>
<span class="functiontext">PL::Scenes::compile_scene_end</span><span class="plain">(</span><span class="identifier">sc</span><span class="plain">, 0);</span>
<span class="identifier">Emit::up</span><span class="plain">();</span>
<span class="identifier">Emit::up</span><span class="plain">();</span>
<span class="plain">}</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">S</span><span class="plain"> = </span><span class="identifier">sc</span><span class="plain">-</span><span class="element">&gt;anchor_condition</span><span class="plain">[</span><span class="identifier">end</span><span class="plain">];</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">S</span><span class="plain">) {</span>
&lt;<span class="cwebmacro">Reparse the scene end condition in this new context</span> <span class="cwebmacronumber">26.1</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Compile code to test the scene end condition</span> <span class="cwebmacronumber">26.2</span>&gt;<span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function PL::Scenes::test_scene_end is used in <a href="#SP25_2">&#167;25.2</a>.</p>
<p class="inwebparagraph"><a id="SP26_1"></a><b>&#167;26.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Reparse the scene end condition in this new context</span> <span class="cwebmacronumber">26.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">current_sentence</span><span class="plain"> = </span><span class="identifier">sc</span><span class="plain">-</span><span class="element">&gt;anchor_condition_set</span><span class="plain">[</span><span class="identifier">end</span><span class="plain">];</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ParseTree::is</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">, </span><span class="identifier">UNKNOWN_NT</span><span class="plain">)) {</span>
<span class="reserved">if</span><span class="plain"> (&lt;</span><span class="identifier">s</span><span class="plain">-</span><span class="identifier">condition</span><span class="plain">&gt;(</span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">))) </span><span class="identifier">S</span><span class="plain"> = &lt;&lt;</span><span class="identifier">rp</span><span class="plain">&gt;&gt;;</span>
<span class="identifier">sc</span><span class="plain">-</span><span class="element">&gt;anchor_condition</span><span class="plain">[</span><span class="identifier">end</span><span class="plain">] = </span><span class="identifier">S</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ParseTree::is</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">, </span><span class="identifier">UNKNOWN_NT</span><span class="plain">)) {</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Condition: $P\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">S</span><span class="plain">);</span>
<span class="identifier">Problems::Issue::sentence_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_ScenesBadCondition</span><span class="plain">),</span>
<span class="string">"'begins when' and 'ends when' must be followed by a condition"</span><span class="plain">,</span>
<span class="string">"which this does not seem to be, or else 'when play begins', "</span>
<span class="string">"'when play ends', 'when S begins', or 'when S ends', where "</span>
<span class="string">"S is the name of any scene."</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Dash::check_condition</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">) </span><span class="reserved">return</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP26">&#167;26</a>.</p>
<p class="inwebparagraph"><a id="SP26_2"></a><b>&#167;26.2. </b>If the condition holds, we set the change flag <code class="display"><span class="extract">ch</span></code> and abort the search
through scenes by jumping past the run of tests. (We can't compile a break
instruction because we're not compiling a loop.)
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Compile code to test the scene end condition</span> <span class="cwebmacronumber">26.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">Emit::inv_primitive</span><span class="plain">(</span><span class="identifier">if_interp</span><span class="plain">);</span>
<span class="identifier">Emit::down</span><span class="plain">();</span>
<span class="identifier">current_sentence</span><span class="plain"> = </span><span class="identifier">sc</span><span class="plain">-</span><span class="element">&gt;anchor_condition_set</span><span class="plain">[</span><span class="identifier">end</span><span class="plain">];</span>
<span class="identifier">Specifications::Compiler::emit_as_val</span><span class="plain">(</span><span class="identifier">K_truth_state</span><span class="plain">, </span><span class="identifier">S</span><span class="plain">);</span>
<span class="identifier">Emit::code</span><span class="plain">();</span>
<span class="identifier">Emit::down</span><span class="plain">();</span>
<span class="identifier">Emit::inv_primitive</span><span class="plain">(</span><span class="identifier">store_interp</span><span class="plain">);</span>
<span class="identifier">Emit::down</span><span class="plain">();</span>
<span class="identifier">Emit::ref_symbol</span><span class="plain">(</span><span class="identifier">K_value</span><span class="plain">, </span><span class="identifier">ch_s</span><span class="plain">);</span>
<span class="identifier">Emit::val</span><span class="plain">(</span><span class="identifier">K_number</span><span class="plain">, </span><span class="identifier">LITERAL_IVAL</span><span class="plain">, 1);</span>
<span class="identifier">Emit::up</span><span class="plain">();</span>
<span class="functiontext">PL::Scenes::compile_scene_end</span><span class="plain">(</span><span class="identifier">sc</span><span class="plain">, </span><span class="identifier">end</span><span class="plain">);</span>
<span class="identifier">Emit::inv_primitive</span><span class="plain">(</span><span class="identifier">jump_interp</span><span class="plain">);</span>
<span class="identifier">Emit::down</span><span class="plain">();</span>
<span class="identifier">Emit::lab</span><span class="plain">(</span><span class="identifier">CScene_l</span><span class="plain">);</span>
<span class="identifier">Emit::up</span><span class="plain">();</span>
<span class="identifier">Emit::up</span><span class="plain">();</span>
<span class="identifier">Emit::up</span><span class="plain">();</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP26">&#167;26</a>.</p>
<p class="inwebparagraph"><a id="SP27"></a><b>&#167;27. </b>That's everything except for the consequences of a scene end occurring.
Code for that is generated here.
</p>
<p class="inwebparagraph">Because one end can cause another, given anchoring, we must guard against
compiler hangs when the source text calls for infinite recursion (since
this would cause us to generate infinitely long code). So the <code class="display"><span class="extract">marker</span></code> flags
are used to mark which scenes have already been ended in code generated
for this purpose.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">PL::Scenes::compile_scene_end</span><span class="plain">(</span><span class="reserved">scene</span><span class="plain"> *</span><span class="identifier">sc</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">end</span><span class="plain">) {</span>
<span class="reserved">scene</span><span class="plain"> *</span><span class="identifier">sc2</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">sc2</span><span class="plain">, </span><span class="reserved">scene</span><span class="plain">) </span><span class="identifier">sc2</span><span class="plain">-</span><span class="element">&gt;marker</span><span class="plain"> = 0;</span>
<span class="functiontext">PL::Scenes::compile_scene_end_dash</span><span class="plain">(</span><span class="identifier">sc</span><span class="plain">, </span><span class="identifier">end</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function PL::Scenes::compile_scene_end is used in <a href="#SP26">&#167;26</a>, <a href="#SP26_2">&#167;26.2</a>.</p>
<p class="inwebparagraph"><a id="SP28"></a><b>&#167;28. </b>The semantics of scene ending are trickier than they look, because of the
fact that "Ballroom Dance ends merrily" (say, end number 3) is in some
sense a specialisation of "Ballroom Dance ends" (1). The doctrine is that
end 3 causes end 1 to happen first, because a special ending is also a
general ending; but rules taking effect on end 3 come earlier than
those for end 1, because they're more specialised, so they have a right to
take effect first.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">PL::Scenes::compile_scene_end_dash</span><span class="plain">(</span><span class="reserved">scene</span><span class="plain"> *</span><span class="identifier">sc</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">end</span><span class="plain">) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">ix</span><span class="plain"> = </span><span class="identifier">sc</span><span class="plain">-&gt;</span><span class="identifier">allocation_id</span><span class="plain">;</span>
<span class="identifier">sc</span><span class="plain">-</span><span class="element">&gt;marker</span><span class="plain">++;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">end</span><span class="plain"> &gt;= 2) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">e</span><span class="plain"> = </span><span class="identifier">end</span><span class="plain">; </span><span class="identifier">end</span><span class="plain"> = 1;</span>
&lt;<span class="cwebmacro">Compile code to print text in response to the SCENES command</span> <span class="cwebmacronumber">28.4</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Compile code to update the scene status</span> <span class="cwebmacronumber">28.1</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Compile code to update the arrays recording most recent scene ending</span> <span class="cwebmacronumber">28.3</span>&gt;<span class="plain">;</span>
<span class="identifier">end</span><span class="plain"> = </span><span class="identifier">e</span><span class="plain">;</span>
<span class="plain">}</span>
&lt;<span class="cwebmacro">Compile code to print text in response to the SCENES command</span> <span class="cwebmacronumber">28.4</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Compile code to update the scene status</span> <span class="cwebmacronumber">28.1</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Compile code to run the scene end rulebooks</span> <span class="cwebmacronumber">28.2</span>&gt;
&lt;<span class="cwebmacro">Compile code to update the arrays recording most recent scene ending</span> <span class="cwebmacronumber">28.3</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Compile code to cause consequent scene ends</span> <span class="cwebmacronumber">28.5</span>&gt;<span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">end</span><span class="plain"> &gt;= 2) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">e</span><span class="plain"> = </span><span class="identifier">end</span><span class="plain">; </span><span class="identifier">end</span><span class="plain"> = 1;</span>
&lt;<span class="cwebmacro">Compile code to run the scene end rulebooks</span> <span class="cwebmacronumber">28.2</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Compile code to cause consequent scene ends</span> <span class="cwebmacronumber">28.5</span>&gt;<span class="plain">;</span>
<span class="identifier">end</span><span class="plain"> = </span><span class="identifier">e</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function PL::Scenes::compile_scene_end_dash is used in <a href="#SP27">&#167;27</a>, <a href="#SP28_5">&#167;28.5</a>.</p>
<p class="inwebparagraph"><a id="SP28_1"></a><b>&#167;28.1. </b>If the scene has the "recurring" either/or property, then any of the
"ends" endings will fail to reset its status. (This doesn't mean that no
end actually occurred.)
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Compile code to update the scene status</span> <span class="cwebmacronumber">28.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">end</span><span class="plain"> == 0) {</span>
<span class="identifier">Emit::inv_primitive</span><span class="plain">(</span><span class="identifier">store_interp</span><span class="plain">);</span>
<span class="identifier">Emit::down</span><span class="plain">();</span>
<span class="identifier">Emit::inv_primitive</span><span class="plain">(</span><span class="identifier">lookupref_interp</span><span class="plain">);</span>
<span class="identifier">Emit::down</span><span class="plain">();</span>
<span class="identifier">Emit::val_iname</span><span class="plain">(</span><span class="identifier">K_value</span><span class="plain">, </span><span class="identifier">Hierarchy::find</span><span class="plain">(</span><span class="identifier">SCENE_STATUS_HL</span><span class="plain">));</span>
<span class="identifier">Emit::val</span><span class="plain">(</span><span class="identifier">K_number</span><span class="plain">, </span><span class="identifier">LITERAL_IVAL</span><span class="plain">, (</span><span class="identifier">inter_t</span><span class="plain">) </span><span class="identifier">sc</span><span class="plain">-&gt;</span><span class="identifier">allocation_id</span><span class="plain">);</span>
<span class="identifier">Emit::up</span><span class="plain">();</span>
<span class="identifier">Emit::val</span><span class="plain">(</span><span class="identifier">K_number</span><span class="plain">, </span><span class="identifier">LITERAL_IVAL</span><span class="plain">, 1);</span>
<span class="identifier">Emit::up</span><span class="plain">();</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">Emit::inv_primitive</span><span class="plain">(</span><span class="identifier">ifelse_interp</span><span class="plain">);</span>
<span class="identifier">Emit::down</span><span class="plain">();</span>
<span class="identifier">inter_name</span><span class="plain"> *</span><span class="identifier">iname</span><span class="plain"> = </span><span class="identifier">Hierarchy::find</span><span class="plain">(</span><span class="identifier">GPROPERTY_HL</span><span class="plain">);</span>
<span class="identifier">Emit::inv_call</span><span class="plain">(</span><span class="identifier">InterNames::to_symbol</span><span class="plain">(</span><span class="identifier">iname</span><span class="plain">));</span>
<span class="identifier">Emit::down</span><span class="plain">();</span>
<span class="identifier">Kinds::RunTime::emit_weak_id_as_val</span><span class="plain">(</span><span class="identifier">K_scene</span><span class="plain">);</span>
<span class="identifier">Emit::val</span><span class="plain">(</span><span class="identifier">K_number</span><span class="plain">, </span><span class="identifier">LITERAL_IVAL</span><span class="plain">, (</span><span class="identifier">inter_t</span><span class="plain">) </span><span class="identifier">ix</span><span class="plain">+1);</span>
<span class="identifier">Emit::val_iname</span><span class="plain">(</span><span class="identifier">K_value</span><span class="plain">, </span><span class="identifier">Properties::iname</span><span class="plain">(</span><span class="identifier">P_recurring</span><span class="plain">));</span>
<span class="identifier">Emit::up</span><span class="plain">();</span>
<span class="identifier">Emit::code</span><span class="plain">();</span>
<span class="identifier">Emit::down</span><span class="plain">();</span>
<span class="identifier">Emit::inv_primitive</span><span class="plain">(</span><span class="identifier">store_interp</span><span class="plain">);</span>
<span class="identifier">Emit::down</span><span class="plain">();</span>
<span class="identifier">Emit::inv_primitive</span><span class="plain">(</span><span class="identifier">lookupref_interp</span><span class="plain">);</span>
<span class="identifier">Emit::down</span><span class="plain">();</span>
<span class="identifier">Emit::val_iname</span><span class="plain">(</span><span class="identifier">K_value</span><span class="plain">, </span><span class="identifier">Hierarchy::find</span><span class="plain">(</span><span class="identifier">SCENE_STATUS_HL</span><span class="plain">));</span>
<span class="identifier">Emit::val</span><span class="plain">(</span><span class="identifier">K_number</span><span class="plain">, </span><span class="identifier">LITERAL_IVAL</span><span class="plain">, (</span><span class="identifier">inter_t</span><span class="plain">) </span><span class="identifier">sc</span><span class="plain">-&gt;</span><span class="identifier">allocation_id</span><span class="plain">);</span>
<span class="identifier">Emit::up</span><span class="plain">();</span>
<span class="identifier">Emit::val</span><span class="plain">(</span><span class="identifier">K_number</span><span class="plain">, </span><span class="identifier">LITERAL_IVAL</span><span class="plain">, 0);</span>
<span class="identifier">Emit::up</span><span class="plain">();</span>
<span class="identifier">Emit::up</span><span class="plain">();</span>
<span class="identifier">Emit::code</span><span class="plain">();</span>
<span class="identifier">Emit::down</span><span class="plain">();</span>
<span class="identifier">Emit::inv_primitive</span><span class="plain">(</span><span class="identifier">store_interp</span><span class="plain">);</span>
<span class="identifier">Emit::down</span><span class="plain">();</span>
<span class="identifier">Emit::inv_primitive</span><span class="plain">(</span><span class="identifier">lookupref_interp</span><span class="plain">);</span>
<span class="identifier">Emit::down</span><span class="plain">();</span>
<span class="identifier">Emit::val_iname</span><span class="plain">(</span><span class="identifier">K_value</span><span class="plain">, </span><span class="identifier">Hierarchy::find</span><span class="plain">(</span><span class="identifier">SCENE_STATUS_HL</span><span class="plain">));</span>
<span class="identifier">Emit::val</span><span class="plain">(</span><span class="identifier">K_number</span><span class="plain">, </span><span class="identifier">LITERAL_IVAL</span><span class="plain">, (</span><span class="identifier">inter_t</span><span class="plain">) </span><span class="identifier">sc</span><span class="plain">-&gt;</span><span class="identifier">allocation_id</span><span class="plain">);</span>
<span class="identifier">Emit::up</span><span class="plain">();</span>
<span class="identifier">Emit::val</span><span class="plain">(</span><span class="identifier">K_number</span><span class="plain">, </span><span class="identifier">LITERAL_IVAL</span><span class="plain">, 2);</span>
<span class="identifier">Emit::up</span><span class="plain">();</span>
<span class="identifier">Emit::up</span><span class="plain">();</span>
<span class="identifier">Emit::up</span><span class="plain">();</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP28">&#167;28</a> (twice).</p>
<p class="inwebparagraph"><a id="SP28_2"></a><b>&#167;28.2. </b><code class="display">
&lt;<span class="cwebmacrodefn">Compile code to run the scene end rulebooks</span> <span class="cwebmacronumber">28.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">end</span><span class="plain"> == 0) {</span>
<span class="identifier">Emit::inv_call</span><span class="plain">(</span><span class="identifier">InterNames::to_symbol</span><span class="plain">(</span><span class="identifier">Hierarchy::find</span><span class="plain">(</span><span class="identifier">FOLLOWRULEBOOK_HL</span><span class="plain">)));</span>
<span class="identifier">Emit::down</span><span class="plain">();</span>
<span class="identifier">Emit::val_iname</span><span class="plain">(</span><span class="identifier">K_value</span><span class="plain">, </span><span class="identifier">Hierarchy::find</span><span class="plain">(</span><span class="identifier">WHEN_SCENE_BEGINS_HL</span><span class="plain">));</span>
<span class="identifier">Emit::val</span><span class="plain">(</span><span class="identifier">K_number</span><span class="plain">, </span><span class="identifier">LITERAL_IVAL</span><span class="plain">, (</span><span class="identifier">inter_t</span><span class="plain">) (</span><span class="identifier">sc</span><span class="plain">-&gt;</span><span class="identifier">allocation_id</span><span class="plain"> + 1));</span>
<span class="identifier">Emit::up</span><span class="plain">();</span>
<span class="plain">}</span>
<span class="identifier">Emit::inv_call</span><span class="plain">(</span><span class="identifier">InterNames::to_symbol</span><span class="plain">(</span><span class="identifier">Hierarchy::find</span><span class="plain">(</span><span class="identifier">FOLLOWRULEBOOK_HL</span><span class="plain">)));</span>
<span class="identifier">Emit::down</span><span class="plain">();</span>
<span class="identifier">Emit::val</span><span class="plain">(</span><span class="identifier">K_number</span><span class="plain">, </span><span class="identifier">LITERAL_IVAL</span><span class="plain">, (</span><span class="identifier">inter_t</span><span class="plain">) (</span><span class="identifier">sc</span><span class="plain">-</span><span class="element">&gt;end_rulebook</span><span class="plain">[</span><span class="identifier">end</span><span class="plain">]-&gt;</span><span class="identifier">allocation_id</span><span class="plain">));</span>
<span class="identifier">Emit::up</span><span class="plain">();</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">end</span><span class="plain"> == 1) {</span>
<span class="identifier">Emit::inv_call</span><span class="plain">(</span><span class="identifier">InterNames::to_symbol</span><span class="plain">(</span><span class="identifier">Hierarchy::find</span><span class="plain">(</span><span class="identifier">FOLLOWRULEBOOK_HL</span><span class="plain">)));</span>
<span class="identifier">Emit::down</span><span class="plain">();</span>
<span class="identifier">Emit::val_iname</span><span class="plain">(</span><span class="identifier">K_value</span><span class="plain">, </span><span class="identifier">Hierarchy::find</span><span class="plain">(</span><span class="identifier">WHEN_SCENE_ENDS_HL</span><span class="plain">));</span>
<span class="identifier">Emit::val</span><span class="plain">(</span><span class="identifier">K_number</span><span class="plain">, </span><span class="identifier">LITERAL_IVAL</span><span class="plain">, (</span><span class="identifier">inter_t</span><span class="plain">) (</span><span class="identifier">sc</span><span class="plain">-&gt;</span><span class="identifier">allocation_id</span><span class="plain"> + 1));</span>
<span class="identifier">Emit::up</span><span class="plain">();</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP28">&#167;28</a> (twice).</p>
<p class="inwebparagraph"><a id="SP28_3"></a><b>&#167;28.3. </b><code class="display">
&lt;<span class="cwebmacrodefn">Compile code to update the arrays recording most recent scene ending</span> <span class="cwebmacronumber">28.3</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">inter_name</span><span class="plain"> *</span><span class="identifier">sarr</span><span class="plain"> = </span><span class="identifier">Hierarchy::find</span><span class="plain">(</span><span class="identifier">SCENE_ENDED_HL</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">end</span><span class="plain"> == 0) </span><span class="identifier">sarr</span><span class="plain"> = </span><span class="identifier">Hierarchy::find</span><span class="plain">(</span><span class="identifier">SCENE_STARTED_HL</span><span class="plain">);</span>
<span class="identifier">Emit::inv_primitive</span><span class="plain">(</span><span class="identifier">store_interp</span><span class="plain">);</span>
<span class="identifier">Emit::down</span><span class="plain">();</span>
<span class="identifier">Emit::inv_primitive</span><span class="plain">(</span><span class="identifier">lookupref_interp</span><span class="plain">);</span>
<span class="identifier">Emit::down</span><span class="plain">();</span>
<span class="identifier">Emit::val_iname</span><span class="plain">(</span><span class="identifier">K_value</span><span class="plain">, </span><span class="identifier">sarr</span><span class="plain">);</span>
<span class="identifier">Emit::val</span><span class="plain">(</span><span class="identifier">K_number</span><span class="plain">, </span><span class="identifier">LITERAL_IVAL</span><span class="plain">, (</span><span class="identifier">inter_t</span><span class="plain">) </span><span class="identifier">sc</span><span class="plain">-&gt;</span><span class="identifier">allocation_id</span><span class="plain">);</span>
<span class="identifier">Emit::up</span><span class="plain">();</span>
<span class="identifier">Emit::val_iname</span><span class="plain">(</span><span class="identifier">K_number</span><span class="plain">, </span><span class="identifier">Hierarchy::find</span><span class="plain">(</span><span class="identifier">THE_TIME_HL</span><span class="plain">));</span>
<span class="identifier">Emit::up</span><span class="plain">();</span>
<span class="identifier">Emit::inv_primitive</span><span class="plain">(</span><span class="identifier">store_interp</span><span class="plain">);</span>
<span class="identifier">Emit::down</span><span class="plain">();</span>
<span class="identifier">Emit::inv_primitive</span><span class="plain">(</span><span class="identifier">lookupref_interp</span><span class="plain">);</span>
<span class="identifier">Emit::down</span><span class="plain">();</span>
<span class="identifier">Emit::val_iname</span><span class="plain">(</span><span class="identifier">K_value</span><span class="plain">, </span><span class="identifier">Hierarchy::find</span><span class="plain">(</span><span class="identifier">SCENE_ENDINGS_HL</span><span class="plain">));</span>
<span class="identifier">Emit::val</span><span class="plain">(</span><span class="identifier">K_number</span><span class="plain">, </span><span class="identifier">LITERAL_IVAL</span><span class="plain">, (</span><span class="identifier">inter_t</span><span class="plain">) </span><span class="identifier">sc</span><span class="plain">-&gt;</span><span class="identifier">allocation_id</span><span class="plain">);</span>
<span class="identifier">Emit::up</span><span class="plain">();</span>
<span class="identifier">Emit::inv_primitive</span><span class="plain">(</span><span class="identifier">bitwiseor_interp</span><span class="plain">);</span>
<span class="identifier">Emit::down</span><span class="plain">();</span>
<span class="identifier">Emit::inv_primitive</span><span class="plain">(</span><span class="identifier">lookup_interp</span><span class="plain">);</span>
<span class="identifier">Emit::down</span><span class="plain">();</span>
<span class="identifier">Emit::val_iname</span><span class="plain">(</span><span class="identifier">K_value</span><span class="plain">, </span><span class="identifier">Hierarchy::find</span><span class="plain">(</span><span class="identifier">SCENE_ENDINGS_HL</span><span class="plain">));</span>
<span class="identifier">Emit::val</span><span class="plain">(</span><span class="identifier">K_number</span><span class="plain">, </span><span class="identifier">LITERAL_IVAL</span><span class="plain">, (</span><span class="identifier">inter_t</span><span class="plain">) </span><span class="identifier">sc</span><span class="plain">-&gt;</span><span class="identifier">allocation_id</span><span class="plain">);</span>
<span class="identifier">Emit::up</span><span class="plain">();</span>
<span class="identifier">Emit::val</span><span class="plain">(</span><span class="identifier">K_number</span><span class="plain">, </span><span class="identifier">LITERAL_IVAL</span><span class="plain">, (</span><span class="identifier">inter_t</span><span class="plain">) (1 &lt;&lt; </span><span class="identifier">end</span><span class="plain">));</span>
<span class="identifier">Emit::up</span><span class="plain">();</span>
<span class="identifier">Emit::up</span><span class="plain">();</span>
<span class="identifier">Emit::inv_primitive</span><span class="plain">(</span><span class="identifier">store_interp</span><span class="plain">);</span>
<span class="identifier">Emit::down</span><span class="plain">();</span>
<span class="identifier">Emit::inv_primitive</span><span class="plain">(</span><span class="identifier">lookupref_interp</span><span class="plain">);</span>
<span class="identifier">Emit::down</span><span class="plain">();</span>
<span class="identifier">Emit::val_iname</span><span class="plain">(</span><span class="identifier">K_value</span><span class="plain">, </span><span class="identifier">Hierarchy::find</span><span class="plain">(</span><span class="identifier">SCENE_LATEST_ENDING_HL</span><span class="plain">));</span>
<span class="identifier">Emit::val</span><span class="plain">(</span><span class="identifier">K_number</span><span class="plain">, </span><span class="identifier">LITERAL_IVAL</span><span class="plain">, (</span><span class="identifier">inter_t</span><span class="plain">) </span><span class="identifier">sc</span><span class="plain">-&gt;</span><span class="identifier">allocation_id</span><span class="plain">);</span>
<span class="identifier">Emit::up</span><span class="plain">();</span>
<span class="identifier">Emit::val</span><span class="plain">(</span><span class="identifier">K_value</span><span class="plain">, </span><span class="identifier">LITERAL_IVAL</span><span class="plain">, (</span><span class="identifier">inter_t</span><span class="plain">) </span><span class="identifier">end</span><span class="plain">);</span>
<span class="identifier">Emit::up</span><span class="plain">();</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP28">&#167;28</a> (twice).</p>
<p class="inwebparagraph"><a id="SP28_4"></a><b>&#167;28.4. </b><code class="display">
&lt;<span class="cwebmacrodefn">Compile code to print text in response to the SCENES command</span> <span class="cwebmacronumber">28.4</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">Emit::inv_primitive</span><span class="plain">(</span><span class="identifier">if_interp</span><span class="plain">);</span>
<span class="identifier">Emit::down</span><span class="plain">();</span>
<span class="identifier">Emit::val_iname</span><span class="plain">(</span><span class="identifier">K_value</span><span class="plain">, </span><span class="identifier">Hierarchy::find</span><span class="plain">(</span><span class="identifier">DEBUG_SCENES_HL</span><span class="plain">));</span>
<span class="identifier">Emit::code</span><span class="plain">();</span>
<span class="identifier">Emit::down</span><span class="plain">();</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"[Scene '"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">sc</span><span class="plain">-</span><span class="element">&gt;as_instance</span><span class="plain">) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"%+W"</span><span class="plain">, </span><span class="identifier">Instances::get_name</span><span class="plain">(</span><span class="identifier">sc</span><span class="plain">-</span><span class="element">&gt;as_instance</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">));</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"' "</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">end</span><span class="plain"> == 0) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"begins"</span><span class="plain">); </span><span class="reserved">else</span><span class="plain"> </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"ends"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">end</span><span class="plain"> &gt;= 2) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">" %+W"</span><span class="plain">, </span><span class="identifier">sc</span><span class="plain">-</span><span class="element">&gt;end_names</span><span class="plain">[</span><span class="identifier">end</span><span class="plain">]);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"]\</span><span class="plain">n</span><span class="string">"</span><span class="plain">);</span>
<span class="identifier">Emit::inv_primitive</span><span class="plain">(</span><span class="identifier">print_interp</span><span class="plain">);</span>
<span class="identifier">Emit::down</span><span class="plain">();</span>
<span class="identifier">Emit::val_text</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">);</span>
<span class="identifier">Emit::up</span><span class="plain">();</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">);</span>
<span class="identifier">Emit::up</span><span class="plain">();</span>
<span class="identifier">Emit::up</span><span class="plain">();</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP28">&#167;28</a> (twice).</p>
<p class="inwebparagraph"><a id="SP28_5"></a><b>&#167;28.5. </b>In general, the marker count is used to ensure that <code class="display"><span class="extract">PL::Scenes::compile_scene_end_dash</span></code>
never calls itself for a scene it has been called with before on this round.
This prevents Inform locking up generating infinite amounts of code. However,
one exception is allowed, in very limited circumstances. Suppose we want to
make a scene recur, but only if it ends in a particular way. Then we might
type:
</p>
<blockquote>
<p>Brisk Quadrille begins when Brisk Quadrille ends untidily.</p>
</blockquote>
<p class="inwebparagraph">This is allowed; it's a case where the "tolerance" below is raised.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Compile code to cause consequent scene ends</span> <span class="cwebmacronumber">28.5</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">scene</span><span class="plain"> *</span><span class="identifier">other_scene</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">other_scene</span><span class="plain">, </span><span class="reserved">scene</span><span class="plain">) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">tolerance</span><span class="plain"> = 1;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">sc</span><span class="plain"> == </span><span class="identifier">other_scene</span><span class="plain">) </span><span class="identifier">tolerance</span><span class="plain"> = </span><span class="identifier">sc</span><span class="plain">-</span><span class="element">&gt;no_ends</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">other_scene</span><span class="plain">-</span><span class="element">&gt;marker</span><span class="plain"> &lt; </span><span class="identifier">tolerance</span><span class="plain">) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">other_end</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">other_end</span><span class="plain"> = 0; </span><span class="identifier">other_end</span><span class="plain"> &lt; </span><span class="identifier">other_scene</span><span class="plain">-</span><span class="element">&gt;no_ends</span><span class="plain">; </span><span class="identifier">other_end</span><span class="plain">++) {</span>
<span class="reserved">scene_connector</span><span class="plain"> *</span><span class="identifier">scon</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">scon</span><span class="plain"> = </span><span class="identifier">other_scene</span><span class="plain">-</span><span class="element">&gt;anchor_scene</span><span class="plain">[</span><span class="identifier">other_end</span><span class="plain">]; </span><span class="identifier">scon</span><span class="plain">; </span><span class="identifier">scon</span><span class="plain"> = </span><span class="identifier">scon</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">scon</span><span class="plain">-</span><span class="element">&gt;connect_to</span><span class="plain"> == </span><span class="identifier">sc</span><span class="plain">) &amp;&amp; (</span><span class="identifier">scon</span><span class="plain">-</span><span class="element">&gt;end</span><span class="plain"> == </span><span class="identifier">end</span><span class="plain">)) {</span>
<span class="identifier">Emit::inv_primitive</span><span class="plain">(</span><span class="identifier">if_interp</span><span class="plain">);</span>
<span class="identifier">Emit::down</span><span class="plain">();</span>
<span class="identifier">Emit::inv_primitive</span><span class="plain">(</span><span class="identifier">eq_interp</span><span class="plain">);</span>
<span class="identifier">Emit::down</span><span class="plain">();</span>
<span class="identifier">Emit::inv_primitive</span><span class="plain">(</span><span class="identifier">lookup_interp</span><span class="plain">);</span>
<span class="identifier">Emit::down</span><span class="plain">();</span>
<span class="identifier">Emit::val_iname</span><span class="plain">(</span><span class="identifier">K_value</span><span class="plain">, </span><span class="identifier">Hierarchy::find</span><span class="plain">(</span><span class="identifier">SCENE_STATUS_HL</span><span class="plain">));</span>
<span class="identifier">Emit::val</span><span class="plain">(</span><span class="identifier">K_number</span><span class="plain">, </span><span class="identifier">LITERAL_IVAL</span><span class="plain">, (</span><span class="identifier">inter_t</span><span class="plain">) </span><span class="identifier">other_scene</span><span class="plain">-&gt;</span><span class="identifier">allocation_id</span><span class="plain">);</span>
<span class="identifier">Emit::up</span><span class="plain">();</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">other_end</span><span class="plain"> &gt;= 1)</span>
<span class="identifier">Emit::val</span><span class="plain">(</span><span class="identifier">K_number</span><span class="plain">, </span><span class="identifier">LITERAL_IVAL</span><span class="plain">, 1);</span>
<span class="reserved">else</span>
<span class="identifier">Emit::val</span><span class="plain">(</span><span class="identifier">K_number</span><span class="plain">, </span><span class="identifier">LITERAL_IVAL</span><span class="plain">, 0);</span>
<span class="identifier">Emit::up</span><span class="plain">();</span>
<span class="identifier">Emit::code</span><span class="plain">();</span>
<span class="identifier">Emit::down</span><span class="plain">();</span>
<span class="functiontext">PL::Scenes::compile_scene_end_dash</span><span class="plain">(</span><span class="identifier">other_scene</span><span class="plain">, </span><span class="identifier">other_end</span><span class="plain">);</span>
<span class="identifier">Emit::up</span><span class="plain">();</span>
<span class="identifier">Emit::up</span><span class="plain">();</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP28">&#167;28</a> (twice).</p>
<p class="inwebparagraph"><a id="SP29"></a><b>&#167;29. More SCENES output. </b>As we've seen, when the SCENES command has been typed, Inform prints a notice
out at run-time when any scene end occurs. It also prints a run-down of the
scene status at the moment the command is typed, and the following code is
what handles this.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">PL::Scenes::ShowSceneStatus_routine</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="identifier">packaging_state</span><span class="plain"> </span><span class="identifier">save</span><span class="plain"> = </span><span class="identifier">Routines::begin</span><span class="plain">(</span><span class="identifier">Hierarchy::find</span><span class="plain">(</span><span class="identifier">SHOWSCENESTATUS_HL</span><span class="plain">));</span>
<span class="identifier">Emit::inv_primitive</span><span class="plain">(</span><span class="identifier">ifdebug_interp</span><span class="plain">);</span>
<span class="identifier">Emit::down</span><span class="plain">();</span>
<span class="identifier">Emit::code</span><span class="plain">();</span>
<span class="identifier">Emit::down</span><span class="plain">();</span>
<span class="reserved">scene</span><span class="plain"> *</span><span class="identifier">sc</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">sc</span><span class="plain">, </span><span class="reserved">scene</span><span class="plain">) {</span>
<span class="identifier">wording</span><span class="plain"> </span><span class="identifier">NW</span><span class="plain"> = </span><span class="identifier">Instances::get_name</span><span class="plain">(</span><span class="identifier">sc</span><span class="plain">-</span><span class="element">&gt;as_instance</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">);</span>
<span class="identifier">Emit::inv_primitive</span><span class="plain">(</span><span class="identifier">ifelse_interp</span><span class="plain">);</span>
<span class="identifier">Emit::down</span><span class="plain">();</span>
<span class="identifier">Emit::inv_primitive</span><span class="plain">(</span><span class="identifier">eq_interp</span><span class="plain">);</span>
<span class="identifier">Emit::down</span><span class="plain">();</span>
<span class="identifier">Emit::inv_primitive</span><span class="plain">(</span><span class="identifier">lookup_interp</span><span class="plain">);</span>
<span class="identifier">Emit::down</span><span class="plain">();</span>
<span class="identifier">Emit::val_iname</span><span class="plain">(</span><span class="identifier">K_object</span><span class="plain">, </span><span class="identifier">Hierarchy::find</span><span class="plain">(</span><span class="identifier">SCENE_STATUS_HL</span><span class="plain">));</span>
<span class="identifier">Emit::val</span><span class="plain">(</span><span class="identifier">K_number</span><span class="plain">, </span><span class="identifier">LITERAL_IVAL</span><span class="plain">, (</span><span class="identifier">inter_t</span><span class="plain">) </span><span class="identifier">sc</span><span class="plain">-&gt;</span><span class="identifier">allocation_id</span><span class="plain">);</span>
<span class="identifier">Emit::up</span><span class="plain">();</span>
<span class="identifier">Emit::val</span><span class="plain">(</span><span class="identifier">K_number</span><span class="plain">, </span><span class="identifier">LITERAL_IVAL</span><span class="plain">, 1);</span>
<span class="identifier">Emit::up</span><span class="plain">();</span>
<span class="identifier">Emit::code</span><span class="plain">();</span>
<span class="identifier">Emit::down</span><span class="plain">();</span>
&lt;<span class="cwebmacro">Show status of this running scene</span> <span class="cwebmacronumber">29.1</span>&gt;<span class="plain">;</span>
<span class="identifier">Emit::up</span><span class="plain">();</span>
<span class="identifier">Emit::code</span><span class="plain">();</span>
<span class="identifier">Emit::down</span><span class="plain">();</span>
&lt;<span class="cwebmacro">Show status of this non-running scene</span> <span class="cwebmacronumber">29.2</span>&gt;<span class="plain">;</span>
<span class="identifier">Emit::up</span><span class="plain">();</span>
<span class="identifier">Emit::up</span><span class="plain">();</span>
<span class="plain">}</span>
<span class="identifier">Emit::up</span><span class="plain">();</span>
<span class="identifier">Emit::up</span><span class="plain">();</span>
<span class="identifier">Routines::end</span><span class="plain">(</span><span class="identifier">save</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function PL::Scenes::ShowSceneStatus_routine appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP29_1"></a><b>&#167;29.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Show status of this running scene</span> <span class="cwebmacronumber">29.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">);</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="string">"Scene '%+W' playing (for "</span><span class="plain">, </span><span class="identifier">NW</span><span class="plain">);</span>
<span class="identifier">Emit::inv_primitive</span><span class="plain">(</span><span class="identifier">print_interp</span><span class="plain">);</span>
<span class="identifier">Emit::down</span><span class="plain">();</span>
<span class="identifier">Emit::val_text</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">);</span>
<span class="identifier">Emit::up</span><span class="plain">();</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">);</span>
<span class="identifier">Emit::inv_primitive</span><span class="plain">(</span><span class="identifier">printnumber_interp</span><span class="plain">);</span>
<span class="identifier">Emit::down</span><span class="plain">();</span>
<span class="identifier">Emit::inv_primitive</span><span class="plain">(</span><span class="identifier">minus_interp</span><span class="plain">);</span>
<span class="identifier">Emit::down</span><span class="plain">();</span>
<span class="identifier">Emit::val_iname</span><span class="plain">(</span><span class="identifier">K_number</span><span class="plain">, </span><span class="identifier">Hierarchy::find</span><span class="plain">(</span><span class="identifier">THE_TIME_HL</span><span class="plain">));</span>
<span class="identifier">Emit::inv_primitive</span><span class="plain">(</span><span class="identifier">lookup_interp</span><span class="plain">);</span>
<span class="identifier">Emit::down</span><span class="plain">();</span>
<span class="identifier">Emit::val_iname</span><span class="plain">(</span><span class="identifier">K_object</span><span class="plain">, </span><span class="identifier">Hierarchy::find</span><span class="plain">(</span><span class="identifier">SCENE_STARTED_HL</span><span class="plain">));</span>
<span class="identifier">Emit::val</span><span class="plain">(</span><span class="identifier">K_number</span><span class="plain">, </span><span class="identifier">LITERAL_IVAL</span><span class="plain">, (</span><span class="identifier">inter_t</span><span class="plain">) </span><span class="identifier">sc</span><span class="plain">-&gt;</span><span class="identifier">allocation_id</span><span class="plain">);</span>
<span class="identifier">Emit::up</span><span class="plain">();</span>
<span class="identifier">Emit::up</span><span class="plain">();</span>
<span class="identifier">Emit::up</span><span class="plain">();</span>
<span class="identifier">Emit::inv_primitive</span><span class="plain">(</span><span class="identifier">print_interp</span><span class="plain">);</span>
<span class="identifier">Emit::down</span><span class="plain">();</span>
<span class="identifier">Emit::val_text</span><span class="plain">(</span><span class="identifier">I</span><span class="string">" mins now)\</span><span class="plain">n</span><span class="string">"</span><span class="plain">);</span>
<span class="identifier">Emit::up</span><span class="plain">();</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP29">&#167;29</a>.</p>
<p class="inwebparagraph"><a id="SP29_2"></a><b>&#167;29.2. </b><code class="display">
&lt;<span class="cwebmacrodefn">Show status of this non-running scene</span> <span class="cwebmacronumber">29.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">Emit::inv_primitive</span><span class="plain">(</span><span class="identifier">if_interp</span><span class="plain">);</span>
<span class="identifier">Emit::down</span><span class="plain">();</span>
<span class="identifier">Emit::inv_primitive</span><span class="plain">(</span><span class="identifier">gt_interp</span><span class="plain">);</span>
<span class="identifier">Emit::down</span><span class="plain">();</span>
<span class="identifier">Emit::inv_primitive</span><span class="plain">(</span><span class="identifier">lookup_interp</span><span class="plain">);</span>
<span class="identifier">Emit::down</span><span class="plain">();</span>
<span class="identifier">Emit::val_iname</span><span class="plain">(</span><span class="identifier">K_object</span><span class="plain">, </span><span class="identifier">Hierarchy::find</span><span class="plain">(</span><span class="identifier">SCENE_LATEST_ENDING_HL</span><span class="plain">));</span>
<span class="identifier">Emit::val</span><span class="plain">(</span><span class="identifier">K_number</span><span class="plain">, </span><span class="identifier">LITERAL_IVAL</span><span class="plain">, (</span><span class="identifier">inter_t</span><span class="plain">) </span><span class="identifier">sc</span><span class="plain">-&gt;</span><span class="identifier">allocation_id</span><span class="plain">);</span>
<span class="identifier">Emit::up</span><span class="plain">();</span>
<span class="identifier">Emit::val</span><span class="plain">(</span><span class="identifier">K_number</span><span class="plain">, </span><span class="identifier">LITERAL_IVAL</span><span class="plain">, 0);</span>
<span class="identifier">Emit::up</span><span class="plain">();</span>
<span class="identifier">Emit::code</span><span class="plain">();</span>
<span class="identifier">Emit::down</span><span class="plain">();</span>
&lt;<span class="cwebmacro">Show status of this recently ended scene</span> <span class="cwebmacronumber">29.2.1</span>&gt;<span class="plain">;</span>
<span class="identifier">Emit::up</span><span class="plain">();</span>
<span class="identifier">Emit::up</span><span class="plain">();</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP29">&#167;29</a>.</p>
<p class="inwebparagraph"><a id="SP29_2_1"></a><b>&#167;29.2.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Show status of this recently ended scene</span> <span class="cwebmacronumber">29.2.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">);</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="string">"Scene '%+W' ended"</span><span class="plain">, </span><span class="identifier">NW</span><span class="plain">);</span>
<span class="identifier">Emit::inv_primitive</span><span class="plain">(</span><span class="identifier">print_interp</span><span class="plain">);</span>
<span class="identifier">Emit::down</span><span class="plain">();</span>
<span class="identifier">Emit::val_text</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">);</span>
<span class="identifier">Emit::up</span><span class="plain">();</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">sc</span><span class="plain">-</span><span class="element">&gt;no_ends</span><span class="plain"> &gt; 2) {</span>
<span class="identifier">Emit::inv_primitive</span><span class="plain">(</span><span class="identifier">switch_interp</span><span class="plain">);</span>
<span class="identifier">Emit::down</span><span class="plain">();</span>
<span class="identifier">Emit::inv_primitive</span><span class="plain">(</span><span class="identifier">lookup_interp</span><span class="plain">);</span>
<span class="identifier">Emit::down</span><span class="plain">();</span>
<span class="identifier">Emit::val_iname</span><span class="plain">(</span><span class="identifier">K_object</span><span class="plain">, </span><span class="identifier">Hierarchy::find</span><span class="plain">(</span><span class="identifier">SCENE_LATEST_ENDING_HL</span><span class="plain">));</span>
<span class="identifier">Emit::val</span><span class="plain">(</span><span class="identifier">K_number</span><span class="plain">, </span><span class="identifier">LITERAL_IVAL</span><span class="plain">, (</span><span class="identifier">inter_t</span><span class="plain">) </span><span class="identifier">sc</span><span class="plain">-&gt;</span><span class="identifier">allocation_id</span><span class="plain">);</span>
<span class="identifier">Emit::up</span><span class="plain">();</span>
<span class="identifier">Emit::code</span><span class="plain">();</span>
<span class="identifier">Emit::down</span><span class="plain">();</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">end</span><span class="plain">=2; </span><span class="identifier">end</span><span class="plain">&lt;</span><span class="identifier">sc</span><span class="plain">-</span><span class="element">&gt;no_ends</span><span class="plain">; </span><span class="identifier">end</span><span class="plain">++) {</span>
<span class="identifier">Emit::inv_primitive</span><span class="plain">(</span><span class="identifier">case_interp</span><span class="plain">);</span>
<span class="identifier">Emit::down</span><span class="plain">();</span>
<span class="identifier">Emit::val</span><span class="plain">(</span><span class="identifier">K_number</span><span class="plain">, </span><span class="identifier">LITERAL_IVAL</span><span class="plain">, (</span><span class="identifier">inter_t</span><span class="plain">) </span><span class="identifier">end</span><span class="plain">);</span>
<span class="identifier">Emit::code</span><span class="plain">();</span>
<span class="identifier">Emit::down</span><span class="plain">();</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">);</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="string">" %+W"</span><span class="plain">, </span><span class="identifier">sc</span><span class="plain">-</span><span class="element">&gt;end_names</span><span class="plain">[</span><span class="identifier">end</span><span class="plain">]);</span>
<span class="identifier">Emit::inv_primitive</span><span class="plain">(</span><span class="identifier">print_interp</span><span class="plain">);</span>
<span class="identifier">Emit::down</span><span class="plain">();</span>
<span class="identifier">Emit::val_text</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">);</span>
<span class="identifier">Emit::up</span><span class="plain">();</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">);</span>
<span class="identifier">Emit::up</span><span class="plain">();</span>
<span class="identifier">Emit::up</span><span class="plain">();</span>
<span class="plain">}</span>
<span class="identifier">Emit::up</span><span class="plain">();</span>
<span class="identifier">Emit::up</span><span class="plain">();</span>
<span class="plain">}</span>
<span class="identifier">Emit::inv_primitive</span><span class="plain">(</span><span class="identifier">print_interp</span><span class="plain">);</span>
<span class="identifier">Emit::down</span><span class="plain">();</span>
<span class="identifier">Emit::val_text</span><span class="plain">(</span><span class="identifier">I</span><span class="string">"\</span><span class="plain">n</span><span class="string">"</span><span class="plain">);</span>
<span class="identifier">Emit::up</span><span class="plain">();</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP29_2">&#167;29.2</a>.</p>
<p class="inwebparagraph"><a id="SP30"></a><b>&#167;30. During clauses. </b>We've now seen one use of scenes: they kick off rulebooks when they begin or
end. The other use for them is to predicate rules on whether they are currently
playing or not, using a "during" clause.
</p>
<p class="inwebparagraph">We allow these either to name a specific scene, or to describe a collection
of them:
</p>
<pre class="display">
<span class="plain">&lt;</span><span class="identifier">s</span><span class="plain">-</span><span class="reserved">scene</span><span class="plain">-</span><span class="identifier">description</span><span class="plain">&gt; ::=</span>
<span class="plain">&lt;</span><span class="identifier">s</span><span class="plain">-</span><span class="identifier">value</span><span class="plain">&gt; ==&gt; </span>&lt;<span class="cwebmacro">Filter to force this to be a scene description</span> <span class="cwebmacronumber">30.1</span>&gt;
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP30_1"></a><b>&#167;30.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Filter to force this to be a scene description</span> <span class="cwebmacronumber">30.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">K_scene</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">spec</span><span class="plain"> = </span><span class="identifier">RP</span><span class="plain">[1];</span>
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">I</span><span class="plain"> = </span><span class="identifier">Rvalues::to_instance</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (((</span><span class="identifier">I</span><span class="plain">) &amp;&amp; (</span><span class="identifier">Instances::of_kind</span><span class="plain">(</span><span class="identifier">I</span><span class="plain">, </span><span class="identifier">K_scene</span><span class="plain">))) ||</span>
<span class="plain">((</span><span class="identifier">Specifications::is_description</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">)) &amp;&amp;</span>
<span class="plain">(</span><span class="identifier">Kinds::Compare::eq</span><span class="plain">(</span><span class="identifier">Specifications::to_kind</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">), </span><span class="identifier">K_scene</span><span class="plain">)))) {</span>
<span class="plain">*</span><span class="identifier">XP</span><span class="plain"> = </span><span class="identifier">spec</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP30">&#167;30</a>.</p>
<p class="inwebparagraph"><a id="SP31"></a><b>&#167;31. </b>And this is where we compile I6 code to test that a scene matching this is
actually running:
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">PL::Scenes::emit_during_clause</span><span class="plain">(</span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">spec</span><span class="plain">) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">stuck</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">K_scene</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) { </span><span class="identifier">Emit::val</span><span class="plain">(</span><span class="identifier">K_truth_state</span><span class="plain">, </span><span class="identifier">LITERAL_IVAL</span><span class="plain">, 1); </span><span class="reserved">return</span><span class="plain">; }</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ParseTreeUsage::is_rvalue</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">)) {</span>
<span class="identifier">Dash::check_value</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">, </span><span class="identifier">K_scene</span><span class="plain">);</span>
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">I</span><span class="plain"> = </span><span class="identifier">Rvalues::to_instance</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Instances::of_kind</span><span class="plain">(</span><span class="identifier">I</span><span class="plain">, </span><span class="identifier">K_scene</span><span class="plain">)) {</span>
<span class="reserved">scene</span><span class="plain"> *</span><span class="identifier">sc</span><span class="plain"> = </span><span class="functiontext">PL::Scenes::from_named_constant</span><span class="plain">(</span><span class="identifier">I</span><span class="plain">);</span>
<span class="identifier">Emit::inv_primitive</span><span class="plain">(</span><span class="identifier">eq_interp</span><span class="plain">);</span>
<span class="identifier">Emit::down</span><span class="plain">();</span>
<span class="identifier">Emit::inv_primitive</span><span class="plain">(</span><span class="identifier">lookup_interp</span><span class="plain">);</span>
<span class="identifier">Emit::down</span><span class="plain">();</span>
<span class="identifier">Emit::val_iname</span><span class="plain">(</span><span class="identifier">K_value</span><span class="plain">, </span><span class="identifier">Hierarchy::find</span><span class="plain">(</span><span class="identifier">SCENE_STATUS_HL</span><span class="plain">));</span>
<span class="identifier">Emit::val</span><span class="plain">(</span><span class="identifier">K_number</span><span class="plain">, </span><span class="identifier">LITERAL_IVAL</span><span class="plain">, (</span><span class="identifier">inter_t</span><span class="plain">) </span><span class="identifier">sc</span><span class="plain">-&gt;</span><span class="identifier">allocation_id</span><span class="plain">);</span>
<span class="identifier">Emit::up</span><span class="plain">();</span>
<span class="identifier">Emit::val</span><span class="plain">(</span><span class="identifier">K_number</span><span class="plain">, </span><span class="identifier">LITERAL_IVAL</span><span class="plain">, 1);</span>
<span class="identifier">Emit::up</span><span class="plain">();</span>
<span class="identifier">stuck</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Dash::check_value</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">, </span><span class="identifier">Kinds::unary_construction</span><span class="plain">(</span><span class="identifier">CON_description</span><span class="plain">, </span><span class="identifier">K_scene</span><span class="plain">)) == </span><span class="identifier">ALWAYS_MATCH</span><span class="plain">) {</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">desc</span><span class="plain"> = </span><span class="identifier">Descriptions::to_rvalue</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">desc</span><span class="plain">) {</span>
<span class="identifier">Emit::inv_call</span><span class="plain">(</span><span class="identifier">InterNames::to_symbol</span><span class="plain">(</span><span class="identifier">Hierarchy::find</span><span class="plain">(</span><span class="identifier">DURINGSCENEMATCHING_HL</span><span class="plain">)));</span>
<span class="identifier">Emit::down</span><span class="plain">();</span>
<span class="identifier">Specifications::Compiler::emit_as_val</span><span class="plain">(</span><span class="identifier">K_value</span><span class="plain">, </span><span class="identifier">desc</span><span class="plain">);</span>
<span class="identifier">Emit::up</span><span class="plain">();</span>
<span class="identifier">stuck</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">stuck</span><span class="plain">) {</span>
<span class="identifier">Emit::val</span><span class="plain">(</span><span class="identifier">K_truth_state</span><span class="plain">, </span><span class="identifier">LITERAL_IVAL</span><span class="plain">, 1);</span>
<span class="identifier">Problems::Issue::sentence_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_ScenesBadDuring</span><span class="plain">),</span>
<span class="string">"'during' must be followed by the name of a scene or of a "</span>
<span class="string">"description which applies to a single scene"</span><span class="plain">,</span>
<span class="string">"such as 'during Station Arrival' or 'during a recurring scene'."</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function PL::Scenes::emit_during_clause appears nowhere else.</p>
<hr class="tocbar">
<ul class="toc"><li><a href="3-sc.html">Back to 'Showme Command'</a></li><li><a href="3-tm2.html">Continue with 'Temporal Map'</a></li></ul><hr class="tocbar">
<!--End of weave-->
</body>
</html>