WelcomeWhat's NewsORLibraryDownloadsLinksWebMaster@OnyxRing.com

This site
pageviews since

Today's date:

Author: Roger Firth
Title: Print Rules

Creation Date: 8/6/2004 10:38:35 PM
Last Updated: 8/6/2004 10:38:35 PM

Print rules

This topic is about using Inform's print statement. Everything said here for print applies also to print_ret -- remember that these are exactly equivalent:

print stuff_to_be_printed; new_line; rtrue;
print stuff_to_be_printed; print "^"; return true;
print_ret stuff_to_be_printed;

The print statement can be used like this:

print term;
print term;
print term;
However, since it's just about the only statement where commas play a significant role, you'll more often see it in this form:

print term, term, ... term;

where you must have at least one term and can have as many as you like. Inform copes automatically with literal numbers and strings; this example outputs the expected "2 plus 3 is equal to 5." result:

print 2, " plus ", 3, " is equal to ", 2+3, ".^";

Things get more interesting as soon as you start to use variables. Consider these two examples:

x = 2+3;
print 2, " plus ", 3, " is equal to ", x, ".^";

x = " is equal to ";
print 2, " plus ", 3, x, 2+3, ".^";

The first still works fine, but the second produces the somewhat baffling "2 plus 3197685." which isn't at all what you want to find; between the "3" and the "5", where you'd hoped to see the phrase " is equal to ", you've instead got the mysterious number 19768. What's going on? Simply this: each Inform variable is stored in a single computer word -- that's just sixteen bits (or thirty-two bits in Glulx) -- fine for holding a number such as the result of adding 2 and 3, but far too small to hold a long string of characters like " is equal to ". Instead, the Inform compiler places those characters in a special memory area dedicated to holding all of the game's strings, and stores a pointer into that area -- the string's address -- in the variable. That's what "19768" is: the memory address where the phrase can be found.

So, how do you print what you want: the string itself rather than its fairly meaningless memory address? Like this:

x = " is equal to ";
print 2, " plus ", 3, (string) x, 2+3, ".^";

The general message coming out of all this is that, unless told otherwise, Inform treats each variable value simply as a number to be printed in signed decimal format. If you know better -- that the value has to be printed in some other format -- you need to explicitly say so. Typical cases are where:

  • the value isn't actually a number as such, but rather an address of an Inform item such as a string, object, or word in Inform's dictionary;
  • the value is a number, but you don't want it printed in signed decimal format, but instead in words, or as a hexadecimal value, or whatever;
  • the value is an encoded representation of some data which needs to be decoded or transformed before being printed.

Built-in rules

The way that you say to Inform "treat the following value specially, rather than just print it as a decimal number" is by using a rule: a word in parentheses immediately before the value. That's what (string) is -- a rule that tells Inform to treat what follows as the address of a string to be printed. Several built-in rules are available:

(number) expr
(char) expr
(string) addr
(address) addr
(name) addr
(a) addr
(the) addr
(The) addr
(ItorThem) addr
(ThatorThose) addr
(CThatorThose) addr
(CTheyorThats) addr
(IsorAre) addr
the expression's value in words [1]
the expression's value as a single character
the character string at this address [1]
the dictionary word at this address
the name of the object at this address
the object's name preceded by "a/an/some" [2]
the object's name preceded by "the" [3]
the object's name preceded by "The" [3]
"him/her/it/them" [4]
"him/her/that/those" [4]
"He/She/That/Those" [4]
"He's/She's/That's/They're" [4]
"is/are" [4]

Note 1: There's an important distinction between an expr and an addr: you can perform arithmetic in the former, not in the latter. (number) 2+3 and (char) 'q'-1 will both work, but (string) "Christmas"-5 and (name) self_obj+8 are recipes for disaster.
Note 2: Unless the object has an article property or a proper attribute.
Note 3: Unless the object has a proper attribute.
Note 4: The appropriate value is determined the attributes of the object at this address.

Homegrown rules

The built-in print rules are very useful, but there's nothing to stop you adding extra ones of your own. All you need do is write a routine of the desired name, taking a single parameter which is the value to be printed. The Inform Designer's Manual (Edition 4/1 §1.12) provides a sample hex() routine so that you can, for example, print (hex) -4 to produce the output "fffc". (Caution: don't use the equivalent routine from the DM Edition 3 -- it mishandles negative numbers.) Also, Card() in §2.4 decodes a number 0..51 into a playing card. Here are a few other examples.

Possesive pronouns. Like (a) and (the), to print "his/her/its/their" to suit the specified object; see also DM 4 Exercise 62:

[ hisorher x;
        if (x has pluralname) print "their";
        else if (x hasnt animate || x has neuter) print "its";
            else if (x has female) print "her"; else print "his";
. . .
print "In the bed dozes ", (a) NPC1, ", twitching and muttering under ", (hisorher) NPC1, " breath.";

Non-zero numbers. A version of the standard (number) rule which print "no" instead of "zero":

[ nznumber x; if (x > 0) print (number) x; else print "no"; ];
. . .
print "You have ", (nznumber) coins.number, " coins left to spend.";

Typographic control. Switching into boldface or underlined/italicized type normally requires a separate style statement. Here, you can control the typography (of a string) within a print statement:

[ b x; style bold; print (string) x; style roman; ];
[ u x; style underline; print (string) x; style roman; ];
. . .
print "...and can print in ", (b) "bold face", " as well as using ", (u) "italics", ".";

Decoding. Sometimes, you work internally with encoded values which need to be turned into string representations only at the instant of being printed. For example, a day-of-the-year (1..365) is transformed into a meaningful date (no, it doesn't handle leap years):

[ dayofyear x; switch (x) {
          1 to  31: print (ordinal) x,     " January";
         32 to  59: print (ordinal) x- 31, " February";
         60 to  90: print (ordinal) x- 59, " March";
         91 to 120: print (ordinal) x- 90, " April";

Copyright 2004 - 2021 : Roger Firth
OnyxRing.com has been given the potentially non-exclusive right to display the content of this article. However the original author retains all rights. Permission to reproduce this article -- either in part or in whole -- is left strictly to the discretion of the original author.

Table of ContentsAuthorsSearchIndex
Would you
recommend this
article to
someone else?
You bet I would! Heck No!