Contents this "Lesson:"
Object chair "chair"
has supporter enterable
with name "chair",
before
[; Take : "It is too big to carted around.";
];
If the player attempts to take the chair, "It is too big to be carted around."
will be printed and the chair's before routine will return true (1). The action
stops
and the prompt appears again.
Object chair "chair"
has supporter enterable
with name "chair",
before
[; Take : print "It's pretty heavy. ";
];
But
print "string";
just
prints the string and
returns 0. So this prints, "It's pretty heavy. " and returns 0. Because
processing was not stopped, Inform next calls its built-in library routine,
Take, which checks to see if the chair is touchable, if the player is carrying
too much already, etc. If all conditions
are right, it moves the chair to the player (to the player's inventory) and
print_rets,
"Taken", returning 1, thus finally stopping further
processing. Put together, this is will show on the screen as -- "It's pretty
heavy. Taken."
| Knowing what is/returns true or false -- 1 or 0 -- is essential for understanding Inform. |
| Command |
|---|
|
];
(end of routine, which returns automatically -- the value returned depends on the contents, usually 1, but some routines have a default value) |
|
print "string";
(prints string and returns 0) |
|
print_ret "string";
(prints string with a carriage return (new line) and returns 1) |
|
"string";
(prints string with a carriage return (new line) and returns 1 -- same as above) |
|
return;
(returns from a routine with no value, which is sometimes handy) |
|
return #;
(returns a specific numeric value) |
|
rfalse;
(returns false -- 0) |
|
rtrue;
(returns true -- 1) |
| Processing | Actions Performed |
|---|---|
| start of each turn |
Look or New Room
PrintorRun room's initial NewRoom MoveFloatingObjects Look Steps: 1a. A new-line is printed. The location's short name is printed (in bold-face, if possible). 1b. If the player is on a supporter, then " (on <something>)" is printed; if inside anything else, then " (in <something>)". 1c. " (as 1d. A new-line is printed. Now the `long description'. This step is skipped if the player has just moved of his own will into a location already visited, unless the game is in "verbose" mode. 2. If the location has a describe property, then it is run. If not, the location's description property is looked at: if it's a string, it is printed; if it's a routine, it is run. All rooms must provide either a describe property or a description of themselves. Now for items nearby: 3a. Any objects on the floor are listed. 3b. If the player is in or on something, the other objects also on/in the supporter/container are listed. The library has now finished, but your game gets a chance to add a postscript. 4. The entry point LookRoutine is called. |
|
Parsing
Parses the player's input (breaks sentence down into understandable parts). |
BeforeParsing
ChooseObjects parse_name ParseNoun animate/talkable's grammar routine |
|
Before
An opportunity for your code to interfere with or block altogether what might soon happen. |
GamePreRoutine
player's orders' property react_before of all objects in scope before of current room before (action) of first noun |
|
During
The library takes control and decides if the action makes sense according to its normal world model: for example, only an edible object may be eaten; only an object in the player's possession can be thrown at somebody, and so on. If the action is impossible, a complaint is printed and that's all. Otherwise the action is now carried out. |
LibraryMessages |
|
After
An opportunity for your code to react to what has happened, after it has happened but before any text announcing it has been printed. If it chooses, your code can print and cause an entirely different outcome. If your code doesn't interfere, the library reports back to the player (with such choice phrases as "Dropped."). |
react_after of all objects in scope
after of current room after of first noun GamePostRoutine |
| end of each turn |
1.The turns counter is incremented.
2.The 24-clock is moved on. 3.Daemons and timers are run (in no guaranteed order). 4. each_turn takes place for the current room, and then for everything nearby (that is, in scope). 5. The game's global TimePasses routine is called. 6. Light is re-considered (it may have changed as a result of events since this time last turn). |
[ Initialise;
location = field;
move lantern to player.
"You don't know how you got here. You were just strolling
along minding your own business, when this big troll...";
];
Of course, you put the printed string last because that will return true (1).
player = newselfobj;A Doe Crib Note:
|
When changing the player in
Initialise use the equal sign. When changing the player elsewhere in your
game, use
ChangePlayer(newselfobj);. Why? Well, ChangePlayer() performs all kinds of
complicated maneuvers (MoveFloatingObjects(), OffersLight(), etc.) that
Initialise also performs. So if you call ChangePlayer in Initialise, they
will be done twice. Also Zarf recommends = in Initialise. Good
enough for me ;-).
However, if you want the game to report the player's changed state after the room name, (as a dog), then you must use ChangePlayer and use it with a 1 -- ChangePlayer(dog, 1); |
Object selfobj "(self object)" <- original player object from parserm.h
with short_name
[; return L__M(##Miscellany, 18);
],
description
[; return L__M(##Miscellany, 19);
],
before NULL, after NULL, life NULL, each_turn NULL,
time_out NULL, describe NULL,
capacity 100, parse_name 0,
orders 0, number 0,
has concealed animate proper transparent;
Object newselfobj "(self object)" <- new player object
has concealed animate proper transparent
with short_name
[; return L__M(##Miscellany, 18);
],
description
[; return L__M(##Miscellany, 19);
],
before NULL, after NULL, life NULL, each_turn NULL,
time_out NULL, describe NULL,
capacity 100, parse_name 0,
orders 0, number 0,
add_to_scope hands;
Object hands "hands"
has concealed static transparent
with name "hands", article "your",
description
[; if (gloves has worn)
"On your hands are a pair of gloves.";
"Your hands are bare.";
],
add_to_scope l_hand r_hand;
Object l_hand "left hand"
with name "left" "hand";
Object r_hand "right hand"
with name "right" "hand";
location = office; location = chair;..instead of...
location = office; move player to chair;A Doe Crib Note:
| I have never had a satisfactory explanation of why the first works and the second doesn't. But to start the player on or in an object, use location. It's also a good idea to set the player's location and/or change the player before doing anything else. |
[ Initialise width length i; ! <- local variables
location = field;
move lantern to player;
box ""
"There is nothing quite so silly as a bad writer writing a tutorial."
""
" Marnie Parker"
"";
width = 0->33;
if (width == 0) width = 80;
if (width > 25) length = (width - 25)/2;
else length = 1;
style bold;
spaces length;
print "[Press any key to begin.]";
style roman;
@read_char 1 i;
@erase_window $ffff;
"^^^You don't know how you got here. You were just strolling
along minding your own business, when this big troll..."
];
width = 0->33; gets the default screen size (in most cases). The rest of
that calculation is used to center the prompt, "[Press any key to begin.]" (25
characters). @read_char waits for the player to press a key (any
key), and @erase_window clears the screen after the quote box is printed and
before the introduction is printed. ^ prints a carriage return without
returning 1. It is used here because after clearing the screen the opening
sentence may be lost without some preceeding carriage returns.
print "Do you want to restore a saved game? (Y/N) "; if (YesorNo() ~= 0) RestoreSub();
[ Initialise;
location = field;
move lantern to player.
print "You don't know how you got here. You were just strolling
along minding your own business, when this big troll...^^";
return 2;
];
Note that the banner cannot be permanently skipped. One of Dr. Nelson's
conditions granting you the use of Inform, for free, is that you must include
the banner near the start of the game, because it lists the Inform compiler
and Inform library versions.
Statusline time;before Initialise and after including parser.h. Making a timed game actually work also requires using default Inform routine that should be set in Initialise:
SetTime(hours, rateperturn);Hours is the current time, ratepersturn is how many minutes you want to allot to each turn. The only thing tricky about that is using a 24-hour clock.