Text may be printed in any font of the interpreter's choice, variable- or fixed-pitch: except that when bit 1 of 'Flags 2' in the header is set, or when the text style has been set to Fixed Pitch, then a fixed-pitch font must be used.
8.1.1
In Version 5, the height and width of the current font (in units (see below)) should be written to bytes $27 and $26 of the header, respectively. In Version 6, these bytes are the other way round (height in $27, width in $26). The width of a font is defined as the width of its '0' character.
8.1.2
An interpreter should ideally provide 4 fonts, with ID numbers as follows:
1: the normal font 2: a picture font 3: a character graphics font 4: a Courier-style font with fixed pitch(In addition, font ID 0 means "the previous font".) Ideally all text styles should be available for each font (for instance, Courier bold should be obtainable) except that font 3 need only be available in Roman and Reverse Video. Each font should provide characters for character codes 32 to 126 (plus character codes for any accented characters with codes greater than 127 which are being implemented as single accented letters on-screen).
8.1.3
*** A game must not use fonts other than 1 unless allowed to by the interpreter: see the set_font opcode for how to give or refuse permission. (This paragraph is marked *** because existing Infocom games determined the availability of font 3 for 'Beyond Zork' in a complicated and unsatisfactory way: see S 16.)
8.1.3.1
*** It is legal for a game to change font at any time, including halfway through the printing of a word. (This might be needed to introduce exotic foreign accents in the future.)
8.1.4
The specification of the "picture font" is unknown (conjecturally, it was intended to provide pictures before Version 6 was properly developed). Interpreters need not implement it.
8.1.5
The specification of the character graphics font is given in S 16.
8.1.5.1
In Version 5 (only), an interpreter which cannot provide the character graphics font should clear bit 3 of 'Flags 2' in the header.
In Versions 1 to 3, a status line should be printed by the
interpreter, as follows. In Version 3, it must set bit 4 of
'Flags 1' in the header if it is unable to produce a status line.
In Versions 1 and 2, all games are "score games". In
Version 3, if bit 1 of 'Flags 1' is clear then the game is a "score game";
if it is set, then the game is a "time game".
The short name of the object whose number is in the first global
variable should be printed on the left hand side of the line.
Whenever the status line is being printed the first global
must contain a valid object number. (It would be useful if interpreters
could protect themselves in case the game accidentally violates this
requirement.)
If the object's short name exceeds the available room on
the status line, the author suggests that an interpreter should break
it at the last space and append an ellipsis "...". There is no
guaranteed maximum length for location names but an interpreter should
expect names of length up to at least 49 characters.
If there is room, the right hand side of the status line should
display:
For "score games": the score and number of turns, held in
the values of the second and third global variables respectively. The
score may be assumed to be in the range -99 to 999 inclusive, and
the turn number in the range 0 to 9999.
For "time games": the time, in the form hours:minutes (held
in the second and third globals). The time may be given on a 24-hour clock
or the number of hours may be reduced modulo 12 (but if so, "AM" or "PM"
should be appended). Either way the player should be able to see the
difference between 4am and 4pm, for example. The hours global may be
assumed to be in the range 0 to 23 and the minutes global in the range
0 to 59.
The status line is updated in exactly two circumstances: when
a show_status opcode is executed, and just before the keyboard is
read by read. (It is not displayed when the game begins.)
Under Versions 5 and later, text printing has a current
foreground and background colour. In Version 6, each window has its
own pair. (Note that a Version 6 interpreter going under the
Amiga interpreter number must use the same pair of colours for
all windows. If either is changed, then the interpreter must
change the colour of all text on the screen to match.
This simulates the Amiga hardware, which used two logical colours
for text and switched palette to change their physical colour.)
The following codes are used to refer to colours:
If the interpreter cannot produce colours, it should clear
bit 0 of 'Flags 1' in the header. In Version 6 it should write
colours 2 and 9 (black and white), either way round, into the default
background and foreground colours in bytes $2c and $2d of the
header.
If the interpreter can produce colours, it should set bit
0 of 'Flags 1' in the header, and write its default background
and foreground colours into bytes $2c and $2d of the header.
If a game wishes to use colours, it should have bit 6 in
'Flags 2' set in its story file. (However, an interpreter should not
rule out the use of colours just because this has not been done.)
The screen should ideally be at least 60 characters wide by 14 lines
deep. (Old Apple II interpreters had a 40 character width and some modern
laptop ones have a 9 line height, but implementors should seek to avoid
these extremes if possible.) The interpreter may change the exact
dimensions whenever it likes but must write the current height (in lines)
and width (in characters) into bytes $20 and $21 in the header.
The interpreter should use the screen height for calculating
when to pause and print "[MORE]". A screen height of 255 lines means
"infinite height", in which case the interpreter should never stop
printing for a "[MORE]" prompt. (In case, say, the screen is actually
a teletype printer, or has very good "scrollback".)
Screen dimensions are measured in notional "units". In
Versions 1 to 4, one unit is simply the height or width of one character.
In Version 5 and later, the interpreter is free to implement units as
anything from character sizes down to individual pixels.
In Version 5 and later, the screen's width and height in units
should be written to the words at $22 and $24.
The screen model for Versions 1 and 2 is as follows:
The screen can only be printed to (like a teletype) and there
is no control of the cursor.
At the start of a game, the screen should be cleared and the text
cursor placed at the bottom left (so that text scrolls upwards as the game
gets under way).
The screen model for Version 3 is as follows:
The screen is divided into a lower and an upper window and at any
given time one of these is selected. (Initially it is the lower
window.) The game uses the set_window opcode to select one of the
two. Each window has its own cursor position at which text is
printed. Operations in the upper window do not move the cursor of the
lower. Whenever the upper window is selected, its cursor position is
reset to the top left. Selecting, or re-sizing, the upper window does
not change the screen's appearance.
The upper window has variable height (of n lines)
and the same width as the screen. This should be displayed on the n lines
of the screen below the top one (which continues to hold the status line).
Initially the upper window has
height 0. When the lower window is selected, the game can split off
an upper window of any chosen size by using the split_window opcode.
Printing onto the upper window overlays whatever text is
already there.
When a screen split takes place in Version 3, the upper
window is cleared.
An interpreter need not provide the upper window at all. If
it is going to do so, it should set bit 5 of 'Flags 1' in the header to
signal this to the game. It is only legal for a game to use
set_window or split_window if this bit has been set.
Following a "restore" of the game, the interpreter should
automatically collapse the upper window to size 0.
When text reaches the bottom right of the lower window, it
should be scrolled upwards. The upper window should never be scrolled:
it is legal for a character to be printed on the bottom right position
of the upper window (but the position of the cursor after this operation
is undefined: the author suggests that it stay put).
At the start of a game, the screen should be cleared and the text
cursor placed at the bottom left (so that text scrolls upwards as the game
gets under way).
The screen model for Versions 4 and later, except Version 6,
is as follows:
Text can be printed in five different styles (modelled on the
VT100 design of terminal). These are: Roman (the default), Bold, Italic,
Reverse Video (usually printed with foreground and background colours
reversed) and Fixed Pitch. The specification does not require the
interpreter to be able to display more than one of these at once (e.g. to
combine italic and bold), and most interpreters can't. If the interpreter
is going to allow certain combinations, then note that changing back to
Roman should turn off all the text styles currently active.
An interpreter need not provide Bold or Italic (even for font 1)
and is free to interpret them broadly. (For example, rendering bold-face by
changing the colour, or rendering italic with underlining.)
It is legal to change text style at any point, including in
the middle of a word being printed.
There are two "windows", called "upper" and "lower": at
any given time one of these two is selected. (Initially it is the lower
window.) The game uses the set_window opcode to select one of the
two. Each window has its own cursor position at which text is
printed. Operations in the upper window do not move the cursor of the
lower. Whenever the upper window is selected, its cursor position is
reset to the top left.
The upper window has variable height (of n lines) and the
same width as the screen. (It is usual for interpreters to print the
upper window on the top n lines of the screen, overlaying any text
which is already there, having been printed in the lower window some
time ago.) Initially the upper window has height 0. When the lower
window is selected, the game can split off an upper window of any
chosen size by using the split_window opcode.
It is unclear exactly what split_window should do if
the upper window is currently selected. The author suggests that
it should work as usual, leaving the cursor where it is if the
cursor is still inside the new upper window, and otherwise moving
the cursor back to the top left. (This is analogous to the Version 6
practice.)
In Version 4, the lower window's cursor is always on
the bottom screen line. In Version 5 it can be at any line which is
not underneath the upper window. If a split takes place which would
cause the upper window to swallow the lower window's cursor position,
the interpreter should move the lower window's cursor down to the
line just below the upper window's new size.
When the upper window is selected, its cursor position
can be moved with set_cursor. This position is given in characters
in the form (row, column), with (1,1) at the top left. The opcode
has no effect when the lower window is selected. It is illegal
to move the cursor outside the current size of the upper window.
An interpreter should use a fixed-pitch font when printing on
the upper window.
In Versions 3 to 5, text buffering is never active in the
upper window (even if a game begins printing there without having
turned it off).
Clearing regions of the screen:
When text reaches the bottom right of the lower window, it
should be scrolled upwards. (When the text style is Reverse Video
the new blank line should not have reversed colours.) The upper
window should never be scrolled: it is legal for a character to be
printed on the bottom right position of the upper window (but the
position of the cursor after this operation is undefined: the author
suggests that it stay put).
Using the opcode erase_window, the specified window
can be cleared to background colour. (Even if the text style is Reverse
Video the new blank space should not have reversed colours.)
In Versions 5 and later, the cursor for the window being erased
should be moved to the top left. In Version 4, the lower window's cursor
moves to its bottom left, while the upper window's cursor moves to top left.
Erasing window -1 clears the whole screen to the
background colour of the lower screen, collapses the upper window
to height 0, moves the cursor of the lower screen to bottom
left (in Version 4) or top left (in Versions 5 and
later) and selects the lower screen. The same operation should
happen at the start of a game.
Using erase_line in the upper window should erase
the current line from the cursor position to the right-hand edge,
clearing it to background colour. (Even if the text style is
Reverse Video the new blank space should not have reversed colours.)
The screen model for Version 6 is as follows:
The display is an array of pixels. Coordinates are usually
given (in units) in the form (y,x), with (1,1) in the top left.
If the interpreter thinks the status line should be redrawn
(e.g. because a menu window has been clicked over it), it may set bit
2 of 'Flags 2'. The game is expected to notice, take action and clear
the bit. (However, a more efficient interpreter would cache
the status line and handle redraws itself.)
There are eight "windows", numbered 0 to 7. The code -3
is used as a window number to mean "the currently selected window".
This selection can be changed with the set_window opcode.
Windows are invisible and usually lie on top of each other. All text
and graphics plotting is always clipped to the current window,
and anything showing through is plotted onto the screen.
Subsequent movements of the window do not move what was printed and
there is no sense in which characters or graphics 'belong' to any
particular window once printed. Each window has a position (in units),
a size (in units), a cursor position within it (in units, relative to its
own origin), a number of flags called "attributes" and a number
of variables called "properties".
There are four attributes, numbered as follows:
"Wrapping" is the continuation of printed text from
one line to the next. Text running up to the right margin will
continue from the left margin of the following line. If
"wrapping" is off then characters will be printed until no more
can be fitted in without hitting the right margin, at which point
the cursor will move to the right margin and stay there, so that
any further text will be ignored.
"Buffered printing" means that text to be printed
in the window is temporarily stored in a buffer and only
flushed onto the screen at intervals convenient for the
interpreter.
"Buffered printing" has two practical effects:
firstly it causes a delay before printed text actually appears.
Secondly it affects the way "wrapping" is done.
If "buffered printing" is on, then text is wrapped after the
last word which could fit on a line. If not, then text is
wrapped after the last character that could fit.
Example: suppose the text "Here is an abacus" is printed in
a narrow window. The appearance (after the buffer has been
flushed, if there is buffered printing) might be:
There are 16 properties, numbered as follows:
If a window has character wrapping, then text is
clipped to stay inside the left and right margins. After a
new-line, the cursor moves to the left margin on the next line.
Margins can be set with set_margins but this should only be
done just after a newline or just after the window has been
selected. (These values are margin sizes in pixels, and are by
default 0.)
If the interrupt countdown is set to a non-zero value
(which by default it is not), then the line count is decremented on each
new-line, and when it hits zero the routine whose packed address is stored
in the "newline interrupt routine" property is called before text printing
resumes. (This routine may, for example, meddle with margins to roll text
around a crinkly-shaped picture.) The interrupt routine should not attempt
to print anything.
Because of an Infocom bug, if the interpreter number is
6 (for MSDOS) and the story file is 'Zork Zero' release 393.890714,
but in no other case, the interpreter must do the following instead:
(1) move to the new line, (2) put the cursor at the current left margin,
(3) call the interrupt routine (if it's time to do so). This is the least
bad way to get around a basic inconsistency in existing Infocom
story files and interpreters.
Note that the set_margins opcode, which is often
used by newline interrupt routines (to adjust the shape of a margin
as it flows past a picture), automatically moves the cursor if the
change in margins would leave the cursor outside them. The effect
will depend, unfortunately, on which sequence of events above
takes place.
A line count is never decremented below -999.
The text style is set just as in Version 4, using
set_text_style (which sets that for the current window). The
property holds the operand of that instruction (e.g. 4 for italic).
The foreground colour is stored in the lower byte of the
colour data property, the background colour in the upper byte.
The font height (in pixels) is stored in the upper byte of the
font size property, the font width (in pixels) in the lower byte.
The interpreter should use the line count to see when it
should print "[MORE]". A line count of -999 means "never print
[MORE]". (Version 6 games often set line counts to manipulate
when "[MORE]" is printed.)
If an attempt is made by the game to read the cursor position
at a time when text is held unprinted in a buffer, then this text should
be flushed first, to ensure that the cursor position is accurate before
being read.
All eight windows begin at (1,1).
Window 0 occupies the
whole screen and is initially selected. Window 1 is as wide as the
screen but has zero height. Windows 2 to 7 have zero width and height.
Window 0 initially has attribute 1 off and 2, 3 and 4 on (scrolling,
copy to printer transcript, buffering). Windows 1 to 7 initially have
attribute 4 (buffering) on, and the other attributes off.
A window can be moved with move_window and resized with
window_size. If the window size is reduced so that its cursor lies
outside it, the cursor should be reset to the left margin on the top
line.
Each window remembers its own cursor position (relative
to its own coordinates, so that the position (1,1) is at its top
left). These can
be changed using set_cursor (and it is legal to move the cursor
for an unselected window). It is illegal to move the cursor outside
the current window.
Each window can be scrolled vertically (up or down) any
number of pixels, using the scroll_window opcode.
To some extent windows 0 and 1 mimic the behaviour of the
lower and upper windows in the Version 4 screen model:
The split_screen opcode tiles windows 0 and 1 together
to fill the screen, so that window 1 has the given height and is
placed at the top left, while window 0 is placed just below it
(with its height suitably shortened, possibly making it disappear
altogether if window 1 occupies the whole screen).
An "unsplit" (that is, a split_screen 0) takes place
when the entire screen is cleared with erase_window -1, if a
"split" has previously occurred (meaning that windows 0 and 1
have been set up as above).
Screen clearing operations:
Erasing a picture is like drawing it (see below), except
that the space where it would appear is painted over with background
colour instead.
The current line can be erased using erase_line, either
all the way to the right margin or by any positive number of pixels in
that direction. The space is painted over with background colour
(even if the current text style is Reverse Video).
Each window can be erased using erase_window, erasing to
background colour (even if the current text style is Reverse Video).
Erasing window number -1 erases the entire screen to
the background colour of window 0, unsplits windows 0 and 1
(see S 8.7.3.3 above) and selects window 0.
Erasing window -2 erases the entire screen to the current
background colour. (It doesn't perform erase_window for all the
individual windows, and it doesn't change any window attributes or
cursor positions.)
Pictures may accompany the game. They are not stored in the
story file (or the Z-machine) itself, and the interpreter is simply
expected to know where to find them.
Pictures are numbered from 1 upwards (not necessarily
contiguously). They can be "drawn" or "erased" (using draw_picture
and erase_picture). Before attempting to do so, a game may ask the
interpreter about the picture (using picture_data): this allows the
interpreter to signal that the picture in question is unavailable,
or to specify its height and width.
The game may, if it wishes, use the picture_table opcode
to give the interpreter advance warning that a group of pictures will
soon be needed (for instance, a collection of icons making up a control
panel). The interpreter may want to load these pictures off disc and
into a memory cache.
Some interpreters print the status line when they begin running a Version
3 game, but this is incorrect. (It means that a small game printing text
and then quitting cannot be run unless it includes an object.) The author's
preferred status line formats are:
The only existing Version 3 game to use an upper window is 'Seastalker'
(for its sonarscope display).
Some ports of ITF apply buffering (i.e. word-wrapping) and scrolling to
the upper window, with unfortunate consequences. This is why
the standard Inform status line is one character short of the width
of the screen.
The original Infocom files seldom use erase_window, except with window
-1 (for instance 'Trinity' only uses it in this form). ITF does not
implement it in any other case.
The Version 5 re-releases of older games make use of consecutive
set_text_style instructions to attempt to combine boldface reverse video
(in the hints system).
None of Infocom's Version 4 or 5 files use erase_line at all, and ITF
implements it badly (with unpredictable behaviour in Reverse Video text
style). (It's interesting to note that the Version 5 edition of 'Zork I'
- one of the earliest Version 5 files -- blanks out lines by looking up
the screen width and printing that many spaces.)
It's recommended that a Version 5 interpreter always use units to
correspond to characters: that is, characters occupy $1\times 1$
units. 'Beyond Zork' was written in the expectation that it could
be using either 1x1 or 8x8, and contains correct
code to calculate screen positions whatever units are used.
(Infocom's Version 5 interpreter for MSDOS could either run in a
text mode, 1x1, or a graphics mode, 8x8.)
However, the German translation of 'Zork I' contains incorrect
code to calculate screen positions unless 1x1 units are
used.
Note that a minor bug in Zip writes bytes $22 to $25 in the
header as four values, giving the screen dimensions in the form left,
right, top, bottom: provided units are characters (i.e. provided the
font width and height are both 1) then since "left" and "top"
are both 0, this bug has no effect.
Some details of the known IBM graphics files are given in Paul David
Doherty's "Infocom Fact Sheet". See also Mark Howell's program
"pix2gif", which extracts pictures to GIF files. (This is one of
his "Ztools" programs.)
Although Version 6 graphics files are not specified here, and were
released in several different formats by Infocom for different computers,
a consensus seems to have emerged that the MCGA pictures are the ones
to adopt (files with filenames *.MG1). These are visually identical
to Amiga pictures (whose format has been deciphered by Mark Knibbs).
However, some Version 6 story files were tailored to the interpreters
they would run on, and use the pictures differently according to what
they expect the pictures to be. (For instance, an Amiga-intended
story file will use one big Amiga-format picture where an MSDOS-intended
story file will use several smaller MCGA ones.)
The easiest option is to interpret only DOS-intended Version 6 story
files and only MCGA pictures. But it may be helpful to examine the
Frotz source code, as Frotz implements draw_picture and
picture_data so that Amiga and Macintosh forms of Version 6 story
files can also be used.
It is generally felt that newly-written graphical games should not
imitate the old Infocom graphics formats, which are very awkward to
construct and have been overtaken by technology. Instead, the draft
Blorb proposal for packaging up resources with Z-machine games
calls for PNG format graphics glued together in a fairly simple way.
An ideal Version 6 interpreter ought to understand both
the four Infocom picture-sets and any Blorb set, thus catering
for old and new games alike.
The line count of -999 preventing "[MORE]" is a device used by the
demonstration mode of 'Zork Zero'.
Section
1 / 2 /
3 / 4 /
5 / 6 /
7 / 8 /
9 / 10 /
11 / 12 /
13 / 14 /
15 / 16
Appendix
A / B /
C / D /
E / F
8.2
8.2.1
8.2.2
8.2.2.1
8.2.2.2
8.2.3
8.2.3.1
8.2.3.2
8.2.4
8.3
8.3.1
-1 = the colour of the pixel under the cursor (if any)
0 = the current setting of this colour
1 = the default setting of this colour
2 = black 3 = red 4 = green 5 = yellow
6 = blue 7 = magenta 8 = cyan 9 = white
10 = darkish grey (MSDOS interpreter number)
10 = light grey (Amiga interpreter number)
11 = medium grey (ditto)
12 = dark grey (ditto)
Colours 10, 11, 12 and -1 are available only in Version 6.
In Version 6 the pictures in some graphics files use colours
beyond the above: if so the result of "the colour under
the cursor" is permitted to be stored with value 16 or
greater.
8.3.2
8.3.3
8.3.4
8.4
8.4.1
8.4.2
8.4.3
8.5
8.5.1
8.5.2
8.6
8.6.1
8.6.1.1
8.6.1.1.1
8.6.1.1.2
8.6.1.2
8.6.1.3
8.6.2
8.6.3
8.7
8.7.1
8.7.1.1
8.7.1.2
8.7.2
8.7.2.1
8.7.2.1.1
8.7.2.2
8.7.2.3
8.7.2.4
8.7.2.5
8.7.3
8.7.3.1
8.7.3.2
8.7.3.2.1
8.7.3.3
8.7.3.4
8.8
8.8.1
8.8.2
8.8.3
8.8.3.1
0: wrapping
1: scrolling
2: text copied to output stream 2 (the transcript, if selected)
3: buffered printing
Each can be turned on or off, using the window_style opcode.
8.8.3.1.1
8.8.3.1.2
8.8.3.1.2.1
8.8.3.1.2.2
|...margins....|
wrapping on buffering on Here is an
abacus^
off buffering on Here is an aba^
wrapping on buffering off Here is an aba
cus^
off buffering off Here is an aba^
where the caret denotes the final position of the cursor.
(Games often alter "wrapping": it would normally be on for
a window holding running text but off for a status-line window,
which is why window 0 has "wrapping" on by default but all other
windows have "wrapping" off by default. On the other hand
all windows have "buffered printing" on by default and games
only alter this in rare circumstances to avoid delays in the
appearance of individual printed characters.)
8.8.3.2
0 y coordinate 6 left margin size 12 font number
1 x coordinate 7 right margin size 13 font size
2 y size 8 newline interrupt routine 14 attributes
3 x size 9 interrupt countdown 15 line count
4 y cursor 10 text style
5 x cursor 11 colour data
Each property is a standard Z-machine number and is readable
with get_wind_prop and writeable with put_wind_prop. However,
a game should only use put_wind_prop to set the newline
interrupt routine, the interrupt countdown and the line count:
everything else is either set by the interpreter or by
specialised opcodes (such as set_font).
8.8.3.2.1
8.8.3.2.2
8.8.3.2.2.1
8.8.3.2.2.2
8.8.3.2.2.3
8.8.3.2.3
8.8.3.2.4
8.8.3.2.5
8.8.3.2.6
8.8.3.2.7
8.8.3.3
8.8.3.4
8.8.3.5
8.8.3.6
8.8.4
8.8.4.1
8.8.4.2
8.8.5
8.8.5.1
8.8.5.2
8.8.5.3
8.8.5.3.1
8.8.5.3.2
8.8.6
8.8.6.1
8.8.6.2Remarks
See S 16 for comment on how 'Beyond Zork' uses fonts.
Hall of Mists 80/733
Lincoln Memorial 12:03 PM
Thus the score/turns block always fits in 3+1+4=8 characters and the
time in 2+1+2+1+2=8 characters. (Games needing more exotic time lines,
for example, should not be written in Version 3.)
Infocom's Version 6 interpreters and story files disagree on the meaning
of window attributes 0 and 3 and the opcode buffer_mode, in such
a way that the original specification is hard to deduce from the final
behaviour. If we call the three possible ways that text can appear
"word wrap", "char wrap" and "char clip":
|...margins....|
word wrap Here is an
abacus^
char wrap Here is an aba
cus^
char clip Here is an aba^
then Infocom's interpreters behave as follows:
Apple II MSDOS Macintosh Amiga
A0 off, A3 off char clip(LR) char clip() --- ---
A0 off, A3 on char clip(LR) char clip(LR) --- ---
A0 on, A3 off word wrap char wrap --- ---
A0 on, A3 on word wrap word wrap --- ---
buffer_mode off --- --- char wrap char clip(L)
buffer_mode on --- --- word wrap word wrap
Here "---" means that the interpreter ignores the given state, and
the presence of L, R or both after "char clipp" indicates which of the
left and right margins are respected. The Amiga behaviour may be due
to a bug and two bugs have also been found in the MSDOS implementation.
Under this standard, the appearance is as follows:
Standard
A0 off, A3 off char clip(LR)
A0 off, A3 on char clip(LR)
A0 on, A3 off char wrap
A0 on, A3 on word wrap
buffer_mode off ---
buffer_mode on ---
Due to a bug or an oversight, the V6 story files for all interpreters
use buffer_mode once: to remove buffering while printing
"Please wait..." with a row of full stops trickling out during a slow
operation. Buffering would frustrate this, but fortunately on modern
computers the operation is no longer slow and so the bug does not
cause trouble.