Contents
Back
Forward

19. Starting, moving, changing and killing the player

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 (1645--1696)


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

The only compulsory task for a game's Initialise routine is to set the location variable to the place where the player should begin. This is usually a room (and is permitted to be one that's in darkness) but could instead be an object inside a room, such as a chair or a bed. If you would like to give the player some items to begin with, Initialise should also move them to player.

Games with a long opening sequence might want to start by offering the player a chance to restore a saved game at once. They can do so by writing the following in their Initialise routines:

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

(If you want to make the status line invisible during an opening sequence, see Section 33.) Initialise normally returns 0 or 1 (it doesn't matter which), but if it returns 2 then no game banner will be printed at once. (This is for games which, like 'Sorcerer', delay their banners until after the prologue.) 'Ruins', however, opens in classical fashion:

[ Initialise;
  TitlePage();
  location = Forest;
  move food_ration 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!^";
];

(The TitlePage routine will be an exercise in Section 33: 'Ruins' is really too small a game to warrant one, but never mind.) The location variable needs some explanation. It holds either the current room, if there's light to see by, or the special value thedark (the "Darkness'' object) if there isn't. In the latter case (but only in the latter case) the actual current room is held in the variable real_location, should you need to know it. Neither of these is necessarily the same as the parent of the player object. For instance, if the player sits in a jeep parked in a dark garage, then location is thedark, real_location is Garage and parent(player) is jeep.

Because of this, one shouldn't simply move the player object by hand. Instead, to move the player about (for teleportation of some kind), use the routine PlayerTo(place); (which automatically takes care of printing the new room's description if there's enough light there to see by).

/\ PlayerTo can also be used to move the player to a place inside a room (e.g., a cage, or a traction engine).

/\ Calling PlayerTo(place, 1); moves the player but prints nothing (in particular, prints no room description).

/\ Calling PlayerTo(place, 2); will Look as if the player had arrived in the room by walking in as usual, so only a short description appears if the room is one that has been seen before.

/\ In a process called 'scoring arrival', a room which the player has entered for the first time is given the visited attribute. If it was listed as scored, points are awarded. (See Section 14.)

/\/\ When a Look action takes place, or a call to PlayerTo(place,1), the library 'notes arrival' as well as 'scores arrival'. 'Noting arrival' consists of checking to see if the room has changed since last time (darkness counting as a different room for this purpose). If so, the following happens:

1. -- If the new location has an initial property, this is printed if it's a string, or run if it's a routine.

2. -- The entry point NewRoom is called (if it exists).

3. -- Any 'floating objects', such as drifting mist, which are found_in many places at once, are moved into the room.

The player's whole persona can easily be changed, because the player object can itself have an orders routine, just as the object for any non-player character can. To replace the orders routine for the standard player object, set

player.orders = MyNewRule;
where MyNewRule is a new orders rule. Note that this is applied to every action or order issued by the player. The variable actor holds the person being told to do something, which may well be the player himself, and the variables action, noun and second are set up as usual. 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.";
];
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 42:
(link to
the answer)
Why not achieve the same effect by giving the player a react_before rule instead?

??EXERCISE 43:
(link to
the answer)
(Cf. 'Curses'.) Write an orders routine for the player so that wearing the gas mask will prevent him from talking.

/\ In fact a much more powerful trick is available: the player can actually become a different character in the game, allowing the real player at the keyboard to act through someone else. Calling ChangePlayer(obj) will transform the player to obj. There's no need for obj to have names like "me'' or "myself''; the parser understands these words automatically to refer to the currently-inhabited player object. However, it must provide a number property (which the library will use for workspace). The maximum number of items the player can carry as that object will be its capacity. Finally, since ChangePlayer prints nothing, you may want to conclude with a <<Look>>;

ChangePlayer has many possible applications. 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. More ambitiously, a game could have a stock of half a dozen main characters, and the focus of play can switch between them. A player might have a team of four adventurers to explore a dungeon, 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.

/\ Calling ChangePlayer(object,1); will do the same but make the game print "(as Whoever)'' during room descriptions.

/\/\ When the person to be changed into has an orders routine, things start to get complicated. It may be useful to arrange such a routine as follows:
      orders
      [;  if (player==self)
          {   ! I am the player object...
              if (actor==self)
              {   ! ...giving myself an order, i.e., trying an action.
              }
              else
              {   ! ...giving someone else, the "actor", an order.
              }
          }
          else
          {   ! The player is the "actor" and is giving me an order.
          }
      ],

??/\EXERCISE 44:
(link to
the answer)
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 his wayhel.

??/\/\EXERCISE 45:
(link to
the answer)
Write an orders routine for a Giant with a conscience, who will refuse to attack a mouse, but so that a player who becomes the Giant can be as cruel as he likes.

The player is still alive for as long as the variable deadflag is zero. When set to 1, the player dies; when set to 2, the player wins; and all higher values are taken as more exotic forms of death. Now Inform does not know what to call these exotica: so if they should arise, it calls the DeathMessage routine, which is expected to look at deadflag and can then print something like "You have changed''.

Many games allow reincarnation (or, as David M. Baggett points out, in fact resurrection). You too can allow this, by providing an AfterLife. This routine gets the chance to do as it pleases before any "You are dead'' type message appears, including resetting deadflag back to 0 -- which causes the game to proceed in the normal way, rather than end. AfterLife routines can be tricky to write, though, because the game has to be set to a state which convincingly reflects what has happened.

*REFERENCES:
The magic words "xyzzy'' and "plugh'' in 'Advent' make use of 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.


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.