mirror of
https://github.com/ganelson/inform.git
synced 2024-07-08 18:14:21 +03:00
1200 lines
74 KiB
HTML
1200 lines
74 KiB
HTML
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
|
<html>
|
|
<head>
|
|
<title>S/lt2</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/lt3' 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>ListWriter Template</b></li></ul><p class="purpose">A flexible object-lister taking care of plurals, inventory information, various formats and so on.</p>
|
|
|
|
<ul class="toc"><li><a href="#SP1">§1. Specification</a></li><li><a href="#SP2">§2. Memory</a></li><li><a href="#SP3">§3. WriteListOfMarkedObjects</a></li><li><a href="#SP4">§4. List Number and Gender</a></li><li><a href="#SP5">§5. List Writer Regard Storage</a></li><li><a href="#SP6">§6. Response Printing</a></li><li><a href="#SP7">§7. About Iterator Functions</a></li><li><a href="#SP8">§8. Marked List Iterator</a></li><li><a href="#SP9">§9. Concealment</a></li><li><a href="#SP10">§10. Coalesce Marked List</a></li><li><a href="#SP11">§11. Object Tree Iterator</a></li><li><a href="#SP12">§12. Coalesce Object Tree</a></li><li><a href="#SP13">§13. GroupChildren</a></li><li><a href="#SP14">§14. WriteListFrom</a></li><li><a href="#SP15">§15. Standard Contents Listing Rule</a></li><li><a href="#SP16">§16. Partitioning</a></li><li><a href="#SP17">§17. Partition List</a></li><li><a href="#SP18">§18. Equivalence Relation</a></li><li><a href="#SP19">§19. Grouping</a></li><li><a href="#SP20">§20. Write List Recursively</a></li><li><a href="#SP21">§21. Write Multiple Class Group</a></li><li><a href="#SP22">§22. Write Single Class Group</a></li><li><a href="#SP23">§23. Write After Entry</a></li><li><a href="#SP24">§24. Internal Rule</a></li></ul><hr class="tocbar">
|
|
|
|
<p class="inwebparagraph"><a id="SP1"></a><b>§1. Specification. </b>The list-writer is called by one of the following function calls:
|
|
</p>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<ul class="items"><li>(1) <code class="display"><span class="extract">WriteListOfMarkedObjects(style)</span></code>, where the set of objects listed is
|
|
understood to be exactly those with the <code class="display"><span class="extract">workflag2</span></code> attribute set, and
|
|
<ul class="items"><li>(a) the <code class="display"><span class="extract">style</span></code> is a sum of <code class="display"><span class="extract">*_BIT</span></code> constants as defined in "Definitions.i6t".
|
|
</li></ul>
|
|
</li></ul>
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<ul class="items"><li>(2) <code class="display"><span class="extract">WriteListFrom(obj, style, depth, noactivity, iterator)</span></code>, where only the
|
|
first two parameters are compulsory:
|
|
<ul class="items"><li>(a) the set of objects listed begins with <code class="display"><span class="extract">obj</span></code>;
|
|
</li><li>(b) the <code class="display"><span class="extract">style</span></code> is a sum of <code class="display"><span class="extract">*_BIT</span></code> constants as defined in "Definitions.i6t";
|
|
</li><li>(c) the <code class="display"><span class="extract">depth</span></code> is the recursion depth within the list — ordinarily 0, but
|
|
by supplying a higher value, we can simulate a sublist of another list;
|
|
</li><li>(d) <code class="display"><span class="extract">noactivity</span></code> is a flag which forces the list-writer to ignore the
|
|
"listing the contents of" activity (in cases where it would otherwise consult
|
|
this): by default this is <code class="display"><span class="extract">false</span></code>;
|
|
</li><li>(e) <code class="display"><span class="extract">iterator</span></code> is an iterator function which provides the objects in sequence.
|
|
</li></ul>
|
|
</li></ul>
|
|
<p class="inwebparagraph"><code class="display"><span class="extract">WriteListOfMarkedObjects</span></code> is simply a front-end which supplies suitable
|
|
parameters for <code class="display"><span class="extract">WriteListFrom</span></code>.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">The iterator function is by default <code class="display"><span class="extract">ObjectTreeIterator</span></code>. This defines the
|
|
sequence of objects as being the children of the parent of <code class="display"><span class="extract">obj</span></code>, in object
|
|
tree sequence (that is: <code class="display"><span class="extract">child(parent(obj))</span></code> is first). Moreover, when using
|
|
<code class="display"><span class="extract">ObjectTreeIterator</span></code>, the "listing the contents of" activity is carried out,
|
|
unless <code class="display"><span class="extract">noactivity</span></code> is set.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">We also provide the iterator function <code class="display"><span class="extract">MarkedListIterator</span></code>, which defines
|
|
the sequence of objects as being the list in the word array
|
|
<code class="display"><span class="extract">MarkedObjectArray</span></code> with length <code class="display"><span class="extract">MarkedObjectLength</span></code>. Here the "listing
|
|
the contents of" activity is never used, since the objects are not
|
|
necessarily the contents of any single thing. This of course is the
|
|
iterator used by <code class="display"><span class="extract">WriteListOfMarkedObjects(style)</span></code>: it works by filling
|
|
this array with all the objects having <code class="display"><span class="extract">workflag2</span></code> set.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">The full specification for iterator functions is given below.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">The list-writer automatically groups adjacent and indistinguishable terms
|
|
in the sequence into plurals, and carries out the "printing the plural
|
|
name" activity to handle these. Doing this alone would result in text such
|
|
as "You can see a cake, three coins, an onion, and two coins here",
|
|
where the five coins are mentioned in two clauses because they happen not
|
|
to be adjacent in the list. The list-writer therefore carries out the activity
|
|
"grouping together" to see if the user would like to tie certain objects
|
|
together into a single entry: what this does is to set suitable <code class="display"><span class="extract">list_together</span></code>
|
|
properties for the objects. NI has already given plural objects a similar
|
|
<code class="display"><span class="extract">list_together</span></code> property. The net effect is that any entries in the list with
|
|
a non-blank value of <code class="display"><span class="extract">list_together</span></code> must be adjacent to each other.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">We could achieve that by sorting the list in order of <code class="display"><span class="extract">list_together</span></code> value,
|
|
but that would result in drastic movements, whereas we want to upset the
|
|
original ordering as little as possible. So instead we use a process called
|
|
coalescing the list. This is such that for every value L!= 0
|
|
of <code class="display"><span class="extract">list_together</span></code>, every entry with that value is moved back in the list
|
|
to follow the first entry with that value. Thus if the original order is
|
|
x_1, x_2, ..., x_N then x_j still precedes x_k in coalesced order
|
|
unless there exists i<j<k such that L(i) = L(k) != 0 and L(j)!= L(i).
|
|
This is as stable as it can be while achieving the "interval" property
|
|
that non-zero L values occur in contiguous runs.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">We therefore obtain text such as "You can see a cake, five coins, the tiles
|
|
W, X, Y and Z from a Scrabble set, and an onion here." where the coins and
|
|
the Scrabble tiles have been coalesced together in the list.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">It's important to note that the default <code class="display"><span class="extract">ObjectTreeIterator</span></code> has the
|
|
side-effect of actually reordering the object tree: it rearranges the children
|
|
being listed so that they appear in the tree in coalesced order. The
|
|
<code class="display"><span class="extract">MarkedListIterator</span></code> used by <code class="display"><span class="extract">WriteListOfMarkedObjects</span></code> has the same
|
|
side-effect if the marked objects all happen to share a common parent.
|
|
It might seem odd for a list-writer to have side effects at all, but the
|
|
idea is that occasional coalescing improves the quality of play in many
|
|
small ways — for instance, the sequence of matches to TAKE ALL is tidier —
|
|
and that coalescing has a small speed cost, so we want to do it as little
|
|
as possible. (The latter was more of a consideration for I6: interpreters
|
|
are faster nowadays.)
|
|
</p>
|
|
|
|
<p class="inwebparagraph">This specification is somewhat stronger than that of the I6 library's
|
|
traditional list-writer, because
|
|
</p>
|
|
|
|
<ul class="items"><li>(i) it supports arbitrary lists of objects, not just children of specific
|
|
parents, while still allowing coalesced and grouped lists,
|
|
</li><li>(ii) it can be used recursively in all cases,
|
|
</li><li>(iii) it uses its own memory, rather than borrowing memory from the parser,
|
|
so that it can safely be used while the parser is working, and
|
|
</li><li>(iv) it manages this memory more flexibly and without silently failing by
|
|
buffer overruns on unexpectedly large lists.
|
|
</li></ul>
|
|
<p class="inwebparagraph">The I7 version of <code class="display"><span class="extract">WriteListFrom</span></code>, when using <code class="display"><span class="extract">ObjectTreeIterator</span></code>, differs
|
|
from the I6 version in that the object <code class="display"><span class="extract">o</span></code> is required to be the <code class="display"><span class="extract">child</span></code> of
|
|
its <code class="display"><span class="extract">parent</span></code>, that is, to be the eldest child. (So in effect it's a function
|
|
of parents, not children, but we retain the form for familiarity's sake.)
|
|
In practice this was invariably the way <code class="display"><span class="extract">WriteListFrom</span></code> was used even in
|
|
I6 days.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">Finally, the <code class="display"><span class="extract">ISARE_BIT</span></code> is differently interpreted in I7: instead of printing
|
|
something like " are ducks and drakes", as it would have done in I6, the
|
|
initial space is now suppressed and we instead print "are ducks and drakes".
|
|
</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP2"></a><b>§2. Memory. </b>The list-writer needs to dynamically allocate temporary array space of a known
|
|
size, in such a way that the array is effectively on the local stack frame:
|
|
if only either the Z-machine or Glulx supported a stack in memory, this would
|
|
be no problem, but they do not and we must therefore use the following.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">The size of the stack is such that it can support a list which includes every
|
|
object and recurses in turn to most other objects: in practice, this never
|
|
happens. It would be nice to allocate more just in case, but the Z-machine is
|
|
desperately short of array memory.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">Constant REQUISITION_STACK_SIZE = 3*ICOUNT_OBJECT;</span>
|
|
<span class="plain">Array requisition_stack --> REQUISITION_STACK_SIZE;</span>
|
|
<span class="plain">Global requisition_stack_pointer = 0;</span>
|
|
|
|
<span class="plain">[ RequisitionStack len top addr;</span>
|
|
<span class="plain">top = requisition_stack_pointer + len;</span>
|
|
<span class="plain">if (top > REQUISITION_STACK_SIZE) return false;</span>
|
|
<span class="plain">addr = requisition_stack + requisition_stack_pointer*WORDSIZE;</span>
|
|
<span class="plain">! print "Allocating ", addr, " at pointer ", requisition_stack_pointer, "^";</span>
|
|
<span class="plain">requisition_stack_pointer = top;</span>
|
|
<span class="plain">return addr;</span>
|
|
<span class="plain">];</span>
|
|
|
|
<span class="plain">[ FreeStack addr;</span>
|
|
<span class="plain">if (addr == 0) return;</span>
|
|
<span class="plain">requisition_stack_pointer = (addr - requisition_stack)/WORDSIZE;</span>
|
|
<span class="plain">];</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP3"></a><b>§3. WriteListOfMarkedObjects. </b>This routine will use the <code class="display"><span class="extract">MarkedListIterator</span></code>. That means it has to create
|
|
an array containing the object numbers of every object with the <code class="display"><span class="extract">workflag2</span></code>
|
|
attribute set, placing the address of this array in <code class="display"><span class="extract">MarkedObjectArray</span></code> and
|
|
the length in <code class="display"><span class="extract">MarkedObjectLength</span></code>. Note that we preserve any existing
|
|
marked list on the stack (using the assembly-language instructions <code class="display"><span class="extract">@push</span></code>
|
|
and <code class="display"><span class="extract">@pull</span></code>) for the duration of our use.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">While the final order of this list will depend on what it looks like after
|
|
coalescing, the initial order is also important. If all of the objects have
|
|
a common parent in the object tree, then we coalesce those objects and
|
|
place the list in object tree order. But if not, we place the list in
|
|
object number order (which is essentially the order of traversal of the
|
|
initial state of the object tree: thus objects in Room A will all appear
|
|
before objects in Room B if A was created before B in the source text).
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">Global MarkedObjectArray = 0;</span>
|
|
<span class="plain">Global MarkedObjectLength = 0;</span>
|
|
|
|
<span class="plain">[ WriteListOfMarkedObjects in_style</span>
|
|
<span class="plain">obj common_parent first mixed_parentage length g gc;</span>
|
|
|
|
<span class="plain">gc = -2;</span>
|
|
<span class="plain">objectloop (obj ofclass Object && obj has workflag2) {</span>
|
|
<span class="plain">length++;</span>
|
|
<span class="plain">if (first == nothing) { first = obj; common_parent = parent(obj); }</span>
|
|
<span class="plain">else { if (parent(obj) ~= common_parent) mixed_parentage = true; }</span>
|
|
<span class="plain">g = GetGNAOfObject(obj); g = g%3;</span>
|
|
<span class="plain">if (gc == -2) gc = g;</span>
|
|
<span class="plain">else if (gc ~= g) gc = -1;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">if (mixed_parentage) common_parent = nothing;</span>
|
|
|
|
<span class="plain">if (length == 0) {</span>
|
|
<span class="plain">if (in_style & ISARE_BIT ~= 0) LIST_WRITER_INTERNAL_RM('W');</span>
|
|
<span class="plain">else if (in_style & CFIRSTART_BIT ~= 0) LIST_WRITER_INTERNAL_RM('X');</span>
|
|
<span class="plain">else LIST_WRITER_INTERNAL_RM('Y');</span>
|
|
<span class="plain">} else {</span>
|
|
<span class="plain">@push MarkedObjectArray; @push MarkedObjectLength;</span>
|
|
<span class="plain">MarkedObjectArray = RequisitionStack(length);</span>
|
|
<span class="plain">MarkedObjectLength = length;</span>
|
|
<span class="plain">if (MarkedObjectArray == 0) return RunTimeProblem(RTP_LISTWRITERMEMORY);</span>
|
|
|
|
<span class="plain">if (common_parent) {</span>
|
|
<span class="plain">ObjectTreeCoalesce(child(common_parent));</span>
|
|
<span class="plain">length = 0;</span>
|
|
<span class="plain">objectloop (obj in common_parent) ! object tree order</span>
|
|
<span class="plain">if (obj has workflag2) MarkedObjectArray-->length++ = obj;</span>
|
|
<span class="plain">} else {</span>
|
|
<span class="plain">length = 0;</span>
|
|
<span class="plain">objectloop (obj ofclass Object) ! object number order</span>
|
|
<span class="plain">if (obj has workflag2) MarkedObjectArray-->length++ = obj;</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="plain">WriteListFrom(first, in_style, 0, false, MarkedListIterator);</span>
|
|
|
|
<span class="plain">FreeStack(MarkedObjectArray);</span>
|
|
<span class="plain">@pull MarkedObjectLength; @pull MarkedObjectArray;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">prior_named_list = length;</span>
|
|
<span class="plain">prior_named_list_gender = gc;</span>
|
|
<span class="plain">return;</span>
|
|
<span class="plain">];</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP4"></a><b>§4. List Number and Gender. </b>As a brief parenthesis, the same algorithm can be used to work out the
|
|
prior named list number and gender for everything matching a description.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">[ RegardingMarkedObjects</span>
|
|
<span class="plain">obj length g gc;</span>
|
|
<span class="plain">gc = -2;</span>
|
|
<span class="plain">objectloop (obj ofclass Object && obj has workflag2) {</span>
|
|
<span class="plain">length++;</span>
|
|
<span class="plain">g = GetGNAOfObject(obj); g = g%3;</span>
|
|
<span class="plain">if (gc == -2) {</span>
|
|
<span class="plain">gc = g;</span>
|
|
<span class="plain">prior_named_noun = obj;</span>
|
|
<span class="plain">} else if (gc ~= g) gc = -1;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">prior_named_list = length;</span>
|
|
<span class="plain">prior_named_list_gender = gc;</span>
|
|
<span class="plain">if (length == 0) { prior_named_noun = nothing; prior_named_list_gender = -1; }</span>
|
|
<span class="plain">return;</span>
|
|
<span class="plain">];</span>
|
|
|
|
<span class="plain">[ RegardingSingleObject obj;</span>
|
|
<span class="plain">prior_named_list = 1;</span>
|
|
<span class="plain">prior_named_list_gender = -1;</span>
|
|
<span class="plain">prior_named_noun = obj;</span>
|
|
<span class="plain">];</span>
|
|
|
|
<span class="plain">[ RegardingNumber n;</span>
|
|
<span class="plain">prior_named_list = n;</span>
|
|
<span class="plain">prior_named_list_gender = -1;</span>
|
|
<span class="plain">prior_named_noun = nothing;</span>
|
|
<span class="plain">];</span>
|
|
|
|
<span class="plain">[ PNToVP gna;</span>
|
|
<span class="plain">if (prior_named_noun == player) return story_viewpoint;</span>
|
|
<span class="plain">if (prior_named_noun) gna = GetGNAOfObject(prior_named_noun);</span>
|
|
<span class="plain">if (((gna%6)/3 == 1) || (prior_named_list >= 2)) return 6;</span>
|
|
<span class="plain">return 3;</span>
|
|
<span class="plain">];</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP5"></a><b>§5. List Writer Regard Storage. </b>This is somewhat hacky, but enables "[regarding list writer internals]".
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">Array LWI_Storage --> 1 (-1) nothing;</span>
|
|
<span class="plain">[ SetLWI a b c;</span>
|
|
<span class="plain">LWI_Storage-->0 = a;</span>
|
|
<span class="plain">LWI_Storage-->1 = b;</span>
|
|
<span class="plain">LWI_Storage-->2 = c;</span>
|
|
<span class="plain">];</span>
|
|
<span class="plain">[ RegardingLWI;</span>
|
|
<span class="plain">prior_named_list = LWI_Storage-->0;</span>
|
|
<span class="plain">prior_named_list_gender = LWI_Storage-->1;</span>
|
|
<span class="plain">prior_named_noun = LWI_Storage-->2;</span>
|
|
<span class="plain">];</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP6"></a><b>§6. Response Printing. </b>From which:
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">[ ResponseViaActivity R;</span>
|
|
<span class="plain">@push prior_named_noun; @push prior_named_list; @push prior_named_list_gender;</span>
|
|
<span class="plain">RegardingSingleObject(nothing);</span>
|
|
<span class="plain">CarryOutActivity(PRINTING_RESPONSE_ACT, R);</span>
|
|
<span class="plain">@pull prior_named_list_gender; @pull prior_named_list; @pull prior_named_noun;</span>
|
|
<span class="plain">];</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP7"></a><b>§7. About Iterator Functions. </b>Suppose <code class="display"><span class="extract">Iter</span></code> is an iterator function and that we have a "raw list"
|
|
x_1, x_2, ..., x_n of objects. Of these, the iterator function will
|
|
choose a sublist of "qualifying" objects. It is called with arguments
|
|
</p>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">Iter(obj, depth, L, function)</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph">where the <code class="display"><span class="extract">obj</span></code> is required to be x_j for some j and the function is one
|
|
of the <code class="display"><span class="extract">*_ITF</span></code> constants defined below:
|
|
</p>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<ul class="items"><li>(a) On <code class="display"><span class="extract">START_ITF</span></code>, we return x_1, or <code class="display"><span class="extract">nothing</span></code> if the list is empty.
|
|
</li></ul>
|
|
<ul class="items"><li>(b) On <code class="display"><span class="extract">SEEK_ITF</span></code>, we return the smallest k>= j such that x_k qualifies,
|
|
or <code class="display"><span class="extract">nothing</span></code> if none of x_j, x_{j+1}, ..., x_n qualify.
|
|
</li></ul>
|
|
<ul class="items"><li>(c) On <code class="display"><span class="extract">ADVANCE_ITF</span></code>, we return the smallest k > j such that x_k qualifies,
|
|
or <code class="display"><span class="extract">nothing</span></code> if none of x_{j+1}, x_{j+2} ..., x_n qualify.
|
|
</li></ul>
|
|
<ul class="items"><li>(d) On <code class="display"><span class="extract">COALESCE_ITF</span></code>, we coalesce the entire list (not merely the qualifying
|
|
entries) and return the new x_1, or <code class="display"><span class="extract">nothing</span></code> if the list is empty.
|
|
</li></ul>
|
|
<p class="inwebparagraph">Thus, given any x_i, we can produce the sublist of qualifying entries by
|
|
performing <code class="display"><span class="extract">START_ITF</span></code> on x_i, then <code class="display"><span class="extract">SEEK_ITF</span></code>, to produce q_1; then
|
|
<code class="display"><span class="extract">ADVANCE_ITF</span></code> to produce q_2, and so on until <code class="display"><span class="extract">nothing</span></code> is returned, when
|
|
there are no more qualifying entries. <code class="display"><span class="extract">SEEK_ITF</span></code> and <code class="display"><span class="extract">ADVANCE_ITF</span></code> always
|
|
return qualifying objects, or <code class="display"><span class="extract">nothing</span></code>; but <code class="display"><span class="extract">START_ITF</span></code> and <code class="display"><span class="extract">COALESCE_ITF</span></code>
|
|
may return a non-qualifying object, since there's no reason why x_1 should
|
|
qualify in any ordering.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">The iterator can make its own choice of which entries qualify, and of what
|
|
the raw list is; <code class="display"><span class="extract">depth</span></code> is supplied to help in that decision. But if <code class="display"><span class="extract">L</span></code>
|
|
is non-zero then the iterator is required to disqualify any entry whose
|
|
<code class="display"><span class="extract">list_together</span></code> value is not <code class="display"><span class="extract">L</span></code>.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">Constant SEEK_ITF = 0;</span>
|
|
<span class="plain">Constant ADVANCE_ITF = 1;</span>
|
|
<span class="plain">Constant COALESCE_ITF = 2;</span>
|
|
<span class="plain">Constant START_ITF = 3;</span>
|
|
|
|
<span class="plain">! Constant DBLW; ! Uncomment this to provide debugging information at run-time</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP8"></a><b>§8. Marked List Iterator. </b>Here the raw list is provided by the <code class="display"><span class="extract">MarkedObjectArray</span></code>, which is convenient
|
|
for coalescing, but not so helpful for translating the <code class="display"><span class="extract">obj</span></code> parameter into
|
|
the i such that it is x_i. We simply search from the beginning to do
|
|
this, which combined with other code using the iterator makes for some
|
|
unnecessary O(n^2) calculations. But it saves memory and nuisance, and the
|
|
iterator is used only with printing to the screen, which never needs to be
|
|
very rapid anyway (because the player can only read very slowly).
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">[ MarkedListIterator obj depth required_lt function i;</span>
|
|
<span class="plain">if (obj == nothing) return nothing;</span>
|
|
<span class="plain">if (required_lt == 0) required_lt = EMPTY_TEXT_VALUE;</span>
|
|
<span class="plain">switch(function) {</span>
|
|
<span class="plain">START_ITF: return MarkedObjectArray-->0;</span>
|
|
<span class="plain">COALESCE_ITF: return MarkedListCoalesce();</span>
|
|
<span class="plain">SEEK_ITF, ADVANCE_ITF:</span>
|
|
<span class="plain">for (i=0: i<MarkedObjectLength: i++)</span>
|
|
<span class="plain">if (MarkedObjectArray-->i == obj) {</span>
|
|
<span class="plain">if (function == ADVANCE_ITF) i++;</span>
|
|
<span class="plain">for (:i<MarkedObjectLength: i++) {</span>
|
|
<span class="plain">obj = MarkedObjectArray-->i;</span>
|
|
<span class="plain">if ((LT_Compare(required_lt, EMPTY_TEXT_VALUE) ~= 0) &&</span>
|
|
<span class="plain">(LT_Compare(obj.list_together, required_lt) ~= 0)) continue;</span>
|
|
<span class="plain">if ((c_style & WORKFLAG_BIT) && (depth==0) && (obj hasnt workflag))</span>
|
|
<span class="plain">continue;</span>
|
|
<span class="plain">if ((c_style & CONCEAL_BIT) && (ConcealedFromLists(obj))) continue;</span>
|
|
<span class="plain">return obj;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">return nothing;</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="SP9"></a><b>§9. Concealment. </b>This is the definition of concealment used by the list-writer, and means that,
|
|
for example, the "deciding the concealed possessions" activity is taken into
|
|
account.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">[ ConcealedFromLists obj c;</span>
|
|
<span class="plain">if ((obj has concealed) || (obj has scenery)) rtrue;</span>
|
|
<span class="plain">c = parent(obj);</span>
|
|
<span class="plain">if ((c) && (c ofclass K5_container or K6_supporter) && (TestConcealment(c, obj))) rtrue;</span>
|
|
<span class="plain">rfalse;</span>
|
|
<span class="plain">];</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP10"></a><b>§10. Coalesce Marked List. </b>The return value is the new first entry in the raw list.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">[ MarkedListCoalesce o i lt l swap m;</span>
|
|
<span class="plain">for (i=0: i<MarkedObjectLength: i++) {</span>
|
|
<span class="plain">lt = (MarkedObjectArray-->i).list_together;</span>
|
|
<span class="plain">if (LT_Compare(lt, EMPTY_TEXT_VALUE) ~= 0) {</span>
|
|
<span class="plain">! Find first object in list after contiguous run with this list_together value:</span>
|
|
<span class="plain">for (i++: (i<MarkedObjectLength) &&</span>
|
|
<span class="plain">(LT_Compare((MarkedObjectArray-->i).list_together, lt) == 0): i++) ;</span>
|
|
<span class="plain">! If the contiguous run extends to end of list, the list is now perfect:</span>
|
|
<span class="plain">if (i == MarkedObjectLength) return MarkedObjectArray-->0;</span>
|
|
<span class="plain">! And otherwise we look to see if any future entries belong in the earlier run:</span>
|
|
<span class="plain">for (l=i+1: l<MarkedObjectLength: l++)</span>
|
|
<span class="plain">if (LT_Compare((MarkedObjectArray-->l).list_together, lt) == 0) {</span>
|
|
<span class="plain">! Yes, they do: so we perform a rotation to insert it before element i:</span>
|
|
<span class="plain">swap = MarkedObjectArray-->l;</span>
|
|
<span class="plain">for (m=l: m>i: m--) MarkedObjectArray-->m = MarkedObjectArray-->(m-1);</span>
|
|
<span class="plain">MarkedObjectArray-->i = swap;</span>
|
|
<span class="plain">! And now the run is longer:</span>
|
|
<span class="plain">i++;</span>
|
|
<span class="plain">if (i == MarkedObjectLength) return MarkedObjectArray-->0;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">i--;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">return MarkedObjectArray-->0;</span>
|
|
<span class="plain">];</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP11"></a><b>§11. Object Tree Iterator. </b>Here the raw list is the list of all children of a given parent: since the
|
|
argument <code class="display"><span class="extract">obj</span></code> is required to be a member of the raw list, we can use
|
|
<code class="display"><span class="extract">parent(obj)</span></code> to find it. Now seeking and advancing are fast, but coalescing
|
|
is slower.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">Global list_filter_routine;</span>
|
|
|
|
<span class="plain">[ ObjectTreeIterator obj depth required_lt function;</span>
|
|
<span class="plain">if ((obj == nothing) || (parent(obj) == nothing)) return nothing;</span>
|
|
<span class="plain">if (function == START_ITF) obj = child(parent(obj));</span>
|
|
<span class="plain">if (function == COALESCE_ITF) return ObjectTreeCoalesce(obj);</span>
|
|
<span class="plain">if (function == ADVANCE_ITF) obj = sibling(obj);</span>
|
|
<span class="plain">if (required_lt == 0) required_lt = EMPTY_TEXT_VALUE;</span>
|
|
<span class="plain">for (:: obj = sibling(obj)) {</span>
|
|
<span class="plain">if (obj == nothing) return nothing;</span>
|
|
<span class="plain">!if (function == ADVANCE_ITF) print "Considering ", (the) obj, ": ", (TEXT_TY_Say) obj.list_together, ": ", (TEXT_TY_Say) required_lt, ": ", ": ", (TEXT_TY_Say) lt_value, ": ", LT_Compare(obj.list_together, required_lt), "^";</span>
|
|
<span class="plain">if ((LT_Compare(required_lt, EMPTY_TEXT_VALUE) ~= 0) &&</span>
|
|
<span class="plain">(LT_Compare(obj.list_together, required_lt) ~= 0)) continue;</span>
|
|
<span class="plain">if ((c_style & WORKFLAG_BIT) && (depth==0) && (obj hasnt workflag)) continue;</span>
|
|
<span class="plain">if (obj hasnt list_filter_permits) continue;</span>
|
|
<span class="plain">if ((c_style & CONCEAL_BIT) && (ConcealedFromLists(obj))) continue;</span>
|
|
<span class="plain">return obj;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">];</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP12"></a><b>§12. Coalesce Object Tree. </b>Again, the return value is the new first entry in the raw list.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">[ ObjectTreeCoalesce obj memb lt later;</span>
|
|
<span class="plain">#Ifdef DBLW; print "^^Sorting out: "; DiagnoseSortList(obj); #Endif;</span>
|
|
<span class="plain">.StartAgain;</span>
|
|
<span class="plain">for (memb=obj: memb~=nothing: memb=sibling(memb)) {</span>
|
|
<span class="plain">lt = memb.list_together;</span>
|
|
<span class="plain">if (LT_Compare(lt, EMPTY_TEXT_VALUE) ~= 0) {</span>
|
|
<span class="plain">! Find first object in list after contiguous run with this list_together value:</span>
|
|
<span class="plain">for (memb=sibling(memb):</span>
|
|
<span class="plain">(memb) && (LT_Compare(memb.list_together, lt) == 0): memb = sibling(memb)) ;</span>
|
|
<span class="plain">! If the contiguous run extends to end of list, the list is now perfect:</span>
|
|
<span class="plain">if (memb == 0) return obj;</span>
|
|
<span class="plain">! And otherwise we look to see if any future entries belong in the earlier run:</span>
|
|
<span class="plain">for (later=sibling(memb): later: later=sibling(later))</span>
|
|
<span class="plain">if (LT_Compare(later.list_together, lt) == 0) {</span>
|
|
<span class="plain">! Yes, they do: so we perform a regrouping of the list and start again:</span>
|
|
<span class="plain">obj = GroupChildren(parent(obj), lt);</span>
|
|
<span class="plain">#Ifdef DBLW; print "^^Sorted to: "; DiagnoseSortList(obj); #Endif;</span>
|
|
<span class="plain">jump StartAgain;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">return obj;</span>
|
|
<span class="plain">];</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP13"></a><b>§13. GroupChildren. </b>The following runs through the child-objects of <code class="display"><span class="extract">par</span></code> in the I6 object tree,
|
|
and moves those having a given <code class="display"><span class="extract">list_property</span></code> property value together, to
|
|
become the eldest children. It preserves the ordering in between those
|
|
objects, and also in between those not having that property value.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">We do this by temporarily moving objects into and out of <code class="display"><span class="extract">in_obj</span></code> and <code class="display"><span class="extract">out_obj</span></code>,
|
|
objects which in all other circumstances never have children in the tree.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">[ GroupChildren par value;</span>
|
|
<span class="plain">while (child(par) ~= 0) {</span>
|
|
<span class="plain">if (LT_Compare(child(par).list_together, value) ~= 0)</span>
|
|
<span class="plain">move child(par) to out_obj;</span>
|
|
<span class="plain">else</span>
|
|
<span class="plain">move child(par) to in_obj;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">while (child(in_obj) ~= 0) move child(in_obj) to par;</span>
|
|
<span class="plain">while (child(out_obj) ~= 0) move child(out_obj) to par;</span>
|
|
<span class="plain">return child(par);</span>
|
|
<span class="plain">];</span>
|
|
|
|
<span class="plain">#Ifdef DBLW;</span>
|
|
<span class="plain">[ DiagnoseSortList obj memb;</span>
|
|
<span class="plain">for (memb=child(obj): memb~=nothing: memb=sibling(memb)) print memb, " --> "; new_line;</span>
|
|
<span class="plain">];</span>
|
|
<span class="plain">#Endif;</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP14"></a><b>§14. WriteListFrom. </b>And here we go at last. Or at any rate we initialise the quartet of global
|
|
variables detailing the current list-writing process, and begin.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">[ WriteListFrom first in_style depth noactivity iter a ol;</span>
|
|
<span class="plain">@push c_iterator; @push c_style; @push c_depth; @push c_margin;</span>
|
|
<span class="plain">if (iter) c_iterator = iter; else c_iterator = ObjectTreeIterator;</span>
|
|
<span class="plain">c_style = in_style; c_depth = depth;</span>
|
|
<span class="plain">c_margin = 0; if (in_style & EXTRAINDENT_BIT) c_margin = 1;</span>
|
|
|
|
<span class="plain">objectloop (a ofclass Object) {</span>
|
|
<span class="plain">give a list_filter_permits;</span>
|
|
<span class="plain">if ((list_filter_routine) && (list_filter_routine(a) == false))</span>
|
|
<span class="plain">give a ~list_filter_permits;</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="plain">first = c_iterator(first, depth, 0, START_ITF);</span>
|
|
<span class="plain">if (first == nothing) {</span>
|
|
<span class="plain">if (in_style & ISARE_BIT ~= 0) LIST_WRITER_INTERNAL_RM('W');</span>
|
|
<span class="plain">else LIST_WRITER_INTERNAL_RM('Y');</span>
|
|
<span class="plain">if (in_style & NEWLINE_BIT ~= 0) new_line;</span>
|
|
<span class="plain">} else {</span>
|
|
<span class="plain">if ((noactivity) || (iter)) {</span>
|
|
<span class="plain">WriteListR(first, c_depth, true);</span>
|
|
<span class="plain">say__p = 1;</span>
|
|
<span class="plain">} else {</span>
|
|
<span class="plain">objectloop (ol provides list_together)</span>
|
|
<span class="plain">BlkValueCopy(ol.list_together, EMPTY_TEXT_VALUE);</span>
|
|
<span class="plain">CarryOutActivity(LISTING_CONTENTS_ACT, parent(first));</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="plain">@pull c_margin; @pull c_depth; @pull c_style; @pull c_iterator;</span>
|
|
<span class="plain">];</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP15"></a><b>§15. Standard Contents Listing Rule. </b>The default for the listing contents activity is to call this rule in its
|
|
"for" stage: note that this suppresses the use of the activity, to avoid
|
|
an infinite regress. The activity is used only for the default
|
|
<code class="display"><span class="extract">ObjectTreeIterator</span></code>, so there is no need to specify which is used.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">[ STANDARD_CONTENTS_LISTING_R;</span>
|
|
<span class="plain">WriteListFrom(child(parameter_value), c_style, c_depth, true);</span>
|
|
<span class="plain">];</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP16"></a><b>§16. Partitioning. </b>Given qualifying objects x_1, ..., x_j, we partition them into classes of
|
|
the equivalence relation x_i~ x_j if and only
|
|
</p>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<ul class="items"><li>(i) they both have a <code class="display"><span class="extract">plural</span></code> property (not necessarily the same), and
|
|
</li><li>(ii) neither will cause the list-maker to recurse downwards to show the
|
|
objects inside or on top of them, and
|
|
</li><li>(iii) if they cause the list-maker to add information about whether they
|
|
are worn, lighted or open, then it will add the same information about both, and
|
|
</li><li>(iv) they are considered identical by the parser, in that they respond to the
|
|
same syntaxes of name: so that it is impossible to find a TAKE X command such
|
|
that X matches one and not the other.
|
|
</li></ul>
|
|
<p class="inwebparagraph">The equivalence classes are numbered consecutively upwards from 1 to n,
|
|
in order of first appearance in the list. For each object x_i,
|
|
<code class="display"><span class="extract">partition_classes->(i-1)</span></code> is the number of its equivalence class. For each
|
|
equivalence class number c, <code class="display"><span class="extract">partition_class_sizes->c</span></code> is the number of
|
|
objects in this class.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">#Ifdef DBLW;</span>
|
|
<span class="plain">Global DBLW_no_classes; Global DBLW_no_objs;</span>
|
|
<span class="plain">[ DebugPartition partition_class_sizes partition_classes first depth i k o;</span>
|
|
<span class="plain">print "[Length of list is ", DBLW_no_objs, " with ", k, " plural.]^";</span>
|
|
<span class="plain">print "[Partitioned into ", DBLW_no_classes, " equivalence classes.]^";</span>
|
|
<span class="plain">for (i=1: i<=DBLW_no_classes : i++) {</span>
|
|
<span class="plain">print "Class ", i, " has size ", partition_class_sizes->i, "^";</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">for (k=0, o=first: k<DBLW_no_objs : k++, o = c_iterator(o, depth, lt_value, ADVANCE_ITF)) {</span>
|
|
<span class="plain">print "Entry ", k, " has class ", partition_classes->k,</span>
|
|
<span class="plain">" represented by ", o, " with L=", o.list_together, "^";</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">];</span>
|
|
<span class="plain">#Endif;</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP17"></a><b>§17. Partition List. </b>The following creates the <code class="display"><span class="extract">partition_classes</span></code> and <code class="display"><span class="extract">partition_class_sizes</span></code>
|
|
accordingly. We return n, the number of classes.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">[ PartitionList first no_objs depth partition_classes partition_class_sizes</span>
|
|
<span class="plain">i k l n m;</span>
|
|
<span class="plain">for (i=0: i<no_objs: i++) partition_classes->i = 0;</span>
|
|
<span class="plain">n = 1;</span>
|
|
<span class="plain">for (i=first, k=0: k<no_objs: i=c_iterator(i, depth, lt_value, ADVANCE_ITF), k++)</span>
|
|
<span class="plain">if (partition_classes->k == 0) {</span>
|
|
<span class="plain">partition_classes->k = n; partition_class_sizes->n = 1;</span>
|
|
<span class="plain">for (l=c_iterator(i, depth, lt_value, ADVANCE_ITF), m=k+1:</span>
|
|
<span class="plain">(l~=0) && (m<no_objs):</span>
|
|
<span class="plain">l=c_iterator(l, depth, lt_value, ADVANCE_ITF), m++) {</span>
|
|
<span class="plain">if ((partition_classes->m == 0) && (ListEqual(i, l))) {</span>
|
|
<span class="plain">if (partition_class_sizes->n < 255) (partition_class_sizes->n)++;</span>
|
|
<span class="plain">partition_classes->m = n;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">if (n < 255) n++;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">n--;</span>
|
|
<span class="plain">#Ifdef DBLW;</span>
|
|
<span class="plain">DBLW_no_classes = n; DBLW_no_objs = no_objs;</span>
|
|
<span class="plain">DebugPartition(partition_class_sizes, partition_classes, first, depth);</span>
|
|
<span class="plain">#Endif;</span>
|
|
<span class="plain">return n;</span>
|
|
<span class="plain">];</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP18"></a><b>§18. Equivalence Relation. </b>The above algorithm will fail unless <code class="display"><span class="extract">ListEqual</span></code> is indeed reflexive, symmetric
|
|
and transitive, which ultimately depends on the care with which <code class="display"><span class="extract">Identical</span></code>
|
|
is implemented, which in turn hangs on the <code class="display"><span class="extract">parse_noun</span></code> properties compiled
|
|
by NI. But this seems to be sound.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">[ ListEqual o1 o2;</span>
|
|
<span class="plain">if ((o1.plural == 0) || (o2.plural == 0)) rfalse;</span>
|
|
<span class="plain">if (child(o1) ~= 0 && WillRecurs(o1) ~= 0) rfalse;</span>
|
|
<span class="plain">if (child(o2) ~= 0 && WillRecurs(o2) ~= 0) rfalse;</span>
|
|
<span class="plain">if (c_style & (FULLINV_BIT + PARTINV_BIT) ~= 0) {</span>
|
|
<span class="plain">if ((o1 hasnt worn && o2 has worn) || (o2 hasnt worn && o1 has worn)) rfalse;</span>
|
|
<span class="plain">if ((o1 hasnt light && o2 has light) || (o2 hasnt light && o1 has light)) rfalse;</span>
|
|
<span class="plain">if (o1 has container) {</span>
|
|
<span class="plain">if (o2 hasnt container) rfalse;</span>
|
|
<span class="plain">if ((o1 has open && o2 hasnt open) || (o2 has open && o1 hasnt open))</span>
|
|
<span class="plain">rfalse;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">else if (o2 has container)</span>
|
|
<span class="plain">rfalse;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">return Identical(o1, o2);</span>
|
|
<span class="plain">];</span>
|
|
|
|
<span class="plain">[ WillRecurs o;</span>
|
|
<span class="plain">if (c_style & ALWAYS_BIT ~= 0) rtrue;</span>
|
|
<span class="plain">if (c_style & RECURSE_BIT == 0) rfalse;</span>
|
|
<span class="plain">if ((o has supporter) || ((o has container) && (o has open or transparent))) rtrue;</span>
|
|
<span class="plain">rfalse;</span>
|
|
<span class="plain">];</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP19"></a><b>§19. Grouping. </b>A "group" is a maximally-sized run of one or more adjacent partition
|
|
classes in the list whose first members have a common value of
|
|
<code class="display"><span class="extract">list_together</span></code> which is a routine or string, and which is not equal to
|
|
<code class="display"><span class="extract">lt_value</span></code>, the current grouping value. (As we see below, it's by setting
|
|
<code class="display"><span class="extract">lt_value</span></code> that we restrict attention to a particular group: if we reacted
|
|
to that as a <code class="display"><span class="extract">list_together</span></code> value here, then we would simply go around in
|
|
circles, and never be able to see the individual objects in the group.)
|
|
</p>
|
|
|
|
<p class="inwebparagraph">For instance, suppose we have objects with <code class="display"><span class="extract">list_together</span></code> values as follows,
|
|
where R_1 and R_2 are addresses of routines:
|
|
</p>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">coin| ($R_1$), |coin| ($R_1$), |box| ($R_2$), |statuette| (0), |coin| ($R_1$), |box</span>
|
|
(R_2)</pre>
|
|
|
|
<p class="inwebparagraph">Then the partition is 1, 1, 2, 3, 1, 2, so that the final output will be
|
|
something like "three coins, two boxes and a statuette" — with three
|
|
grouped terms. Here each partition class is the only member in its group,
|
|
so the number of groups is the same as the number of classes. (The above
|
|
list is not coalesced, so the R_1 values, for instance, are not
|
|
contiguous: we need to work in general with non-coalesced lists because
|
|
not every iterator function will be able to coalesce fully.)
|
|
</p>
|
|
|
|
<p class="inwebparagraph">But if we have something like this:
|
|
</p>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">coin| ($R_1$), |Q| ($R_2$), |W| ($R_2$), |coin| ($R_1$), |statuette| (0), |E| ($R_2$), |R</span>
|
|
(R_2)</pre>
|
|
|
|
<p class="inwebparagraph">then the partition is 1, 2, 3, 1, 4, 5, 6 and we have six classes in all.
|
|
But classes 2 and 3 are grouped together, as are classes 5 and 6, so we
|
|
end up with a list having just four groups: "two coins, the letters Q and
|
|
W from a Scrabble set, a statuette and the letters E and R from a Scrabble
|
|
set". (Again, this list has not been fully coalesced: if it had been, it
|
|
would be reordered <code class="display"><span class="extract">coin</span></code>, <code class="display"><span class="extract">coin</span></code>, <code class="display"><span class="extract">Q</span></code>, <code class="display"><span class="extract">W</span></code>, <code class="display"><span class="extract">E</span></code>, <code class="display"><span class="extract">R</span></code>, <code class="display"><span class="extract">statuette</span></code>, with
|
|
partition 1, 1, 2, 3, 4, 5, 6, and three groups: "two coins, the letters Q,
|
|
W, E and R from a Scrabble set and a statuette".)
|
|
</p>
|
|
|
|
<p class="inwebparagraph">The reason we do not group together classes with a common non-zero
|
|
<code class="display"><span class="extract">list_together</span></code> which is not a routine or string is that low values
|
|
of <code class="display"><span class="extract">list_together</span></code> are used in coalescing the list into a pleasing order
|
|
(say, moving all of the key-like items together) but not in grouping: see
|
|
<code class="display"><span class="extract">list_together</span></code> in the Inform Designer's Manual, 4th edition.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">We calculate the number of groups by starting with the number of classes
|
|
and then subtracting one each time two adjacent classes share <code class="display"><span class="extract">list_together</span></code>
|
|
in the above sense.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">[ NumberOfGroupsInList o no_classes depth partition_classes partition_class_sizes</span>
|
|
<span class="plain">no_groups cl memb k current_lt lt;</span>
|
|
<span class="plain">current_lt = EMPTY_TEXT_VALUE;</span>
|
|
<span class="plain">lt = EMPTY_TEXT_VALUE;</span>
|
|
<span class="plain">no_groups = no_classes;</span>
|
|
<span class="plain">for (cl=1, memb=o, k=0: cl<=no_classes: cl++) {</span>
|
|
<span class="plain">! Advance to first member of class number cl</span>
|
|
<span class="plain">while (partition_classes->k ~= cl) {</span>
|
|
<span class="plain">k++; memb = c_iterator(memb, depth, lt_value, ADVANCE_ITF);</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">if (memb) { ! In case of accidents, but should always happen</span>
|
|
<span class="plain">lt = memb.list_together;</span>
|
|
<span class="plain">if ((LT_Compare(lt, lt_value) ~= 0) &&</span>
|
|
<span class="plain">(LT_Compare(lt, EMPTY_TEXT_VALUE) ~= 0) &&</span>
|
|
<span class="plain">(LT_Compare(lt, current_lt) == 0)) {</span>
|
|
<span class="plain">no_groups--;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">current_lt = lt;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">#Ifdef DBLW; print "[There are ", no_groups, " groups.]^"; #Endif;</span>
|
|
<span class="plain">return no_groups;</span>
|
|
<span class="plain">];</span>
|
|
|
|
<span class="plain">[ LT_Compare lt1 lt2;</span>
|
|
<span class="plain">if (lt1 == lt2) return 0;</span>
|
|
<span class="plain">if (lt1 == 0) lt1 = EMPTY_TEXT_VALUE;</span>
|
|
<span class="plain">if (lt2 == 0) lt2 = EMPTY_TEXT_VALUE;</span>
|
|
<span class="plain">if (TEXT_TY_IsSubstituted(lt1) == false) {</span>
|
|
<span class="plain">if (TEXT_TY_IsSubstituted(lt2) == false) return (lt1-->1)-(lt2-->1);</span>
|
|
<span class="plain">return -1;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">if (TEXT_TY_IsSubstituted(lt2) == false) {</span>
|
|
<span class="plain">return -1;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">return BlkValueCompare(lt1, lt2);</span>
|
|
<span class="plain">];</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP20"></a><b>§20. Write List Recursively. </b>The big one: <code class="display"><span class="extract">WriteListR</span></code> is the heart of the list-writer.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">[ WriteListR o depth from_start</span>
|
|
<span class="plain">partition_classes partition_class_sizes</span>
|
|
<span class="plain">cl memb index k2 l m no_classes q groups_to_do current_lt;</span>
|
|
<span class="plain">if (o == nothing) return; ! An empty list: no output</span>
|
|
|
|
<span class="plain">if (from_start) {</span>
|
|
<span class="plain">o = c_iterator(o, depth, 0, COALESCE_ITF); ! Coalesce list and choose new start</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">o = c_iterator(o, depth, 0, SEEK_ITF); ! Find first entry in list from o</span>
|
|
<span class="plain">if (o == nothing) return;</span>
|
|
|
|
<span class="plain">! Count index = length of list</span>
|
|
<span class="plain">for (memb=o, index=0: memb: memb=c_iterator(memb, depth, lt_value, ADVANCE_ITF)) index++;</span>
|
|
|
|
<span class="plain">if (c_style & ISARE_BIT ~= 0) {</span>
|
|
<span class="plain">SetLWI(index, -1, o);</span>
|
|
<span class="plain">LIST_WRITER_INTERNAL_RM('V', o);</span>
|
|
<span class="plain">if (c_style & NEWLINE_BIT ~= 0) print ":^";</span>
|
|
<span class="plain">else print (char) ' ';</span>
|
|
<span class="plain">c_style = c_style - ISARE_BIT;</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="plain">partition_classes = RequisitionStack(index/WORDSIZE + 2);</span>
|
|
<span class="plain">partition_class_sizes = RequisitionStack(index/WORDSIZE + 2);</span>
|
|
<span class="plain">if ((partition_classes == 0) || (partition_class_sizes == 0))</span>
|
|
<span class="plain">return RunTimeProblem(RTP_LISTWRITERMEMORY);</span>
|
|
|
|
<span class="plain">no_classes =</span>
|
|
<span class="plain">PartitionList(o, index, depth, partition_classes, partition_class_sizes);</span>
|
|
|
|
<span class="plain">groups_to_do =</span>
|
|
<span class="plain">NumberOfGroupsInList(o, no_classes, depth, partition_classes, partition_class_sizes);</span>
|
|
|
|
<span class="plain">for (cl=1, memb=o, index=0, current_lt=EMPTY_TEXT_VALUE: groups_to_do>0: cl++) {</span>
|
|
<span class="plain">! Set memb to first object of partition class cl</span>
|
|
<span class="plain">while (partition_classes->index ~= cl) {</span>
|
|
<span class="plain">index++; memb=c_iterator(memb, depth, lt_value, ADVANCE_ITF);</span>
|
|
<span class="plain">if (memb==0) { print "*** Error in list-writer ***^"; return; }</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="plain">#Ifdef DBLW;</span>
|
|
<span class="plain">! DebugPartition(partition_class_sizes, partition_classes, o, depth);</span>
|
|
<span class="plain">print "^[Class ", cl, " of ", no_classes, ": first object ", memb,</span>
|
|
<span class="plain">" (", memb.list_together, "); groups_to_do ", groups_to_do, ",</span>
|
|
<span class="plain">current_lt=", current_lt, " listing_size=", listing_size,</span>
|
|
<span class="plain">" lt_value=", lt_value, " memb.list_together=", memb.list_together, "]^";</span>
|
|
<span class="plain">#Endif;</span>
|
|
|
|
<span class="plain">if ((LT_Compare(memb.list_together, lt_value) == 0) ||</span>
|
|
<span class="plain">(LT_Compare(memb.list_together, EMPTY_TEXT_VALUE) == 0)) current_lt = EMPTY_TEXT_VALUE;</span>
|
|
<span class="plain">else {</span>
|
|
<span class="plain">if (LT_Compare(memb.list_together, current_lt) == 0) continue;</span>
|
|
|
|
<span class="plain">! Otherwise this class begins a new group</span>
|
|
<span class="plain">@push listing_size;</span>
|
|
<span class="plain">q = memb; listing_size = 1; l = index; m = cl;</span>
|
|
<span class="plain">while (m < no_classes &&</span>
|
|
<span class="plain">(LT_Compare(q.list_together, memb.list_together) == 0)) {</span>
|
|
<span class="plain">m++;</span>
|
|
<span class="plain">while (partition_classes->l ~= m) {</span>
|
|
<span class="plain">l++; q = c_iterator(q, depth, lt_value, ADVANCE_ITF);</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">if (LT_Compare(q.list_together, memb.list_together) == 0)</span>
|
|
<span class="plain">listing_size++;</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="plain">if (listing_size > 1) {</span>
|
|
<span class="plain">! The new group contains more than one partition class</span>
|
|
<span class="plain">WriteMultiClassGroup(cl, memb, depth, partition_class_sizes);</span>
|
|
<span class="plain">current_lt = memb.list_together;</span>
|
|
<span class="plain">jump GroupComplete;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">current_lt = EMPTY_TEXT_VALUE;</span>
|
|
<span class="plain">@pull listing_size;</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="plain">WriteSingleClassGroup(cl, memb, depth, partition_class_sizes->cl);</span>
|
|
|
|
<span class="plain">.GroupComplete;</span>
|
|
<span class="plain">groups_to_do--;</span>
|
|
<span class="plain">if (c_style & ENGLISH_BIT ~= 0) {</span>
|
|
<span class="plain">if (groups_to_do == 1) {</span>
|
|
<span class="plain">if (TEMPLATE_CONFIGURATION_BITMAP & SERIAL_COMMA_TCBIT) {</span>
|
|
<span class="plain">if (cl > 1) print ",";</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">LIST_WRITER_INTERNAL_RM('C');</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">if (groups_to_do > 1) print ", ";</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="plain">FreeStack(partition_class_sizes);</span>
|
|
<span class="plain">FreeStack(partition_classes);</span>
|
|
<span class="plain">]; ! end of WriteListR</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP21"></a><b>§21. Write Multiple Class Group. </b>The text of a single group which contains more than one partition class.
|
|
We carry out the "grouping together" activity, so that the user can add
|
|
text fore and aft — this is how groups of objects such as "X, Y and Z"
|
|
can be fluffed up to "the letters X, Y and Z from a Scrabble set" —
|
|
but the default is simple: we print the grouped items by calling
|
|
<code class="display"><span class="extract">WriteListR</span></code> once again, but this time starting from X, and where
|
|
<code class="display"><span class="extract">lt_value</span></code> is set to the common <code class="display"><span class="extract">list_together</span></code> value of X, Y and Z.
|
|
(That restricts the list to just the objects in this group.) Because
|
|
<code class="display"><span class="extract">lt_value</span></code> is set to this value, the grouping code won't then group X, Y
|
|
and Z again, and they will instead be individual classes in the new
|
|
list — so each will end up being sent, in turn, to <code class="display"><span class="extract">WriteSingleClassGroup</span></code>
|
|
below, and that is where they are printed.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">[ WriteMultiClassGroup cl memb depth partition_class_sizes pv q k2 l;</span>
|
|
<span class="plain">! Save the style, because the activity below is allowed to change it</span>
|
|
<span class="plain">q = c_style;</span>
|
|
<span class="plain">if (c_style & INDENT_BIT ~= 0) PrintSpaces(2*(depth+c_margin));</span>
|
|
|
|
<span class="plain">BeginActivity(GROUPING_TOGETHER_ACT, memb);</span>
|
|
|
|
<span class="plain">if (ForActivity(GROUPING_TOGETHER_ACT, memb)) {</span>
|
|
<span class="plain">c_style = c_style &~ NEWLINE_BIT;</span>
|
|
<span class="plain">} else {</span>
|
|
<span class="plain">pv = memb.list_together;</span>
|
|
<span class="plain">if (TEXT_TY_IsSubstituted(pv) == false) {</span>
|
|
<span class="plain">inventory_stage = 1;</span>
|
|
<span class="plain">parser_one = memb; parser_two = depth + c_margin;</span>
|
|
<span class="plain">if ((pv-->1)() == 1) jump Omit__Sublist2;</span>
|
|
<span class="plain">} else if (pv) {</span>
|
|
<span class="plain">! Set k2 to the number of objects covered by the group</span>
|
|
<span class="plain">k2 = 0;</span>
|
|
<span class="plain">for (l=0 : l<listing_size : l++) k2 = k2 + partition_class_sizes->(l+cl);</span>
|
|
<span class="plain">EnglishNumber(k2); print " ";</span>
|
|
<span class="plain">print (TEXT_TY_Say) pv;</span>
|
|
<span class="plain">if (c_style & ENGLISH_BIT ~= 0) print " (";</span>
|
|
<span class="plain">if (c_style & INDENT_BIT ~= 0) print ":^";</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="plain">c_margin++;</span>
|
|
<span class="plain">@push lt_value; @push listing_together; @push listing_size;</span>
|
|
|
|
<span class="plain">lt_value = memb.list_together; listing_together = memb;</span>
|
|
<span class="plain">#Ifdef DBLW; print "^^DOWN lt_value = ", lt_value, " listing_together = ", memb, "^^";</span>
|
|
<span class="plain">@push DBLW_no_classes; @push DBLW_no_objs; #Endif;</span>
|
|
<span class="plain">WriteListR(memb, depth, false);</span>
|
|
<span class="plain">#Ifdef DBLW; print "^^UP^^"; @pull DBLW_no_objs; @pull DBLW_no_classes; #Endif;</span>
|
|
|
|
<span class="plain">@pull listing_size; @pull listing_together; @pull lt_value;</span>
|
|
<span class="plain">c_margin--;</span>
|
|
|
|
<span class="plain">pv = memb.list_together;</span>
|
|
<span class="plain">if (TEXT_TY_IsSubstituted(pv) == false) {</span>
|
|
<span class="plain">inventory_stage = 2;</span>
|
|
<span class="plain">parser_one = memb; parser_two = depth+c_margin;</span>
|
|
<span class="plain">(pv-->1)();</span>
|
|
<span class="plain">} else if (LT_Compare(pv, EMPTY_TEXT_VALUE) ~= 0) {</span>
|
|
<span class="plain">if (q & ENGLISH_BIT ~= 0) print ")";</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">.Omit__Sublist2;</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="plain">EndActivity(GROUPING_TOGETHER_ACT, memb);</span>
|
|
|
|
<span class="plain">! If the NEWLINE_BIT has been forced by the activity, act now</span>
|
|
<span class="plain">! before it vanishes...</span>
|
|
<span class="plain">if (q & NEWLINE_BIT ~= 0 && c_style & NEWLINE_BIT == 0) new_line;</span>
|
|
|
|
<span class="plain">! ...when the original style is restored again:</span>
|
|
<span class="plain">c_style = q;</span>
|
|
<span class="plain">];</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP22"></a><b>§22. Write Single Class Group. </b>The text of a single group which contains exactly one partition class.
|
|
Because of the way the multiple-class case recurses, every class ends up
|
|
in this routine sooner or later; this is the place where the actual
|
|
name of an object is printed, at long last.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">[ WriteSingleClassGroup cl memb depth size q;</span>
|
|
<span class="plain">q = c_style;</span>
|
|
<span class="plain">if (c_style & INDENT_BIT) PrintSpaces(2*(depth+c_margin));</span>
|
|
<span class="plain">if (size == 1) {</span>
|
|
<span class="plain">if (c_style & NOARTICLE_BIT ~= 0) print (name) memb;</span>
|
|
<span class="plain">else {</span>
|
|
<span class="plain">if (c_style & DEFART_BIT) {</span>
|
|
<span class="plain">if ((cl == 1) && (c_style & CFIRSTART_BIT)) print (The) memb;</span>
|
|
<span class="plain">else print (the) memb;</span>
|
|
<span class="plain">} else {</span>
|
|
<span class="plain">if ((cl == 1) && (c_style & CFIRSTART_BIT)) print (CIndefArt) memb;</span>
|
|
<span class="plain">else print (a) memb;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">} else {</span>
|
|
<span class="plain">if (c_style & DEFART_BIT) {</span>
|
|
<span class="plain">if ((cl == 1) && (c_style & CFIRSTART_BIT)) PrefaceByArticle(memb, 0, size);</span>
|
|
<span class="plain">else PrefaceByArticle(memb, 1, size);</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">@push listing_size; listing_size = size;</span>
|
|
<span class="plain">CarryOutActivity(PRINTING_A_NUMBER_OF_ACT, memb);</span>
|
|
<span class="plain">@pull listing_size;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">if ((size > 1) && (memb hasnt pluralname)) {</span>
|
|
<span class="plain">give memb pluralname;</span>
|
|
<span class="plain">WriteAfterEntry(memb, depth);</span>
|
|
<span class="plain">give memb ~pluralname;</span>
|
|
<span class="plain">} else WriteAfterEntry(memb, depth);</span>
|
|
<span class="plain">c_style = q;</span>
|
|
<span class="plain">];</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP23"></a><b>§23. Write After Entry. </b>Each entry can be followed by supplementary, usually parenthetical, information:
|
|
exactly what, depends on the style. The extreme case is when the style, and
|
|
the object, call for recursion to list the object-tree contents: this is
|
|
achieved by calling <code class="display"><span class="extract">WriteListR</span></code>, using the <code class="display"><span class="extract">ObjectTreeIterator</span></code> (whatever
|
|
the iterator used at the top level) and increasing the depth by 1.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">[ WriteAfterEntry o depth</span>
|
|
<span class="plain">p recurse_flag parenth_flag eldest_child child_count combo;</span>
|
|
|
|
<span class="plain">inventory_stage = 2;</span>
|
|
<span class="plain">if (c_style & PARTINV_BIT) {</span>
|
|
<span class="plain">BeginActivity(PRINTING_ROOM_DESC_DETAILS_ACT, o);</span>
|
|
<span class="plain">if (ForActivity(PRINTING_ROOM_DESC_DETAILS_ACT, o) == false) {</span>
|
|
<span class="plain">combo = 0;</span>
|
|
<span class="plain">if (o has light && location hasnt light) combo=combo+1;</span>
|
|
<span class="plain">if (o has container && o hasnt open) combo=combo+2;</span>
|
|
<span class="plain">if ((o has container && (o has open || o has transparent))</span>
|
|
<span class="plain">&& (child(o)==0)) combo=combo+4;</span>
|
|
<span class="plain">if (combo) LIST_WRITER_INTERNAL_RM('A'); ! space and open bracket</span>
|
|
<span class="plain">switch (combo) {</span>
|
|
<span class="plain">1: LIST_WRITER_INTERNAL_RM('D', o);</span>
|
|
<span class="plain">2: LIST_WRITER_INTERNAL_RM('E', o);</span>
|
|
<span class="plain">3: LIST_WRITER_INTERNAL_RM('H', o);</span>
|
|
<span class="plain">4: LIST_WRITER_INTERNAL_RM('F', o);</span>
|
|
<span class="plain">5: LIST_WRITER_INTERNAL_RM('I', o);</span>
|
|
<span class="plain">6: LIST_WRITER_INTERNAL_RM('G', o);</span>
|
|
<span class="plain">7: LIST_WRITER_INTERNAL_RM('J', o);</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">if (combo) LIST_WRITER_INTERNAL_RM('B'); ! close bracket</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">EndActivity(PRINTING_ROOM_DESC_DETAILS_ACT, o);</span>
|
|
<span class="plain">} ! end of PARTINV_BIT processing</span>
|
|
|
|
<span class="plain">if (c_style & FULLINV_BIT) {</span>
|
|
<span class="plain">BeginActivity(PRINTING_INVENTORY_DETAILS_ACT, o);</span>
|
|
<span class="plain">if (ForActivity(PRINTING_INVENTORY_DETAILS_ACT, o) == false) {</span>
|
|
<span class="plain">if (o has light && o has worn) { LIST_WRITER_INTERNAL_RM('A'); LIST_WRITER_INTERNAL_RM('K', o); parenth_flag = true; }</span>
|
|
<span class="plain">else {</span>
|
|
<span class="plain">if (o has light) { LIST_WRITER_INTERNAL_RM('A'); LIST_WRITER_INTERNAL_RM('D', o); parenth_flag = true; }</span>
|
|
<span class="plain">if (o has worn) { LIST_WRITER_INTERNAL_RM('A'); LIST_WRITER_INTERNAL_RM('L', o); parenth_flag = true; }</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="plain">if (o has container) {</span>
|
|
<span class="plain">if (o has openable) {</span>
|
|
<span class="plain">if (parenth_flag) {</span>
|
|
<span class="plain">if (TEMPLATE_CONFIGURATION_BITMAP & SERIAL_COMMA_TCBIT)</span>
|
|
<span class="plain">print ",";</span>
|
|
<span class="plain">LIST_WRITER_INTERNAL_RM('C');</span>
|
|
<span class="plain">} else LIST_WRITER_INTERNAL_RM('A', o);</span>
|
|
<span class="plain">if (o has open) {</span>
|
|
<span class="plain">if (child(o)) LIST_WRITER_INTERNAL_RM('M', o);</span>
|
|
<span class="plain">else LIST_WRITER_INTERNAL_RM('N', o);</span>
|
|
<span class="plain">} else {</span>
|
|
<span class="plain">if (o has lockable && o has locked) LIST_WRITER_INTERNAL_RM('P', o);</span>
|
|
<span class="plain">else LIST_WRITER_INTERNAL_RM('O', o);</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">parenth_flag = true;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">else {</span>
|
|
<span class="plain">if (child(o)==0 && o has transparent) {</span>
|
|
<span class="plain">if (parenth_flag) { LIST_WRITER_INTERNAL_RM('C'); LIST_WRITER_INTERNAL_RM('F'); }</span>
|
|
<span class="plain">else { LIST_WRITER_INTERNAL_RM('A'); LIST_WRITER_INTERNAL_RM('F'); LIST_WRITER_INTERNAL_RM('B'); }</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">if (parenth_flag) LIST_WRITER_INTERNAL_RM('B');</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">EndActivity(PRINTING_INVENTORY_DETAILS_ACT, o);</span>
|
|
<span class="plain">} ! end of FULLINV_BIT processing</span>
|
|
|
|
<span class="plain">child_count = 0;</span>
|
|
<span class="plain">eldest_child = nothing;</span>
|
|
<span class="plain">objectloop (p in o)</span>
|
|
<span class="plain">if ((c_style & CONCEAL_BIT == 0) || (ConcealedFromLists(p) == false))</span>
|
|
<span class="plain">if (p has list_filter_permits) {</span>
|
|
<span class="plain">child_count++;</span>
|
|
<span class="plain">if (eldest_child == nothing) eldest_child = p;</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="plain">if (child_count && (c_style & ALWAYS_BIT)) {</span>
|
|
<span class="plain">if (c_style & ENGLISH_BIT) { print " "; LIST_WRITER_INTERNAL_RM('Q', o); print " "; }</span>
|
|
<span class="plain">recurse_flag = true;</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="plain">if (child_count && (c_style & RECURSE_BIT)) {</span>
|
|
<span class="plain">if (o has supporter) {</span>
|
|
<span class="plain">if (c_style & ENGLISH_BIT) {</span>
|
|
<span class="plain">if (c_style & TERSE_BIT) {</span>
|
|
<span class="plain">LIST_WRITER_INTERNAL_RM('A', o);</span>
|
|
<span class="plain">LIST_WRITER_INTERNAL_RM('R', o);</span>
|
|
<span class="plain">} else LIST_WRITER_INTERNAL_RM('S', o);</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">recurse_flag = true;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">if (o has container && (o has open || o has transparent)) {</span>
|
|
<span class="plain">if (c_style & ENGLISH_BIT) {</span>
|
|
<span class="plain">if (c_style & TERSE_BIT) {</span>
|
|
<span class="plain">LIST_WRITER_INTERNAL_RM('A', o);</span>
|
|
<span class="plain">LIST_WRITER_INTERNAL_RM('T', o);</span>
|
|
<span class="plain">} else LIST_WRITER_INTERNAL_RM('U', o);</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">recurse_flag = true;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="plain">if (recurse_flag && (c_style & ENGLISH_BIT)) {</span>
|
|
<span class="plain">SetLWI(child_count, -1, eldest_child);</span>
|
|
<span class="plain">LIST_WRITER_INTERNAL_RM('V', o); print " ";</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="plain">if (c_style & NEWLINE_BIT) new_line;</span>
|
|
|
|
<span class="plain">if (recurse_flag) {</span>
|
|
<span class="plain">o = child(o);</span>
|
|
<span class="plain">@push lt_value; @push listing_together; @push listing_size;</span>
|
|
<span class="plain">@push c_iterator;</span>
|
|
<span class="plain">c_iterator = ObjectTreeIterator;</span>
|
|
<span class="plain">lt_value = EMPTY_TEXT_VALUE; listing_together = 0; listing_size = 0;</span>
|
|
<span class="plain">WriteListR(o, depth+1, true);</span>
|
|
<span class="plain">@pull c_iterator;</span>
|
|
<span class="plain">@pull listing_size; @pull listing_together; @pull lt_value;</span>
|
|
<span class="plain">if (c_style & TERSE_BIT) LIST_WRITER_INTERNAL_RM('B');</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">];</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP24"></a><b>§24. Internal Rule. </b>This rule does nothing in itself; it exists as a placeholder for the
|
|
response texts used by the list-writer.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">[ LIST_WRITER_INTERNAL_R;</span>
|
|
<span class="plain">];</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<hr class="tocbar">
|
|
<ul class="toc"><li><a href="S-lt2.html">Back to 'Light Template'</a></li><li><a href="S-mpr.html">Continue with 'MapRouteFinding'</a></li></ul><hr class="tocbar">
|
|
<!--End of weave-->
|
|
</body>
|
|
</html>
|
|
|