DM4 §21: Starting, moving, changing and killing the player

## §21 Starting, moving, changing and killing the player

> Life's but a walking shadow, a poor player
> That struts and frets his hour upon the stage
> And then is heard no more; it is a tale
> Told by an idiot, full of sound and fury,
> Signifying nothing.
> — William Shakespeare (1564–1616), Macbeth V v

To recap on §4, an “entry point routine” is one provided by your own source code which the library may call from time to time. There are about twenty of these, listed in §A5, and all of them are optional but one: `Initialise`. This routine is called before any text of the game is printed, and it can do many things: start timers and daemons, set the time of day, equip the player with possessions, make any random settings needed and so on. It usually prints out some welcoming text, though not the name and author of the game, because that appears soon after when the “game banner” is printed. The only thing it must do is to set the `location` variable to where the player begins.

This is usually a room, possibly in darkness, but might instead be an `enterable` object inside a room, such as a chair or a bed. Like medieval romance epics, interactive fiction games often start by waking the player from sleep, sometimes by way of a dream sequence. If your game begins with verbose instructions before the first opportunity for a player to type a command, you may want to offer the chance to restore a saved game at once:

    print "Would you like to restore a game? >";
    if (YesOrNo()) <Restore>;

To equip the player with possessions, simply move the relevant objects to `player`.

The return value from `Initialise` is ordinarily ignored, whether `true` or `false`, and the library goes on to print the game banner. If, however, you return 2, the game banner is suppressed for now. This feature is provided for games like ‘Sorcerer’ and ‘Seastalker’ which play out a short prelude first. If you do suppress the banner from `Initialise`, you should print it no more than a few turns later on by calling the library routine `Banner`. The banner is familiar to players, reassuringly traditional and useful when testing, because it identifies which version of a game is giving trouble. Like an imprint page with an ISBN, it is invaluable to bibliographers and collectors of story files.

· · · · ·

‘Ruins’ opens in classical fashion:

    [ Initialise;
      TitlePage();
      location = Forest;
      move map to player;
      move sodium_lamp to player;
      move dictionary to player;
      thedark.description = "The darkness of ages presses in on you, and
          you feel claustrophobic.";
      "^^^Days of searching, days of thirsty hacking through the briars of
      the forest, but at last your patience was rewarded. A discovery!^";
    ];

For the source code of the ‘Ruins’ `TitlePage` routine, see the exercises in §42.

· · · · ·

The question “where is the player?” can be answered in three different ways. Looking at `parent(player)` tells you the object immediately containing the player, which can be a location but might instead be a chair or vehicle. So a condition such as:

    if (player in Bridleway) ...

would be `false` if the player were riding a horse through the Bridleway. The safer alternative is:

    if (location == Bridleway) ...

but even this would be `false` if the Bridleway were in darkness, because then `location` would be the special object `thedark` (see §19). The definitive location value is stored in `real_location`, so that:

    if (real_location == Bridleway) ...

works in all cases. The condition for “is the player in a dark Bridleway?” is:

    if (location == thedark && real_location == Bridleway) ...

Except for the one time in `Initialise`, you should not attempt to change either of these variables, nor to move the player-object by hand. One safe way to move the player in your own source code is to cause actions like

    <Go n_obj>;

but for moments of teleportation it's easier to use the library routine `PlayerTo`. Calling `PlayerTo(somewhere)` makes the parent-object of the player `somewhere` and adjusts the `location` variables accordingly: it also runs through a fair number of standard game rules, for instance checking the light level and performing a `Look` action to print out the new room description. The value `somewhere` can be a room, or an `enterable` object such as a cage or a traction-engine, provided that the cardinal rule is always observed:

The parent of the player object must at all times be “location-like”. An object is “location-like” if either it is a location, or it has `enterable` and its parent is location-like.

In other words, you can't put the player in an `enterable` cardboard box if that box is itself shut up in a free-standing safe which isn't `enterable`. And you can't `PlayerTo(nothing)` or `PlayerTo(thedark)` because `nothing` is not an object and `thedark` is not location-like.

▲ Calling `PlayerTo(somewhere,1)` moves the player without printing any room description. All other standard game rules are applied.

▲ Calling `PlayerTo(somewhere,2)` is just like `PlayerTo(somewhere)` except that the room description is in the form the player would expect from typing “go east” rather than from typing “look”. The only difference is that in the former case the room is (normally) given an abbreviated description if it has been visited before, whereas in the latter case the description is always given in full.

· · · · ·

▲▲ It's perhaps worth taking a moment to say what the standard rules upon changing location are. The following rules are applied whenever a `Look` action or a call to `PlayerTo` take place.

0. If `PlayerTo` has been called then the `parent` of the player, `location` and `real_location` are set.
1. Any object providing `found_in` is checked. If it claims to be `found_in` the location, it is moved to that location. If not, or if it has `absent`, it is removed from the object tree. (See §8.)
2. The availability of light is checked (see §19), and `location` is set to `thedark` if necessary.
3. The “visibility ceiling” of the player is determined. For instance, the VC for a player in a closed wooden box is the box, but for a player in a closed glass box it's the location. To be more exact:
   1. The VC of a room is the value of `location`, i.e., either `thedark` or the room object.
   2. If the parent of an object is a room or is “see-through” (see §19 for this definition), the VC of the object is the VC of the parent.
   3. If not, the VC of the object is its parent.
4. If the VC is `thedark` or (say) a box, skip this rule. Otherwise: if the VC has changed since the previous time that rule (3) produced a VC which wasn't an `enterable` object, then:
   1. The message `location.initial()` is sent, if the location provides an `initial` rule. If the library finds that the player has been moved in the course of running `initial`, it goes back to rule (3).
   2. The game's entry point routine `NewRoom` is called, if it provides one.
5. The room description is printed out, unless these rules are being gone through by `PlayerTo(somewhere,1)`. For exactly what happens in printing a room description, see §26.
6. If the `location` doesn't have `visited`, give it this attribute and award the player `ROOM_SCORE` points if the `location` has `scored`. (See §22.) Note that this rule looks at `location`, not `real_location`, so no points unless the room is visible.

· · · · ·

In the course of this chapter, rules to interfere with actions have been attached to items, rooms and people, but not yet to the player. In §18 it was set out that an order like “austin, eat tuna” would result in the action `Eat tuna` being passed to `austin.orders`, and heavy hints were dropped that orders and actions are more or less the same thing. This is indeed so, and the player's own object has an `orders` routine. This normally does nothing and always returns `false` to mean “carry on as usual”, but you can install a rule of your own instead:

    player.orders = MyNewRule;

where `MyNewRule` is a new `orders` rule. This rule is applied to every action or order issued by the player. The variable actor holds the person asked to do something, usually but not always `player`, and the variables `action`, `noun` and `second` are set up as usual. For instance:

Example command | `actor` | `action` | `noun` | `second`
“put tuna in dish” | `player` | `Insert` | `tuna` | `dish`
“austin, eat tuna” | `Austin` | `Eat` | `tuna` | `nothing`

For instance, if a cannon goes off right next to the player, a period of partial deafness might ensue:

    [ MyNewRule;
      if (actor ~= player) rfalse;
      Listen: "Your hearing is still weak from all that cannon-fire.";
      default: rfalse;
    ];

The `if` statement needs to be there to prevent commands like “helena, listen” from being ruled out – after all, the player can still speak.

•▲ EXERCISE 51
Why not achieve the same effect by giving the player a `react_before` rule instead?

• EXERCISE 52
(Cf. ‘Curses’.) Write an `orders` routine for the player so that wearing a gas mask will prevent speech.

· · · · ·

The `player` object can not only be altered but switched altogether, allowing the player to play from the perspective of someone or something else at any point in the game. The player who tampers with Dr Frankenstein's brain transference machine may suddenly become the Monster strapped to the table. A player who drinks too much wine could become a drunk player object to whom many different rules apply. The “snavig” spell of ‘Spellbreaker’, which transforms the player to an animal like the one cast upon, could be implemented thus. Similarly the protagonist of ‘Suspended’, who telepathically runs a weather-control station by acting through six sensory robots, Iris, Waldo, Sensa, Auda, Poet and Whiz. In a less original setting, a player might have a team of four adventurers exploring a labyrinth, and be able to switch the one being controlled by typing the name. In this case, an `AfterLife` routine (see below) may be needed to switch the focus back to a still-living member of the team after one has met a sticky end.

The library routine `ChangePlayer(obj)` transforms the player to `obj`. Any object can be used for this. There's no need to give it any name, as the parser always understands pronouns like “me” and “myself” to refer to the current player-object. You may want to set its description, as this is the text printed if the player types “examine myself”, or its `capacity`, the maximum number of items which this form of the player can carry. Finally, this player-object can have its own `orders` property and thus its own rules about what it can and can't do.

As `ChangePlayer` prints nothing, you may want to follow the call with a `<<Look>>;` action.

▲ You can call `ChangePlayer` as part of a game's `Initialise` routine, but if so then you should do this before setting `location`.

▲ Calling `ChangePlayer(obj,1);` does the same except that it makes the game print “(as Whoever)” during subsequent room descriptions.

▲ The body dispossessed remains where it was, in play, unless you move it away or otherwise dispose of it. The player-object which the player begins with is a library-defined object called `selfobj`, and is described in room descriptions as “your former self”.

• EXERCISE 53
In Central American legend, a sorceror can transform himself into a nagual, a familiar such as a spider-monkey; indeed, each individual has an animal self or wayhel, living in a volcanic land over which the king, as a jaguar, rules. Turn the player into wayhel form.

• EXERCISE 54
Alter the Wormcast of ‘Ruins’ (previously defined in §9) so that when in wayhel form, the player can pass through into a hidden burial shaft.

• EXERCISE 55
To complete the design of this sequence from ‘Ruins’, place a visible iron cage above the hidden burial shaft. The cage contains skeletons and a warning written in glyphs, but the player who enters it despite these (and they all will) passes into wayhel life. (The transformed body is unable to move the sodium lamp, but has nocturnal vision, so doesn't need to.) Unfortunately the player is now outside a cage which has closed around the human self which must be returned to, while the wayhel lacks the dexterity to open the cage. The solution is to use the Wormcast to reach the Burial Chamber, then bring its earthen roof down, opening a connection between the chamber below and the cage above. Recovering human form, the player can take the grave goods, climb up into the cage, open it from the inside and escape. Lara Croft would be proud.

· · · · ·

▲▲ The situation becomes a little complicated if the same `orders` routine has to do service in two situations: once while its owner is a character met in the course of play, and then a second time when the player has changed into it. This could be done simply by changing the value of `orders` when the transformation takes place, but an alternative is to arrange code for a single `orders` routine like so:

    orders [;
        if (player == self) {
            if (actor == self) {
                ! I give myself an action
            }
            else {
                ! I give someone else an order
            }
        }
        else {
            ! Someone else gives me an order
        }
    ],

•▲▲ EXERCISE 56
Write an `orders` routine for a Giant with a conscience, who will refuse to attack even a mouse, but so that a player who becomes the Giant can be wantonly cruel.

· · · · ·

“There are only three events in a man's life; birth, life and death; he is not conscious of being born, he dies in pain and he forgets to live.” (Jean de la Bruyère again.) Death is indeed the usual conclusion of an adventure game, and occurs when the source code sets the library variable `deadflag` to `true`: in normal play `deadflag` is always `false`. The “standard Inform rules” never lead to the player's death, so this is something the designer must explicitly do.

Unlike life, however, interactive fiction offers another way out: the player can win. This happens if and when the variable `deadflag` is set to 2.

Any higher values of `deadflag` are considered to be more exotic ways the game can end, requiring text beyond “You have died” or “You have won”. The Inform library doesn't know what this text should be, so it calls the `DeathMessage` entry point routine, which is expected to look at `deadflag` and can then print something suitable. For instance, ‘Ruins’ has a chasm subject to the following `before` rule:

    before [;
        Enter: deadflag = 3;
            "You plummet through the silent void of darkness, cracking
            your skull against an outcrop of rock. Amid the pain and
            redness, you dimly make out the God with the
            Owl-Headdress...";
        JumpOver: "It is far too wide.";
    ],

and this means that it needs a `DeathMessage` routine like so:

    [ DeathMessage;
          if (deadflag == 3)
              print "You have been captured";
    ];

Capture was about the worst fate that could befall you in the unspeakably inhumane world of Maya strife.

‘Ruins’ doesn't, but many games allow reincarnation or, as David M. Baggett points out, in fact resurrection. You too can allow this, by providing an `AfterLife` entry point routine. This gets the chance to do as it pleases before any “death message” is printed, and it can even reset `deadflag` to `false`, causing the game to resume as though nothing had happened. Such `AfterLife` routines can be tricky to write, though, because the game often has to be altered to reflect what has happened.

• REFERENCES
The magic words “xyzzy” and “plugh” in ‘Advent’ employ `PlayerTo`. •‘Advent’ has an amusing `AfterLife` routine: for instance, try collapsing the bridge by leading the bear across, then returning to the scene after resurrection. ‘Balances’ has one which only slightly penalises death.