mirror of
https://github.com/ganelson/inform.git
synced 2024-07-08 18:14:21 +03:00
923 lines
51 KiB
HTML
923 lines
51 KiB
HTML
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
|
<html>
|
|
<head>
|
|
<title>S/tt2</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 'S/wt' generated by 7-->
|
|
<ul class="crumbs"><li><a href="../webs.html">★</a></li><li><a href="index.html">standard_rules Template Library</a></li><li><b>WorldModel Template</b></li></ul><p class="purpose">Testing and changing the fundamental spatial relations.</p>
|
|
|
|
<ul class="toc"><li><a href="#SP1">§1. The Core Tree</a></li><li><a href="#SP2">§2. Climbing the Core Tree</a></li><li><a href="#SP3">§3. To Decide Whether In</a></li><li><a href="#SP4">§4. Containment Relation</a></li><li><a href="#SP5">§5. Support Relation</a></li><li><a href="#SP6">§6. Carrying Relation</a></li><li><a href="#SP7">§7. Wearing Relation</a></li><li><a href="#SP8">§8. Having Relation</a></li><li><a href="#SP9">§9. Making Parts</a></li><li><a href="#SP10">§10. Movements</a></li><li><a href="#SP11">§11. On Stage</a></li><li><a href="#SP12">§12. Moving the Player</a></li><li><a href="#SP13">§13. Move During Going</a></li><li><a href="#SP14">§14. Being Everywhere</a></li><li><a href="#SP15">§15. Testing Everywhere</a></li><li><a href="#SP16">§16. Changing the Player</a></li><li><a href="#SP17">§17. Floating Objects</a></li><li><a href="#SP18">§18. Backdrop Location</a></li><li><a href="#SP19">§19. Wearing Clothes</a></li><li><a href="#SP20">§20. Map Connections</a></li><li><a href="#SP21">§21. Adjacency Relation</a></li><li><a href="#SP22">§22. Regional Containment Relation</a></li><li><a href="#SP23">§23. Doors</a></li><li><a href="#SP24">§24. Visibility Relation</a></li><li><a href="#SP25">§25. Touchability Relation</a></li><li><a href="#SP26">§26. Concealment Relation</a></li></ul><hr class="tocbar">
|
|
|
|
<p class="inwebparagraph"><a id="SP1"></a><b>§1. The Core Tree. </b>Whereas I6 traditionally has a simple object tree hierarchy for containment,
|
|
support, carrying and so on, the I7 template also uses the <code class="display"><span class="extract">component_*</span></code>
|
|
properties to provide a second tree which defines the "part of" relation.
|
|
These two trees interact in a subtle way, and it took a very long time to
|
|
work out the simplest way to express this.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">The core of an object is the root of its subtree in the component
|
|
relation tree. So for a television set with a control panel which has a
|
|
button on, the core for the button (and also for the panel and the set)
|
|
will be the set. When X is a part of Y, it must be spatially in the same
|
|
position as Y, and so the spatial location of X is determined by the position
|
|
in the object tree of its core. (In effect, the spatial situation can be
|
|
found by contracting together all nodes corresponding to objects which are
|
|
parts of each other, but it would waste memory to construct such a tree:
|
|
<code class="display"><span class="extract">CoreOfParentOfCoreOf</span></code> simulates what the <code class="display"><span class="extract">parent</span></code> operation would be in
|
|
such a tree if it existed, wasting a little time instead.)
|
|
</p>
|
|
|
|
<p class="inwebparagraph">The holder of an object is its component parent, if it is part of
|
|
something, or its object-tree parent if it has one. It is illegal for both
|
|
of these to be non-<code class="display"><span class="extract">nothing</span></code>, so this is unambiguous.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">It is just possible for <code class="display"><span class="extract">HolderOf</span></code> to be called before the player has been
|
|
placed into the model world, in cases where Inform is checking a past tense
|
|
condition in the opening pre-turn. We don't want to return <code class="display"><span class="extract">nothing</span></code> then
|
|
because that would make it true that
|
|
</p>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">HolderOf(player) == ContainerOf(player)</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph">and similar conditions — thus, it would appear that in the immediate past
|
|
the player had been on the holder of the player, which is not in fact the
|
|
case. So we return <code class="display"><span class="extract">thedark</span></code> as a typesafe but impossible value here.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">[ HolderOf o;</span>
|
|
<span class="plain">if (InitialSituation-->DONE_INIS == false) return thedark;</span>
|
|
<span class="plain">if (o && (o.component_parent)) return o.component_parent;</span>
|
|
<span class="plain">if (o && (parent(o))) return parent(o);</span>
|
|
<span class="plain">return nothing;</span>
|
|
<span class="plain">];</span>
|
|
|
|
<span class="plain">[ ParentOf o;</span>
|
|
<span class="plain">if (o) o = parent(o);</span>
|
|
<span class="plain">return o;</span>
|
|
<span class="plain">];</span>
|
|
|
|
<span class="plain">[ CoreOf o;</span>
|
|
<span class="plain">while (o && (o provides component_parent) && (o.component_parent)) o = o.component_parent;</span>
|
|
<span class="plain">return o;</span>
|
|
<span class="plain">];</span>
|
|
|
|
<span class="plain">[ CoreOfParentOfCoreOf o;</span>
|
|
<span class="plain">while (o && (o provides component_parent) && (o.component_parent)) o = o.component_parent;</span>
|
|
<span class="plain">if (o) o = parent(o);</span>
|
|
<span class="plain">while (o && (o provides component_parent) && (o.component_parent)) o = o.component_parent;</span>
|
|
<span class="plain">return o;</span>
|
|
<span class="plain">];</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP2"></a><b>§2. Climbing the Core Tree. </b><code class="display"><span class="extract">LocationOf</span></code> returns the room in which an object can be found, or <code class="display"><span class="extract">nothing</span></code>
|
|
if it is out of play. Directions and regions are always out of play. Doors
|
|
and backdrops can be in multiple places: if they are in the current location,
|
|
then that's the answer; otherwise a two-sided door is in its "front side",
|
|
and a backdrop in the earliest declared room which it's currently in.
|
|
For a room, <code class="display"><span class="extract">LocationOf</span></code> is necessarily itself.
|
|
</p>
|
|
|
|
<p class="inwebparagraph"><code class="display"><span class="extract">CommonAncestor</span></code> finds the nearest object indirectly containing <code class="display"><span class="extract">o1</span></code> and
|
|
<code class="display"><span class="extract">o2</span></code>, or returns <code class="display"><span class="extract">nothing</span></code> if there is no common ancestor. (This is a port
|
|
of <code class="display"><span class="extract">CommonAncestor</span></code> from the I6 library, adapted to work on the core tree.)
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">[ LocationOf o;</span>
|
|
<span class="plain">if (~~(o ofclass K1_room or K2_thing)) return nothing;</span>
|
|
<span class="plain">if (o ofclass K4_door) {</span>
|
|
<span class="plain">if (parent(o) == real_location) return real_location;</span>
|
|
<span class="plain">return FrontSideOfDoor(o);</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">if (o ofclass K7_backdrop) {</span>
|
|
<span class="plain">! print "(deciding ", (the) O, " is at ", (the) BackdropLocation(o), ") ";</span>
|
|
<span class="plain">return BackdropLocation(o);</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">while (o) {</span>
|
|
<span class="plain">if (o ofclass K1_room) return o;</span>
|
|
<span class="plain">o = CoreOfParentOfCoreOf(o);</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">return nothing;</span>
|
|
<span class="plain">];</span>
|
|
|
|
<span class="plain">[ CommonAncestor o1 o2 i j;</span>
|
|
<span class="plain">o1 = CoreOf(o1);</span>
|
|
<span class="plain">o2 = CoreOf(o2);</span>
|
|
|
|
<span class="plain">for (i=o1: i: i = CoreOfParentOfCoreOf(i))</span>
|
|
<span class="plain">for (j=o2: j: j = CoreOfParentOfCoreOf(j))</span>
|
|
<span class="plain">if (j == i) return j;</span>
|
|
|
|
<span class="plain">return nothing;</span>
|
|
<span class="plain">];</span>
|
|
|
|
<span class="plain">[ IndirectlyContains o1 o2;</span>
|
|
<span class="plain">if ((o1 == nothing) || (o2 == nothing)) rfalse;</span>
|
|
<span class="plain">if ((o1 ofclass K1_room) && (o2 ofclass K4_door)) {</span>
|
|
<span class="plain">if (o1 == FrontSideOfDoor(o2)) rtrue;</span>
|
|
<span class="plain">if (o1 == BackSideOfDoor(o2)) rtrue;</span>
|
|
<span class="plain">rfalse;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">if (o2 ofclass K7_backdrop) rfalse;</span>
|
|
<span class="plain">for (o2 = HolderOf(o2) : o2 && o2 ~= thedark : o2 = HolderOf(o2)) if (o2 == o1) rtrue;</span>
|
|
<span class="plain">rfalse;</span>
|
|
<span class="plain">];</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP3"></a><b>§3. To Decide Whether In. </b>A curiosity, this: the I6 definition of "To decide whether in (obj - object)".
|
|
As can be seen, there are three possible interpretations of "in", depending
|
|
on the kind of object, so this could all be done with three different
|
|
definitions in the Standard Rules, so that run-time type checking would decide
|
|
which to apply: but that would produce a little overhead and make the code
|
|
for this rather common operation a bit complicated. Besides, this way we can
|
|
produce a respectable run-time problem message when the phrase is misapplied.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">Note that "in X" is not equivalent to "the player is in X": the latter
|
|
uses direct containment, whereas we use indirect containment. Thus "in the
|
|
Hall" and "in the laundry-basket" are both true if the player is in a
|
|
laundry-basket in the Hall.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">[ WhetherIn obj;</span>
|
|
<span class="plain">if (obj has enterable) {</span>
|
|
<span class="plain">if (IndirectlyContains(obj, player)) rtrue;</span>
|
|
<span class="plain">rfalse;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">if (obj ofclass K9_region) return TestRegionalContainment(real_location, obj);</span>
|
|
<span class="plain">if (obj ofclass K1_room) {</span>
|
|
<span class="plain">if (obj == real_location) rtrue;</span>
|
|
<span class="plain">rfalse;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">RunTimeProblem(RTP_NOTINAROOM, obj);</span>
|
|
<span class="plain">rfalse;</span>
|
|
<span class="plain">];</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP4"></a><b>§4. Containment Relation. </b>This is the single most important relation in I7: direct containment. It is
|
|
complicated by the fact that "A is in B" is represented differently at
|
|
run-time when A is a room and B is a region, and when it isn't.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">For each A there is at most one B such that "A is in B" is true. Because of
|
|
this we test the relation with a function of one variable which turns A into B,
|
|
rather than a function of two variables returning true or false. <code class="display"><span class="extract">ContainerOf</span></code>
|
|
is that function.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">I7 frequently needs to compile loops over all A such that "A is in B". In
|
|
simpler relations (such as the support relation below) it can do this efficiently
|
|
by iterating through the object-tree children of B, but for containment we
|
|
have to provide an iterator function <code class="display"><span class="extract">TestContainmentRange</span></code>, as otherwise we
|
|
would get the wrong result when B is a region.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">[ ContainerOf A p;</span>
|
|
<span class="plain">if (A ofclass K1_room) return A.map_region;</span>
|
|
<span class="plain">p = parent(A);</span>
|
|
<span class="plain">if (p == nothing) return nothing;</span>
|
|
<span class="plain">if (p ofclass K5_container) return p;</span>
|
|
<span class="plain">if (p ofclass K1_room) return p;</span>
|
|
<span class="plain">if (p ofclass K9_region) return p;</span>
|
|
<span class="plain">return nothing;</span>
|
|
<span class="plain">];</span>
|
|
|
|
<span class="plain">[ TestContainmentRange obj e f;</span>
|
|
<span class="plain">if (obj ofclass K9_region) {</span>
|
|
<span class="plain">objectloop (f ofclass K1_room && f.map_region == obj)</span>
|
|
<span class="plain">if (f > e) return f;</span>
|
|
<span class="plain">return nothing;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">if (obj ofclass K5_container or K1_room) {</span>
|
|
<span class="plain">if (e == nothing) return child(obj);</span>
|
|
<span class="plain">return sibling(e);</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">return nothing;</span>
|
|
<span class="plain">];</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP5"></a><b>§5. Support Relation. </b>This then is simpler, with no need for an iterator governing searches.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">[ SupporterOf obj p;</span>
|
|
<span class="plain">p = parent(obj);</span>
|
|
<span class="plain">if (p == nothing) return nothing;</span>
|
|
<span class="plain">if (p ofclass K6_supporter) return p;</span>
|
|
<span class="plain">return nothing;</span>
|
|
<span class="plain">];</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP6"></a><b>§6. Carrying Relation. </b>Only people may carry, and something worn is not in this sense carried.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">[ CarrierOf obj p;</span>
|
|
<span class="plain">p = parent(obj);</span>
|
|
<span class="plain">if (p && (p ofclass K8_person) && (obj hasnt worn)) return p;</span>
|
|
<span class="plain">return nothing;</span>
|
|
<span class="plain">];</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP7"></a><b>§7. Wearing Relation. </b>Only people may wear.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">[ WearerOf obj p;</span>
|
|
<span class="plain">p = parent(obj);</span>
|
|
<span class="plain">if (p && (p ofclass K8_person) && (obj has worn)) return p;</span>
|
|
<span class="plain">return nothing;</span>
|
|
<span class="plain">];</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP8"></a><b>§8. Having Relation. </b>A person has something if and only if he either wears or carries it.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">[ OwnerOf obj p;</span>
|
|
<span class="plain">p = parent(obj);</span>
|
|
<span class="plain">if (p && (p ofclass K8_person)) return p;</span>
|
|
<span class="plain">return nothing;</span>
|
|
<span class="plain">];</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP9"></a><b>§9. Making Parts. </b>Note that <code class="display"><span class="extract">MakePart</span></code> removes the part-to-be from the object tree before
|
|
attaching it: it cannot, of course, be the core of the resulting object.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">[ MakePart P Of First;</span>
|
|
<span class="plain">if (P == player) return RunTimeProblem(RTP_CANTMAKEPART, Of);</span>
|
|
<span class="plain">if (parent(P)) remove P; give P ~worn;</span>
|
|
<span class="plain">if (Of == nothing) { DetachPart(P); return; }</span>
|
|
<span class="plain">if (P.component_parent) DetachPart(P);</span>
|
|
<span class="plain">P.component_parent = Of;</span>
|
|
<span class="plain">First = Of.component_child;</span>
|
|
<span class="plain">Of.component_child = P; P.component_sibling = First;</span>
|
|
<span class="plain">];</span>
|
|
|
|
<span class="plain">[ DetachPart P From Daddy O;</span>
|
|
<span class="plain">Daddy = P.component_parent; P.component_parent = nothing;</span>
|
|
<span class="plain">if (Daddy == nothing) { P.component_sibling = nothing; return; }</span>
|
|
<span class="plain">if (Daddy.component_child == P) {</span>
|
|
<span class="plain">Daddy.component_child = P.component_sibling;</span>
|
|
<span class="plain">P.component_sibling = nothing; return;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">for (O = Daddy.component_child: O: O = O.component_sibling)</span>
|
|
<span class="plain">if (O.component_sibling == P) {</span>
|
|
<span class="plain">O.component_sibling = P.component_sibling;</span>
|
|
<span class="plain">P.component_sibling = nothing; return;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">];</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP10"></a><b>§10. Movements. </b>Note that an object is detached from its component parent, if it has one,
|
|
when moved.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">[ MoveObject F T opt going_mode was L;</span>
|
|
<span class="plain">if (F == nothing) return RunTimeProblem(RTP_CANTMOVENOTHING);</span>
|
|
<span class="plain">if (F ofclass K7_backdrop) {</span>
|
|
<span class="plain">if (T ofclass K9_region) {</span>
|
|
<span class="plain">give F ~absent; F.found_in = T.regional_found_in;</span>
|
|
<span class="plain">if (TestRegionalContainment(LocationOf(player), T)) move F to LocationOf(player);</span>
|
|
<span class="plain">else remove F;</span>
|
|
<span class="plain">return; }</span>
|
|
<span class="plain">if (T == FoundEverywhere) {</span>
|
|
<span class="plain">give F ~absent; F.found_in = FoundEverywhere;</span>
|
|
<span class="plain">return;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">return RunTimeProblem(RTP_BACKDROP, F, T);</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">if (T ofclass K9_region) return RunTimeProblem(RTP_NOTBACKDROP, F, T);</span>
|
|
<span class="plain">if (T == FoundEverywhere) return RunTimeProblem(RTP_BACKDROPONLY, F);</span>
|
|
<span class="plain">if (~~(F ofclass K2_thing)) return RunTimeProblem(RTP_NOTTHING, F, T);</span>
|
|
<span class="plain">if (F has worn) {</span>
|
|
<span class="plain">give F ~worn;</span>
|
|
<span class="plain">if (F in T) return;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">DetachPart(F);</span>
|
|
<span class="plain">if (going_mode == false) {</span>
|
|
<span class="plain">if (F == player) { PlayerTo(T, opt); return; }</span>
|
|
<span class="plain">if (IndirectlyContains(F, player)) {</span>
|
|
<span class="plain">L = LocationOf(T);</span>
|
|
<span class="plain">if (L == nothing) return RunTimeProblem(RTP_CANTBEOFFSTAGE);</span>
|
|
<span class="plain">if (LocationOf(player) ~= L) {</span>
|
|
<span class="plain">was = parent(player);</span>
|
|
<span class="plain">move player to real_location;</span>
|
|
<span class="plain">move F to T;</span>
|
|
<span class="plain">PlayerTo(was, true);</span>
|
|
<span class="plain">return;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">move F to T;</span>
|
|
<span class="plain">];</span>
|
|
|
|
<span class="plain">[ RemoveFromPlay F;</span>
|
|
<span class="plain">if (F == nothing) return RunTimeProblem(RTP_CANTREMOVENOTHING);</span>
|
|
<span class="plain">if (F == player) return RunTimeProblem(RTP_CANTREMOVEPLAYER);</span>
|
|
<span class="plain">if (F ofclass K4_door) return RunTimeProblem(RTP_CANTREMOVEDOORS);</span>
|
|
<span class="plain">if (IndirectlyContains(F, player)) return RunTimeProblem(RTP_CANTBEOFFSTAGE);</span>
|
|
<span class="plain">give F ~worn; DetachPart(F);</span>
|
|
<span class="plain">if (F ofclass K7_backdrop) give F absent;</span>
|
|
<span class="plain">remove F;</span>
|
|
<span class="plain">];</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP11"></a><b>§11. On Stage. </b>The following implements the "on-stage" and "off-stage" adjectives
|
|
provided by the Standard Rules. Here, as above, note that the I6 attribute
|
|
<code class="display"><span class="extract">absent</span></code> marks a floating object (see below) which has been removed from
|
|
play; in I7 only doors and backdrops are allowed to float, and only backdrops
|
|
are allowed to be removed from play.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">[ OnStage O set x;</span>
|
|
<span class="plain">if (O ofclass K1_room) rfalse;</span>
|
|
<span class="plain">if (set < 0) {</span>
|
|
<span class="plain">while (metaclass(O) == Object) {</span>
|
|
<span class="plain">if (O ofclass K1_room) rtrue;</span>
|
|
<span class="plain">if (O ofclass K9_region) rfalse;</span>
|
|
<span class="plain">if (O ofclass K4_door) rtrue;</span>
|
|
<span class="plain">if (O ofclass K7_backdrop) { if (O has absent) rfalse; rtrue; }</span>
|
|
<span class="plain">x = O.component_parent; if (x) { O = x; continue; }</span>
|
|
<span class="plain">x = parent(O); if (x) { O = x; continue; }</span>
|
|
<span class="plain">rfalse;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">x = OnStage(O, -1);</span>
|
|
<span class="plain">if ((x) && (set == false)) RemoveFromPlay(O);</span>
|
|
<span class="plain">if ((x == false) && (set)) MoveObject(O, real_location);</span>
|
|
<span class="plain">rfalse;</span>
|
|
<span class="plain">];</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP12"></a><b>§12. Moving the Player. </b>Note that the player object can only be moved by this routine: this allows
|
|
us to maintain the invariant for <code class="display"><span class="extract">real_location</span></code> and <code class="display"><span class="extract">location</span></code> (for which,
|
|
see "Light.i6t") and to ensure that multiply-present objects can be
|
|
witnessed where they need to be.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">[ PlayerTo newplace flag L;</span>
|
|
<span class="plain">L = LocationOf(newplace);</span>
|
|
<span class="plain">if (L == nothing) return RunTimeProblem(RTP_CANTBEOFFSTAGE);</span>
|
|
<span class="plain">@push actor; actor = player;</span>
|
|
<span class="plain">move player to newplace;</span>
|
|
<span class="plain">location = L;</span>
|
|
<span class="plain">real_location = location;</span>
|
|
<span class="plain">MoveFloatingObjects();</span>
|
|
<span class="plain">SilentlyConsiderLight();</span>
|
|
<span class="plain">DivideParagraphPoint();</span>
|
|
<span class="plain">if (flag == 0) R_Process(##Look);</span>
|
|
<span class="plain">if (flag == 1) give location visited;</span>
|
|
<span class="plain">if (flag == 2) AbbreviatedRoomDescription();</span>
|
|
<span class="plain">@pull actor;</span>
|
|
<span class="plain">];</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP13"></a><b>§13. Move During Going. </b>The following routine preserves the invariant for <code class="display"><span class="extract">real_location</span></code>, but gets
|
|
<code class="display"><span class="extract">location</span></code> wrong since it doesn't adjust for light. Nor are floating objects
|
|
moved. It should be used only in the course of other operations which get
|
|
the rest of this right. (I7 uses it only for the "going" action, where
|
|
these various operations are each handled by different named rules to
|
|
increase the flexibility of the system.)
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">[ MoveDuringGoing F T;</span>
|
|
<span class="plain">MoveObject(F, T, 0, true);</span>
|
|
<span class="plain">if (actor == player) {</span>
|
|
<span class="plain">location = LocationOf(player);</span>
|
|
<span class="plain">real_location = location;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">];</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP14"></a><b>§14. Being Everywhere. </b>The following is used as the <code class="display"><span class="extract">found_in</span></code> property for any backdrop which is
|
|
"everywhere", that is, which is found in every room.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">[ FoundEverywhere; rtrue; ];</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP15"></a><b>§15. Testing Everywhere. </b></p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">[ BackdropEverywhere O;</span>
|
|
<span class="plain">if (O ofclass K7_backdrop) {</span>
|
|
<span class="plain">if (O has absent) rfalse;</span>
|
|
<span class="plain">if (O.found_in == FoundEverywhere) rtrue;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">rfalse;</span>
|
|
<span class="plain">];</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP16"></a><b>§16. Changing the Player. </b>It is very important that nobody simply change the value of the <code class="display"><span class="extract">player</span></code>
|
|
variable, because so much else must be updated when the identity of the
|
|
player changes: the light situation, floating objects, the <code class="display"><span class="extract">real_location</span></code>
|
|
and so on. Because of this, the NI compiler contains code which compiles
|
|
an assertion of the proposition "is(<code class="display"><span class="extract">player</span></code>, X)" into a function call
|
|
<code class="display"><span class="extract">ChangePlayer(X)</span></code> rather than a variable assignment <code class="display"><span class="extract">player = X</span></code>. So we
|
|
cannot catch out the system by writing "now the player is Mr Henderson".
|
|
</p>
|
|
|
|
<p class="inwebparagraph">We must ensure that if <code class="display"><span class="extract">player</span></code> is initially X, is changed to Y, and is then
|
|
changed back to X, that both X and Y end exactly as they began — hence the
|
|
flummery below with using <code class="display"><span class="extract">remove_proper</span></code> to ensure that <code class="display"><span class="extract">proper</span></code> is left
|
|
with the correct value. Note that:
|
|
</p>
|
|
|
|
<ul class="items"><li>(1) at any given time exactly one person has the I6 <code class="display"><span class="extract">concealed</span></code> attribute: the
|
|
current player;
|
|
</li><li>(2) the <code class="display"><span class="extract">selfobj</span></code> is the default initial value of <code class="display"><span class="extract">player</span></code>, and because it has
|
|
as its actual printed name "yourself", we need to override this when
|
|
something else takes over as player: we change to "your former self", in
|
|
fact. No such device is needed for other people being changed from because
|
|
they are explicitly given printed names — say "Mr Darcy", "the sous-chef",
|
|
etc. — in the source text.
|
|
</li></ul>
|
|
|
|
<pre class="display">
|
|
<span class="plain">[ ChangePlayer obj flag;</span>
|
|
<span class="plain">if (~~(obj ofclass K8_person)) return RunTimeProblem(RTP_CANTCHANGE, obj);</span>
|
|
<span class="plain">if (~~(OnStage(obj, -1))) return RunTimeProblem(RTP_CANTCHANGEOFFSTAGE, obj);</span>
|
|
<span class="plain">if (obj.component_parent) return RunTimeProblem(RTP_CANTMAKEPART, obj);</span>
|
|
<span class="plain">if (obj == player) return;</span>
|
|
|
|
<span class="plain">give player ~concealed;</span>
|
|
<span class="plain">if (player has remove_proper) give player ~proper;</span>
|
|
<span class="plain">if (player == selfobj) {</span>
|
|
<span class="plain">player.saved_short_name = player.short_name;</span>
|
|
<span class="plain">player.short_name = PRINT_PROTAGONIST_INTERNAL_RM('c');</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">player = obj;</span>
|
|
<span class="plain">if (player == selfobj) {</span>
|
|
<span class="plain">player.short_name = player.saved_short_name;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">if (player hasnt proper) give player remove_proper; ! when changing out again</span>
|
|
<span class="plain">give player concealed;</span>
|
|
<span class="plain">give player proper;</span>
|
|
|
|
<span class="plain">location = LocationOf(player); real_location = location;</span>
|
|
<span class="plain">MoveFloatingObjects();</span>
|
|
<span class="plain">SilentlyConsiderLight();</span>
|
|
<span class="plain">];</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP17"></a><b>§17. Floating Objects. </b>A single object can only be in one position in the object tree, yet backdrops
|
|
and doors must be present in multiple rooms. This is accomplished by making
|
|
them, in I6 jargon, "floating objects": objects which move in the tree
|
|
whenever the player does, so that — from the player's perspective — they
|
|
are always present when they should be. In I6, almost anything can be made
|
|
a floating object, but in I7 this is strictly and only used for backdrops
|
|
and two-sided doors.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">There are several conceptual problems with this scheme: chiefly that it
|
|
assumes that the only witness to the spatial arrangement of objects is the
|
|
player. In I6 that was usually true, but in I7, where every person can
|
|
undertake actions, it really isn't true any longer: if the objects float
|
|
to follow the player, it means that they are not present with other people
|
|
who might need to interact with them. This is why the accessibility rules
|
|
are somewhat hacked for backdrops and doors (see "Light.i6t"). In fact we
|
|
generally achieve the illusion we want, but this is largely because it is
|
|
difficult to catch out all the exceptions for backdrops and doors, and
|
|
because in practice authors tend not to set things up so that the presence
|
|
or absence of backdrops much affects what non-player characters do.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">All the same, the scheme is not logically defensible, and this is why we
|
|
do not allow the user to create new categories of floating objects in I7.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">The I6 implementation of <code class="display"><span class="extract">MoveFloatingObjects</span></code> acted on the <code class="display"><span class="extract">location</span></code>
|
|
rather than the <code class="display"><span class="extract">real_location</span></code>, which (a) meant that multiply-present objects
|
|
could include <code class="display"><span class="extract">thedark</span></code> — the generic Darkness place — as one possible
|
|
location, but (b) assumed that the only sense by which the player could
|
|
witness an object was sight. In I7, <code class="display"><span class="extract">thedark</span></code> is not a valid room, and we
|
|
are a bit more careful about the senses.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">[ MoveFloatingObjects toroom i k l m address flag;</span>
|
|
<span class="plain">if (toroom == nothing) toroom = real_location;</span>
|
|
<span class="plain">if (toroom == nothing) return;</span>
|
|
<span class="plain">objectloop (i) {</span>
|
|
<span class="plain">address = i.&found_in;</span>
|
|
<span class="plain">if (address ~= 0 && i hasnt absent) {</span>
|
|
<span class="plain">if (ZRegion(address-->0) == 2) {</span>
|
|
<span class="plain">m = address-->0;</span>
|
|
<span class="plain">.TestPropositionally;</span>
|
|
<span class="plain">if (m.call(toroom) ~= 0) move i to toroom;</span>
|
|
<span class="plain">else { if (i in toroom) remove i; }</span>
|
|
<span class="plain">} else {</span>
|
|
<span class="plain">k = i.#found_in;</span>
|
|
<span class="plain">for (l=0 : l<k/WORDSIZE : l++) {</span>
|
|
<span class="plain">m = address-->l;</span>
|
|
<span class="plain">if (ZRegion(m) == 2) jump TestPropositionally;</span>
|
|
<span class="plain">if (m == toroom || m in toroom) {</span>
|
|
<span class="plain">if (i notin toroom) move i to toroom;</span>
|
|
<span class="plain">flag = true;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">if (flag == false) { if (i in toroom) remove i; }</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">if ((i ofclass K4_door) && (parent(i) == nothing)) {</span>
|
|
<span class="plain">move i to ((i.door_to).call());</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">];</span>
|
|
|
|
<span class="plain">[ MoveBackdrop bd D x address;</span>
|
|
<span class="plain">if (~~(bd ofclass K7_backdrop)) return RunTimeProblem(RTP_BACKDROPONLY, bd);</span>
|
|
<span class="plain">if (bd.#found_in > WORDSIZE) {</span>
|
|
<span class="plain">address = bd.&found_in;</span>
|
|
<span class="plain">address-->0 = D;</span>
|
|
<span class="plain">} else bd.found_in = D;</span>
|
|
<span class="plain">give bd ~absent;</span>
|
|
<span class="plain">MoveFloatingObjects();</span>
|
|
<span class="plain">];</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP18"></a><b>§18. Backdrop Location. </b>This determines what the "location" of a backdrop is, or, if "target" is
|
|
other than nothing, determines whether it can ever be the location. Note
|
|
that this routine also works for two-sided doors, despite its name.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">[ BackdropLocation O target address m x i k l r sl;</span>
|
|
<span class="plain">if (O has absent) return nothing;</span>
|
|
<span class="plain">if ((target == nothing or real_location) && (parent(O) == real_location))</span>
|
|
<span class="plain">return real_location;</span>
|
|
<span class="plain">address = O.&found_in;</span>
|
|
<span class="plain">if (address ~= 0) {</span>
|
|
<span class="plain">k = O.#found_in;</span>
|
|
<span class="plain">for (l=0 : l<k/WORDSIZE : l++) {</span>
|
|
<span class="plain">m = address-->l;</span>
|
|
<span class="plain">if (ZRegion(m) == 2) {</span>
|
|
<span class="plain">sl = location;</span>
|
|
<span class="plain">if (target) {</span>
|
|
<span class="plain">location = target;</span>
|
|
<span class="plain">r = m.call();</span>
|
|
<span class="plain">if (r ~= 0) { location = sl; return target; }</span>
|
|
<span class="plain">} else {</span>
|
|
<span class="plain">objectloop (x ofclass K1_room) {</span>
|
|
<span class="plain">location = x;</span>
|
|
<span class="plain">r = m.call();</span>
|
|
<span class="plain">if (r ~= 0) { location = sl; return x; }</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">location = sl;</span>
|
|
<span class="plain">} else {</span>
|
|
<span class="plain">if (m ofclass K9_region) {</span>
|
|
<span class="plain">objectloop (x ofclass K1_room)</span>
|
|
<span class="plain">if (TestRegionalContainment(x, m))</span>
|
|
<span class="plain">if (target == nothing or x)</span>
|
|
<span class="plain">return x;</span>
|
|
<span class="plain">} else {</span>
|
|
<span class="plain">if (target == nothing or m) return m;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">return nothing;</span>
|
|
<span class="plain">];</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP19"></a><b>§19. Wearing Clothes. </b>An object X is worn by a person P if and only if (i) the object tree <code class="display"><span class="extract">parent</span></code>
|
|
of X is P, and (ii) X has the <code class="display"><span class="extract">worn</span></code> attribute. In fact for I7 purposes we
|
|
are careful to ensure that (ii) happens only when (i) does in any case:
|
|
if X is moved in the object tree, or made a part of something, or removed
|
|
from play, then <code class="display"><span class="extract">worn</span></code> is removed.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">[ WearObject X P opt;</span>
|
|
<span class="plain">if (X == false) rfalse;</span>
|
|
<span class="plain">if (X notin P) MoveObject(X, P, opt);</span>
|
|
<span class="plain">give X worn;</span>
|
|
<span class="plain">];</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP20"></a><b>§20. Map Connections. </b><code class="display"><span class="extract">MapConnection</span></code> returns the room which is in the given direction (as an object)
|
|
from the given room: it is used, among other things, to test the "mapped east
|
|
of" and similar relations. (The same relations are asserted true with
|
|
<code class="display"><span class="extract">AssertMapConnection</span></code> and false with <code class="display"><span class="extract">AssertMapUnconnection</span></code>.)
|
|
</p>
|
|
|
|
<p class="inwebparagraph"><code class="display"><span class="extract">RoomOrDoorFrom</span></code> returns either the room or door which is in the given
|
|
direction, and is thus simpler (since it doesn't have to investigate what
|
|
is through such a door).
|
|
</p>
|
|
|
|
<p class="inwebparagraph">Both routines return values which are type-safe in I7 provided the kind of
|
|
value they are assigned to is "object": neither returns any specific kind
|
|
of object without fail. (<code class="display"><span class="extract">MapConnection</span></code> is always either a door or <code class="display"><span class="extract">nothing</span></code>,
|
|
but <code class="display"><span class="extract">nothing</span></code> is not a typesafe value for "door".)
|
|
</p>
|
|
|
|
<p class="inwebparagraph">Note that map connections via doors are immutable.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">[ MapConnection from_room dir</span>
|
|
<span class="plain">in_direction through_door;</span>
|
|
<span class="plain">if ((from_room ofclass K1_room) && (dir ofclass K3_direction)) {</span>
|
|
<span class="plain">in_direction = Map_Storage--></span>
|
|
<span class="plain">((from_room.IK1_Count)*No_Directions + dir.IK3_Count);</span>
|
|
<span class="plain">if (in_direction ofclass K1_room) return in_direction;</span>
|
|
<span class="plain">if (in_direction ofclass K4_door) {</span>
|
|
<span class="plain">@push location;</span>
|
|
<span class="plain">location = from_room;</span>
|
|
<span class="plain">through_door = in_direction.door_to();</span>
|
|
<span class="plain">@pull location;</span>
|
|
<span class="plain">if (through_door ofclass K1_room) return through_door;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">return nothing;</span>
|
|
<span class="plain">];</span>
|
|
|
|
<span class="plain">[ DoorFrom obj dir rv;</span>
|
|
<span class="plain">rv = RoomOrDoorFrom(obj, dir);</span>
|
|
<span class="plain">if (rv ofclass K4_door) return rv;</span>
|
|
<span class="plain">return nothing;</span>
|
|
<span class="plain">];</span>
|
|
|
|
<span class="plain">[ RoomOrDoorFrom obj dir use_doors in_direction sl through_door;</span>
|
|
<span class="plain">if ((obj ofclass K1_room) && (dir ofclass K3_direction)) {</span>
|
|
<span class="plain">in_direction = Map_Storage--></span>
|
|
<span class="plain">((obj.IK1_Count)*No_Directions + dir.IK3_Count);</span>
|
|
<span class="plain">if (in_direction ofclass K1_room or K4_door) return in_direction;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">return nothing;</span>
|
|
<span class="plain">];</span>
|
|
|
|
<span class="plain">[ AssertMapConnection r1 dir r2 in_direction;</span>
|
|
<span class="plain">SignalMapChange();</span>
|
|
<span class="plain">in_direction = Map_Storage--></span>
|
|
<span class="plain">((r1.IK1_Count)*No_Directions + dir.IK3_Count);</span>
|
|
<span class="plain">if ((in_direction == 0) || (in_direction ofclass K1_room)) {</span>
|
|
<span class="plain">Map_Storage-->((r1.IK1_Count)*No_Directions + dir.IK3_Count) = r2;</span>
|
|
<span class="plain">return;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">if (in_direction ofclass K4_door) {</span>
|
|
<span class="plain">RunTimeProblem(RTP_EXITDOOR, r1, dir);</span>
|
|
<span class="plain">return;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">RunTimeProblem(RTP_NOEXIT, r1, dir);</span>
|
|
<span class="plain">];</span>
|
|
|
|
<span class="plain">[ AssertMapUnconnection r1 dir r2 in_direction;</span>
|
|
<span class="plain">SignalMapChange();</span>
|
|
<span class="plain">in_direction = Map_Storage--></span>
|
|
<span class="plain">((r1.IK1_Count)*No_Directions + dir.IK3_Count);</span>
|
|
<span class="plain">if (r1 ofclass K4_door) {</span>
|
|
<span class="plain">RunTimeProblem(RTP_EXITDOOR, r1, dir);</span>
|
|
<span class="plain">return;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">if (in_direction == r2)</span>
|
|
<span class="plain">Map_Storage-->((r1.IK1_Count)*No_Directions + dir.IK3_Count) = 0;</span>
|
|
<span class="plain">return;</span>
|
|
<span class="plain">];</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP21"></a><b>§21. Adjacency Relation. </b>A relation between two rooms which, note, does not see connections through
|
|
doors.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">[ TestAdjacency R1 R2 i row;</span>
|
|
<span class="plain">if (R1 ofclass K9_region) RunTimeProblem(RTP_REGIONSNOTADJACENT, R1);</span>
|
|
<span class="plain">else if (R2 ofclass K9_region) RunTimeProblem(RTP_REGIONSNOTADJACENT, R2);</span>
|
|
<span class="plain">row = (R1.IK1_Count)*No_Directions;</span>
|
|
<span class="plain">for (i=0: i<No_Directions: i++, row++)</span>
|
|
<span class="plain">if (Map_Storage-->row == R2) rtrue;</span>
|
|
<span class="plain">rfalse;</span>
|
|
<span class="plain">];</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP22"></a><b>§22. Regional Containment Relation. </b>This tests whether an object with a definite physical location is in a
|
|
given region. (For a two-sided door which straddles regions, the front side
|
|
is what counts; for a backdrop, a direction or another region, the answer
|
|
is always no.) We rely on the fact that every room object has a <code class="display"><span class="extract">map_region</span></code>
|
|
property which is the smallest region containing it, if any does, and
|
|
<code class="display"><span class="extract">nothing</span></code> otherwise; region objects are then in the object tree such that
|
|
parenthood corresponds to spatial containment. (Note that in I7, a region
|
|
must either completely contain another region, or else have no overlap with it.)
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">[ TestRegionalContainment obj region o;</span>
|
|
<span class="plain">if ((obj == nothing) || (region == nothing)) rfalse;</span>
|
|
<span class="plain">if (obj ofclass K7_backdrop or K4_door) {</span>
|
|
<span class="plain">if (obj has absent) rfalse;</span>
|
|
<span class="plain">objectloop (o ofclass K1_room)</span>
|
|
<span class="plain">if (TestRegionalContainment(o, region))</span>
|
|
<span class="plain">if (BackdropLocation(obj, o))</span>
|
|
<span class="plain">rtrue;</span>
|
|
<span class="plain">rfalse;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">if (~~(obj ofclass K1_room)) obj = LocationOf(obj);</span>
|
|
<span class="plain">if (obj == nothing) rfalse;</span>
|
|
<span class="plain">o = obj.map_region;</span>
|
|
<span class="plain">while (o) {</span>
|
|
<span class="plain">if (o == region) rtrue;</span>
|
|
<span class="plain">o = parent(o);</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">rfalse;</span>
|
|
<span class="plain">];</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP23"></a><b>§23. Doors. </b>There are two sorts of door: one-sided and two-sided.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">A two-sided door is in two rooms at once: one is called the front side, the
|
|
other the back side. The front side is the one declared first in the source.
|
|
Note that a one-sided door is also an I6 object of class <code class="display"><span class="extract">K4_door</span></code>, and
|
|
then the front side is the room holding it, while the back side is <code class="display"><span class="extract">nothing</span></code>.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">The <code class="display"><span class="extract">door_to</span></code> property calculates the room which the door leads to; that
|
|
of course depends on which side of it the player is standing. Similarly,
|
|
<code class="display"><span class="extract">door_dir</span></code> calculates the direction it leads in. Unlike the I6 setup, where
|
|
<code class="display"><span class="extract">door_dir</span></code> returned the direction property (<code class="display"><span class="extract">n_to</span></code>, <code class="display"><span class="extract">s_to</span></code>, etc.), here in
|
|
I7's template it returns the direction object (<code class="display"><span class="extract">n_obj</span></code>, <code class="display"><span class="extract">s_obj</span></code>, etc.)
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">[ FrontSideOfDoor D; if (~~(D ofclass K4_door)) rfalse;</span>
|
|
<span class="plain">if (D provides found_in) return (D.&found_in)-->0; ! Two-sided</span>
|
|
<span class="plain">return parent(D); ! One-sided</span>
|
|
<span class="plain">];</span>
|
|
|
|
<span class="plain">[ BackSideOfDoor D; if (~~(D ofclass K4_door)) rfalse;</span>
|
|
<span class="plain">if (D provides found_in) return (D.&found_in)-->1; ! Two-sided</span>
|
|
<span class="plain">return nothing; ! One-sided</span>
|
|
<span class="plain">];</span>
|
|
|
|
<span class="plain">[ OtherSideOfDoor D from_room rv;</span>
|
|
<span class="plain">if (D ofclass K4_door) {</span>
|
|
<span class="plain">@push location;</span>
|
|
<span class="plain">location = LocationOf(from_room);</span>
|
|
<span class="plain">rv = D.door_to();</span>
|
|
<span class="plain">@pull location;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">return rv;</span>
|
|
<span class="plain">];</span>
|
|
|
|
<span class="plain">[ DirectionDoorLeadsIn D from_room rv dir;</span>
|
|
<span class="plain">if (D ofclass K4_door) {</span>
|
|
<span class="plain">@push location;</span>
|
|
<span class="plain">location = LocationOf(from_room);</span>
|
|
<span class="plain">rv = D.door_dir();</span>
|
|
<span class="plain">@pull location;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">return rv;</span>
|
|
<span class="plain">];</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP24"></a><b>§24. Visibility Relation. </b>We use <code class="display"><span class="extract">TestScope</span></code> to decide whether there is a line of sight from A to B;
|
|
it's a relation which cannot be asserted true or false.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">[ TestVisibility A B;</span>
|
|
<span class="plain">if (~~OffersLight(parent(CoreOf(A)))) rfalse;</span>
|
|
<span class="plain">if (suppress_scope_loops) rtrue;</span>
|
|
<span class="plain">return TestScope(B, A);</span>
|
|
<span class="plain">];</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP25"></a><b>§25. Touchability Relation. </b>We use <code class="display"><span class="extract">ObjectIsUntouchable</span></code> to decide whether there is physical access from
|
|
A to B; it's a relation which cannot be asserted true or false.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">[ TestTouchability A B rv;</span>
|
|
<span class="plain">if (A ofclass K4_door or K7_backdrop) MoveFloatingObjects(LocationOf(B));</span>
|
|
<span class="plain">if (B ofclass K4_door or K7_backdrop) MoveFloatingObjects(LocationOf(A));</span>
|
|
<span class="plain">if (TestScope(B,A) == false) rv = true;</span>
|
|
<span class="plain">else rv = ObjectIsUntouchable(B, true, A);</span>
|
|
<span class="plain">if (A ofclass K4_door or K7_backdrop) MoveFloatingObjects();</span>
|
|
<span class="plain">if (rv) rfalse;</span>
|
|
<span class="plain">rtrue;</span>
|
|
<span class="plain">];</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP26"></a><b>§26. Concealment Relation. </b>An activity determines whether one object conceals another; it's a relation
|
|
which cannot be asserted true or false.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">[ TestConcealment A B;</span>
|
|
<span class="plain">if (A ofclass K2_thing && B ofclass K2_thing) {</span>
|
|
<span class="plain">particular_possession = B;</span>
|
|
<span class="plain">if (CarryOutActivity(DECIDING_CONCEALED_POSSESS_ACT, A)) rtrue;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">rfalse;</span>
|
|
<span class="plain">];</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<hr class="tocbar">
|
|
<ul class="toc"><li><a href="S-tt2.html">Back to 'Time Template'</a></li><li><a href="S-zt.html">Continue with 'ZMachine Template'</a></li></ul><hr class="tocbar">
|
|
<!--End of weave-->
|
|
</body>
|
|
</html>
|
|
|