Section 23: Listing and grouping objects

Contents Back Forward | ### 23. Listing and grouping objects
| As some day it may happen that a victim must be found I've got a little list -- I've got a little list Of society offenders who might well be underground, And who never would be missed Who never would be missed! ...W. S. Gilbert (1836--1911), The Mikado The library often needs to reel off a list of objects: when an `Inv` (inventory) action takes place, for instance, or when describing the contents of a container or the duller items in a room. Lists are difficult to print out correctly 'by hand', because there are many cases to get right, especially when taking plurals into account. Fortunately, the library's list-maker is available to the public. The routine to call is:
    WriteListFrom(object, style);
where the list will start from the given object and go along its siblings. Thus, to list all the objects inside `X`, list from `child(X)`. What the list looks like depends on the "style'', which is a bitmap you can make by adding some of the following constants:
`NEWLINE_BIT` | New-line after each entry
`INDENT_BIT` | Indent each entry according to depth
`FULLINV_BIT` | Full inventory information after entry
`ENGLISH_BIT` | English sentence style, with commas and 'and'
`RECURSE_BIT` | Recurse downwards with usual rules
`ALWAYS_BIT` | Always recurse downwards
`TERSE_BIT` | More terse English style
`PARTINV_BIT` | Only brief inventory information after entry
`DEFART_BIT` | Use the definite article in list
`WORKFLAG_BIT` | At top level (only), only list objects
| which have the `workflag` attribute
`ISARE_BIT` | Prints " is " or " are " before list
`CONCEAL_BIT` | Misses out `concealed` or `scenery` objects
The best way to use this is to experiment. For example, a 'tall' inventory is produced by:
    WriteListFrom( child(player),
                   FULLINV_BIT + INDENT_BIT + NEWLINE_BIT + RECURSE_BIT );
and a 'wide' one by:
    WriteListFrom( child(player),
                   FULLINV_BIT + ENGLISH_BIT + RECURSE_BIT );
which produce effects like:
    >inventory tall
    You are carrying:
      a bag (which is open)
        three gold coins
        two silver coins
        a bronze coin
      four featureless white cubes
      a magic burin
      a spell book
    >inventory wide
    You are carrying a bag (which is open), inside which are three gold
    coins, two silver coins and a bronze coin, four featureless white
    cubes, a magic burin and a spell book.
except that the 'You are carrying' part is not done by the list-maker, and nor is the final full stop in the second example. The `workflag` is an attribute which the library scribbles over from time to time as temporary storage, but you can use it with care. In this case it makes it possible to specify any reasonable list.
| `WORKFLAG_BIT` and `CONCEAL_BIT` specify conflicting rules. If they're both given, then what happens is: at the top level, but not below, everything with `workflag` is included; on lower levels, but not at the top, everything without `concealed` or `scenery` is included.
| EXERCISE 52: (link to the answer)
| Write a `DoubleInvSub` action routine to produce an inventory like so:
    You are carrying four featureless white cubes, a magic burin and a
    spell book.  In addition, you are wearing a purple cloak and a miner's
    helmet.
| Finally, there is a neat way to customise the grouping together of non-identical items in lists, considerably enhancing the presentation of the game. If a collection of game objects -- say, all the edible items in the game -- have a common non-zero value of the property `list_together`, in the range 1 to 1000, they will always appear adjacently in inventories, room descriptions and the like.
| Alternatively, instead of being a small number the common value can be a string such as `"foodstuffs"`. If so then lists will cite, e.g., three foodstuffs (a scarlet fish, some lemmas and an onion) in running text, or three foodstuffs: `` a scarlet fish `` some lemmas `` an onion in indented lists. This only happens when two or more are gathered together. Finally, the common value can be a routine, such as:
    list_together
    [; if (inventory_stage==1) print "heaps of food, notably ";
       else print ", which would do you no good";
    ],
Typically this might be part of a class definition from which all the objects in question inherit. A `list_together` routine will be called twice: once, with `inventory_stage` set to 1, as a preamble to the list of items, and once (with 2) to print any postscript required. It is allowed to change `c_style` (the current list style) without needing to restore the old value and may, by returning 1 from stage 1, signal the list-maker not to print a list at all. The simple example above results in heaps of food, notably a scarlet fish, some lemmas and an onion, which would do you no good Such a routine may want to make use of the variables `parser_one` and `parser_two`, which respectively hold the first object in the group and the depth of recursion in the list (this might be needed to keep indentation going properly). Applying `x=NextEntry(x,parser_two);` moves `x` on from `parser_one` to the next item in the group. Another helpful variable is `listing_together`, set up to the first object of a group being listed or to 0 whenever no group is being listed. The following list of 24 items shows some possible effects (see the example game 'List Property'): You can see a plastic fork, knife and spoon, three hats (a fez, a Panama and a sombrero), the letters X, Y, Z, P, Q and R from a Scrabble set, a defrosting Black Forest gateau, Punch magazine, a recent issue of the Spectator, a die and eight coins (four silver, one bronze and three gold) here.
| EXERCISE 53: (link to the answer)
| Implement the Scrabble pieces.
| EXERCISE 54: (link to the answer)
| Implement the three denominations of coin.
| EXERCISE 55: (link to the answer)
| Implement the I Ching in the form of six coins, three gold (goat, deer and chicken), three silver (robin, snake and bison) which can be thrown to reveal gold and silver trigrams.
| REFERENCES: A good example of `WriteListFrom` in action is the definition of `CarryingClass` from the example game 'The Thief', by Gareth Rees. This alters the examine description of a character by appending a list of what that person is carrying and wearing. Denominations of coin are also in evidence in 'Balances'.

Contents / Back / Forward
Chapter I / Chapter II / Chapter III / Chapter IV / Chapter V / Chapter VI / Appendix

Mechanically translated to HTML from third edition as revised 16 May 1997. Copyright © Graham Nelson 1993, 1994, 1995, 1996, 1997: all rights reserved.