Contents
Back
Forward

20. Miscellaneous constants and scoring


For when the One Great Scorer comes
To write against your name,
He marks -- not that you won or lost --
But how you played the game.

...Grantland Rice (1880--1954), Alumnus Football

Some game rules can be altered by defining 'constants' at the start of the program. Two constants you must provide (and before including any of the library files) are the strings Story and Headline:

Constant Story "ZORK II";
Constant Headline "^An Interactive Plagiarism^
             Copyright (c) 1995 by Ivan O. Ideas.^";
All the rest are optional, but should be defined before Verblib is included if they're to take effect.

The library won't allow the player to carry an indefinite number of objects: the limit allowed is the constant MAX_CARRIED, which you may define if you wish. If you don't define it, it's 100, which nearly removes the rule. In fact you can change this during play, since it is actually the capacity of the player which is consulted; the only use of MAX_CARRIED is to set this up to an initial value.

If you define SACK_OBJECT to be some container, then the player will automatically put old, least-used objects away in it as the game progresses, provided it is being carried. This is a feature which endears the designer greatly to players. For instance, the following code appears (in between inclusion of Parser and Verblib) in 'Toyshop':

Object satchel "satchel"
  with description "Big and with a smile painted on it.",
       name "satchel", article "your",
       when_closed "Your satchel lies on the floor.",
       when_open "Your satchel lies open on the floor.",
  has  container open openable;
Constant SACK_OBJECT satchel;
'Ruins' isn't going to provide this feature, because there are few portable objects and those there are would be incongruous if described as being in a rucksack.

Another constant is AMUSING_PROVIDED. If you define this, the library knows to put an "amusing" option on the menu after the game is won. It will then call Amusing from your code when needed. You can use this to roll closing credits, or tell the player various strange things about the game, now that there's no surprise left to spoil.

The other constants you are allowed to define help the score routines along. There are two scoring systems provided by the library, side by side: you can use both or neither. You can always do what you like to the score variable in any case, though the "fullscore'' verb might then not fully account for what's happened. One scores points for getting certain items or reaching certain places; the other for completing certain actions. These constants are:
MAX_SCORE the maximum game score (by default 0);
NUMBER_TASKS number of individual "tasks" to perform (1);
OBJECT_SCORE bonus for first picking up a scored object (4);
ROOM_SCORE bonus for first entering a scored room (5)
and then the individual tasks have scores, as follows:

Array task_scores -> t1 t2 ... tn;
As this is a byte array, the task scores must be between 0 and 255. Within your code, when a player achieves something, call Achieved(task) to mark that the task has been completed. It will only award points if this task has not been completed before. There do not have to be any "tasks": there's no need to use the scoring system provided. Tasks (and the verb "full" for full score) will only work at all if you define the constant TASKS_PROVIDED. The entry point PrintTaskName prints the name of a game task (but, of course, is only ever called in a game with TASKS_PROVIDED defined). For instance, ('Toyshop' again)
[ PrintTaskName ach;
  switch(ach)
  {   0: "eating a sweet";
      1: "driving the car";
      2: "shutting out the draught";
      3: "building a tower of four";
      4: "seeing which way the mantelpiece leans";
  }
];
Another entry point, called PrintRank, gets the chance to print something additional to the score (traditionally, though not necessarily, rankings). For instance, we bid farewell to the 'Ruins' with the following:
[ PrintRank;
  print ", earning you the rank of ";
  switch(score)
  {   0 to 9:   "humble rainforest Tourist.";
      10 to 19: "Investigator.";
      20 to 29: "Acquisitor.";
      30 to 49: "Archaeologist.";
      50:       "Master Archaeologist.";
  }
];

Normally, an Inform game will print messages like

[Your score has gone up by three points.]
when the score changes (by whatever means). The player can turn this on and off with the "notify'' verb; by default it is on. (You can alter the flag notify_mode yourself to control this.)

The verbs "objects'' and "places'' are usually provided, so the player can get a list of all handled objects (and where they now are), and all places visited. If you don't want these to be present, define the constant NO_PLACES before inclusion of the library.

??/\EXERCISE 46:
(link to
the answer)
Suppose one single room object is used internally for the 64 squares of a gigantic chessboard, each of which is a different location to the player. Then "places'' is likely to result in only the last-visited square being listed. Fix this.

*REFERENCES:
'Advent' contains ranks and an Amusing reward (but doesn't use either of these scoring systems, instead working by hand).
'Balances' uses scored objects (for its cubes).
'Toyshop' has tasks, as above.
'Adventureland' uses its TimePasses entry point to recalculate the score every turn (and watch for victory).

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.