Version 1.0

NovelLib

Contents

Introduction

Starting a NOVEL mode Game Making a NOVEL mode Game Other Points

Copyright Notices


Introduction

NovelLib is a library and modified version of Graham Nelson's Inform compiler, for producing Z-Machine games in Novel mode. This library provides the interface, and functions to automate the processing of neat paragraphing. It also provides a few functions and features designed to make the arduous task of providing enough prose in the right places easier.

The first ever game to be written in Novel format was "My Angel" (Jon Ingold, 2000), which came 6th in the Annual I.F. Competition that year and won the Best Story category in the XYZZY's awards. [Neither of those were down to it being in Novel format]. It can be found at http://ww.if-archive.org/games/zcode/My_Angel.z5

NovelLib can create either V5 or V6 files, with V6 being preferable. There are two main differences:

To use the V6 version you'll need to download Jason C. Penney's excellent "V6lib" from his web-site or the if-archive. The relevant pages are:

ftp://ftp.ifarchive.org/if-archive/infocom/compilers/inform6/library/contributions/

http://V6Lib.jczorkmid.net/

The library makes no use of graphics or sound, although both are also possible in the v6 format. V6 should run under most interpreters except quite possibly those on handhelds etc. however it does not run under all of them. FROTZ is recommended. Note that upon starting the game in WinFrotz it will complain about the lack of a graphics file. This is harmless.

If you are compiling to v5 you need to define

Constant VERSION5;
at the top of your code. The default output is a version 6 game.

THE Informal COMPILER

For DOS compiler users -

The EXE file in this archive is a slightly modified version of Graham Nelson's Inform compiler, designed for use with NovelLib by Sean T. Barret (distributed with permission of both). The differences are described in more detail below, but to summarise, the print_ret and "--" forms have had their immediate new_line removed, and the symbol ^ in text now calls the libraries CR() function, and acts as a safe method of providing carriage returns (new_lines) at the beginning or end of paragraphs. To use the new compiler, you'll need to run it with the "N" and "Z" switches turn on - you can do this by putting the line

Switches "N"; Switches "~Z";
at the very top of your code, or apply this on the command line
> INFORMAL -n~z Game.inf
Note the effect on ^ characters ONLY APPLIES to string in print statements (eg. print "The end.^") and not string constants which are printed later (such as description "This is the room.^There is the wall.", which might appear in an object.)

For more information on these switches, see the "Informal.txt" manual supplied with NovelLib.

The compiler also features Sean T. Barret's varying strings extension. See the "Varying.txt" manual for further information.

For other users -

The source code is available to build versions which can run under different platforms. Please contact Sean. T. Barret for this.

 Standard Inform COMPILER USERS

You can still write valid code only you'll need to avoid print_ret "text" (you can use the library function PF instead, as in: return PF("text"). This has the disadvantage that it can only accept constant strings).

The source code to build a compiler for your platform is available. I'll be happy to host any builds for other platforms on my web-site if you send them to me (Unix and Mac, for instance).

What NOVEL mode does

NOVEL mode allows Interactive Fiction games to generate standard prose as the game is played. The input prompt is moved to a separate window (referred to as the Input Line throughout this manual), as are all error messages, disambiguations, and responses that have no real bearing on events. NOVEL mode is capable of organising paragraphs, as well as using relative terms such as "it" or "them" to aid the flow of the text.

This library allows any game to be played in either NOVEL or NORMAL mode with the same coded game-file, so if players find the other format difficult to use they can switch. (NORMAL mode is the one most text adventures operate in, with a prompt between all the pieces of text outputted by the game).

To aid the process of keeping track of where you are in the game, there is an ALTERNATE form of NOVEL mode which switches the type from bold to unbold every turn. If you find this ugly, you could modify the FlipBold routine to change the font colour, or such like. It is defined in the "Novel.h" file.

Random Functions of Some Use

Centre(x)

Bold(txt) Italic(txt) OnMargin() Fmt_(k) Functions to control the Windows in V6

The library defines the constants MainGameWin, InputLineWin and SummaryWin for the window objects of the interface. To print to one, use windowname.Activate(); Remember to switch back to the original window afterwards! The current active window is stored in the ActiveZWindow variable. There are several formatting calls you can make, see the V6Lib documentation for these in detail; the most useful though are:

WindowName.Erase();
- Clear it
WindowName.SetFGColour(<colour constant>);
- Change the foreground colour
WindowName.SetFontStyle(<font type>);
- Change the font
It is also possible to move the cursor and change the font style; users are warned not to do this in the main window as it will interfere with the paragraphing and Alternate mode routines. To change default colours and styles edit the MyZWinStyle object in NovelDef.h.

See the V6lib documentation for a fuller and more informative list.

Up to Contents


STARTING A GAME

For the most part this is done as usual: You set up objects with before routines, and after routines. There are however particular rules to be obseved when making print statements from within these routines, and these are described below. Some output you will want to divert to the Input Window, this is explained in "Printing to the Input Line". There is no status line in a standard NOVEL mode game; a [possibly lamentable] design decision taken for "My Angel". However, there is the option of including one, and the library provides a simple standard model - the alternative is a "Summary" command which gives the player a little information on where she is in the Input Line. This is all easily customizable. See the section below on SummarySub.

What you must include

To produce V6 output (the library default) you will need to download the V6lib library extension. This can be found in the if-archive alongside this distribution, and also on the authors' website. Those relevant pages are:

ftp://ftp.ifarchive.org/if-archive/infocom/compilers/inform6/library/contributions/

http://V6Lib.jczorkmid.net/

Place the v6 library files in the same place as your other library files and then NovelLib will be able to construct game files.

Otherwise place at the top of your code, above any library inclusions,

Constant VERSION5;
If you plan to use the Informal compiler, then at the very top of your code, above all constant definitions, include the line
Switches "N"; Switches "Z";
to enable the extended features.

Then at the top of your code, put

Include "NovelDef";
Then, below the "Grammar" file, you need to place the main body of the library:
Include "Verlib";
Include "Grammar";
Include "Novel";
The library consists of four Novel mode files, and three files from V6lib. These can all safely be put with your other library files, or arranged any way you prefer.

The Initialise routine

The Initialise routine of your game has to set up the v6 lib and NOVEL mode flags, by having the line

NovelInit();
at the start. After the NovelInit() call, all text will be printed as the start of the game, on the main game screen.

Note that NovelInit will print a title screen asking the player to choose Novel mode, Normal mode, to Restore a saved position or start in Alternate mode. You may well want to change or extend this screen, if so simply write your own TitlePage(); routine before the inclusion of the "Novel.h" file.

A TitlePage routine needs to set:

upperprompt

= 0 - if the game is to start in NORMAL mode
= 1 - if the game is to start in NOVEL mode


boldflag

= 1 - if the game is to start in Alternating (novel) mode
= 0  - if the game is to start without the Alternating mode (or normal novel mode, if you like)


So for example, if you wish to make your game alternating NOVEL mode only and have no TitlePage at all, simply define

[ TitlePage; upperprompt = 1; boldflag = 1; ];
before Novel.h is included.

You may want other options, such as an automatic start to scripting, a restore option, or a pre-game menu.

Note - to prevent the library banner from being printed as the first text in the game, you'll need to return 2 from your own Initialise routine. However, a banner should be printed somewhere to comply with the distribution conditions on Inform-compiled games.

Constants you can predefine

VERSION5;

- Will compile version 5 code. Note you still need to specify the version in the command line, as the Inform compiler will not read this constants presence.
SUMMARY_ON = n;
- Will create a summary window which is n lines deep and displays information throughout the game.

- Equivalent of the normal status bar. See here for more information.

PARAGRAPH_INDENT = n;
- Will indent every new paragraph by n + 1 spaces (the 1 being the space at the start of a line of text).

- See here for more information.

PARAGRAPH_SYMBOL = "string";
- Will print "string" at the start of each new paragraph in NOVEL mode.
These should all be defined before the inclusion of "NovelDef.h". Most of these are explained below in more detail.

Up to Contents


MAKING A GAME
 

Printing to the Main Window

The Basics

One of the main objectives in coding for NOVEL mode is producing well-structured paragraphs. The library can't do much to aid you here, apart from supply functions to produce new lines and carriage returns which won't interfere with each other. There are two main rules to abide by when writing for NOVEL mode: Firstly, all text in the Main Window should begin with a space, so that you don't get sentences running into each other thus

"You see a mushroom.It is blue."
Secondly, you can't just put new line's where you want to; because if you should end one paragraph with a new line, and then start the next with a new line (because the first is a good break for a paragraph, and the next a good opening) this will print two consequtive new lines, leaving a blank line across the screen. To aid this, there is a function CR (short for 'Carriage Return') which is a safe way to start a new paragraph, or end an old one. It should be called whenever you feel there is a good place to 'break' the text. More calls rather than less is a good rule of thumb; though starting new paragraphs on every line would be choppy - and make the use of NOVEL mode a touch pointless - it's impossible to format everything logically, and very long paragraphs are awful.

The CR() Function and Paragraphing

The CR() function also prints the indent on the start of the next paragraph. This is by default 2 spaces, plus the additional space at the start of the next block of text, making three. You can change this, by defining

Constant PARAGRAPH_INDENT = n;
above the inclusion of "Novel.h" in your source code; with n the number of spaces in the indent - 1.

You can also indent with symbols (eg. ">" or "-- ") by defining the constant

Constant PARAGRAPH_SYMBOL = ">";
above "novel.h" Note this will only (currently) print in NOVEL mode, Normal mode will indent by whatever the PARAGRAPH_INDENT currently stands at. (This is to avoid additional indent symbols appearing on blank lines above prompts).

If you want to print a line which _doesn't_ end a paragraph, then use PF (Print Function); a call of the form PF(txt) will print the text txt and return true. It's the novel mode equivalent of the standard quote-mark form: " -- ";

If you're using the Informal compiler, then the standard print_ret " --- "; form (or its abbreviation, in which the print_ret is omitted and just quotes are used) will be interpreted the same as return PF(" -- "); It will print out your text and return true, telling the game not to end the current paragraph yet; and not printing any new_line. Also, uses of the ^ symbol in text is modified to call Novel.h's CR() [ more accurately, the CR_() routine ] instead of printing a newline directly. This prevents two new lines every appearing in a row, and allows you to use ^ freely between each_turns, and daemons and before routines, etc. If you want to print consequetive new_lines to format a screen (print a chapter heading, or suchlike) then use the Fmt_(k); function, which prints k consequetive new_line's with no indentation symbols or spaces.

If you're NOT using the Informal compiler, it's perfectly safe to format with "^^^^"; strings as usual.

If you want to change the default behaviour of CR_(); you can edit its definition in Novel.h; for example you may decide to leave one blank line as the default for new paragraphs - this could be done by just adding another new_line; inside the CR_(); routine.

Using the Print Functions

So here's the three ways to use these functions.

An ordinary before routine might contain:

Smell: return PF(" The smell of the flowers is overpowers you for a moment.");
(This will print without any paragraphing associated).
Examine: CR(); return PF(" Enough of such things. You turn your attention to the flowers, much prettier than the boneyard around. They have little red heads, on waving stalks, like cheery jack-in-the-boxes.");
(This will start a new paragraph, but won't end one, unless the next line wants to start a new paragraph too).
Eat: print " You pluck a flower-head and nibble the corner. Eugh. It tastes horrible. Damn flowers. It's not like they look pretty anyway. You feel your enthusiasm for them fade."; return CR();
(This will start wherever the cursor is, and then end the paragraph).

CR() can take a dummy argument so it can be placed in print statements:

print " You feel slightly sick.", (CR) 1; rtrue;
is just as valid as the Eat: line given above.

OnMargin()

Sometimes the decision on whether a line should end the paragraph or not depends on where it stands within the current paragraph. The library provides the OnMargin() function, which will return true if the cursor is currently at the start of a new paragraph. So for instance,

if (OnMargin()) return PF(" I sit."); print " I sit."; return CR();
..will print " I sit." as the end of a paragraph, unless it's the start of one. Note that OnMargin works by looking at the current cursor position, so you have to call it before printing anything else. However, it writes the result found onto the Margin object for later reference: if OnMargin returns true, then the Margin is given the on attribute, otherwise this attribute is removed. So the line above could (and indeed, probably should) be written thus:
OnMargin(); print " I sit."; if (Margin has on) CR(); rtrue;
(The Margin object is an internal library object used for passing a few properties. The only two attributes reserved on it are on and general, so it could make a useful scratch object using other properties.)
 

Avoiding Repetitions

The hardest thing with NOVEL mode is avoiding repeated text. The library provides two variables to help with this a little - pre_noun and pre_action, which tell you the last noun referenced in the text, and the last action performed by the player.

This is useful, for instance, if the player types "EXAMINE PENDANT", then "REMOVE PENDANT":

" The pendant is light brown. You remove the pendant."
looks bad, whereas by checking the pre_noun used, you can produce:
" The pendant is light brown. You remove it."
The checking of pre_noun and printing the name or 'it' (or whatever definite is appropriate) is such a common one, the library provides two functions:
ItorName(obj) will print (the) obj OR it/them/him/her/yourself
CItorName(obj) will print " ", (The) obj OR It/Them/He/She/You
These can be fitted into print statements like the Name or The function. So the example above would be:
before [;
Examine: print (CItorName) self, " is light brown."; rtrue;
],
after [;
Disrobe: print " You remove ", (ItorName) self, "."; rtrue;
],
pre_noun is usually set to the last noun the player referenced, similar to the Parser's itobj. However, some paragraphs may end in text concerning some other object (for example, if the description of the pendant reads " The pendant is light brown, and set into its centre is a crystal shard.", and the player then types TAKE SHARD, " You cannot remove it." is more appropriate than " You cannot take the crystal shard."). So if you want to change the value pre_noun will take, the library provides the lastref variable; and whatever you set this to will become pre_noun on the next round of printing to the main window.

So the pendant's before routine becomes:

before [;
Examine: lastref = crystal_shard;
print (CItorName) self, " is light brown and set into its centre is a crystal shard.";
rtrue;
],
There’s no reason either why lastref has to reference an object – if you set it to a negative number you can use it to refer to specific pieces of text, if there are specific combinations to trap. Of course, this sort of messy, special-case programming is hugely deprecated, and hugely useful in NOVEL mode programming.

If you're using the Informal compiler it is much easier to avoid repetitions too, by using the varying string capabilities. See the "Varying.txt" document for an explanation of how to use these. Note, varying strings are on by default unless turned off with the "~V" switch at compile-time.
 

Library Verb Routines

The library ("Novel.h") includes modified versions of the some of the standard library functions, mainly in order to implement messaging in the Input Line, or to remove automatic new_line printing (such as occurs in InvSub and LookSub). These new routines can be found at the top of Novel.h and if you are replacing them you should use these as your model, rather than those found inside "Verblibm.h", which will not work properly under NOVEL mode.

The library also replaces some routines from the parser, pretty major ones too, however it's only to move some messages which are buried within to the Input Line, and to add the "last object referenced" handling. A full list of the routines replaced can be found in the "NovelDef.h" header file.
 

Library Messages

The library messages are mostly divereted to the Input Line, so messages such as "That's hardly portable" or "The box isn't open" will be printed there. Changing these is easy - just edit the NovelEng.h file or include a LibraryMessages object in your code as you normally would. If moving these messages into the main window they probably need to be more verbose, and certainly will need to explain what has been typed - so for instance "That's hardly portable" would need to be changed to "Bizarrely, you consider taking the <object>, but obviously that's not portable".

Generating decent messages for absurd things to type is one of the major challenges of the NOVEL format. My Angel took a heavy-handed approach and deliberately mis-interpreted things the player typed to its own ends.

The default messages for things such as Drop and Take currently appear in the text, but are quite unsatisfactory, and you are strongly advised to write your own. These can be done safely in the after routines of objects as per normal Inform coding.
 

Printing to the Input Line

There are two routines for placing input in the Input Line: Stat, and StatFont. They work as follows:

Stat(txt, flag, row, depth)

Will print the string txt into the input line. If the player is in normal mode, will print cleanly to the screen.

flag

row depth Stat will return true, so for example
 
return Stat("You don't really want to do that.");


is a valid way to end a turn in a before routine.

eg.

Stat("I beg your pardon?", 1); -- in NovelEng.h
return Stat("These rocks don't look comfortable."); -- in the before routine of a "rock" object.
StatFont(row, flag, depth)

This is just a cursor-setting routine (called by Stat), necessary for printing non-constant strings into the Input Line. (eg. "I don't know how to push ", (the) obj,"."; which cannot be passes as an argument to Stat.) In NORMAL mode, this routine does nothing; except if row == -1 it will print a new_line. Most of the arguments are the same as above:

row

flag: a dual purpose token depth eg.
 
StatFont(2);
if (x1 has pluralname) print "-- They're "; else print "-- That's ";
print "clearly not portable.";
StatFont(-1); -- Response to taking a scenery object

StatFont(2);
print "You can't talk to ", (the) x1, ".";
StatFont(-1, 1); -- Trying to talk to, say, a wall.

See the "NovelEng.h" file for a lot of examples.

Note that when compiling to version 5 and using the SUMMARY_ON constant (see below) StatFont(2); will actually set the cursor to the (2 + SUMMARY_ON)th line of the Input Line; the first few being a SUMMARY line. When printing to the Input Line you should consider it a separate entity to the Summary Window to avoid confusion.

Summary

The game has an-inbuilt SUMMARY verb, which provides the player with the name of the location he's currently in.

With the library routine, you can add comments to the location using the location.status property. eg

Place "Forest"
with status [;
if (player has general) print ", feeling sleepy"; rtrue;
],
...
will generate "Forest" if the player hasnt general, "Forest, feeling sleepy" if he does.

This can be extended, by writing your own SummarySub above the inclusion of Novel.h. It should take the following form:

[ SummarySub;
StatFont(1);
! Print here whatever you want to tell the player. To write to the 1st line, use StatFont(1). To write to the 2nd
!line use StatFont(2). Be careful not to produce more than 2 lines of text, or adjust the depth of the input line
!using StatFont(2, 0, n);
! Note - if the player is in NORMAL mode neither of these calls will print anything. So to move to the next line
!in this case use
! if (~~upperprompt) new_line; ! ie. If in NORMAL mode, print a new_line.
!When you've finished, wait for a keypress before clearing the window and reprinting the prompt
!Except in NORMAL mode just print a new_line
if (upperprompt) @read_char 1 0 0 keypressed;
! You should use the keypressed variable for anything which clears the window before reprinting, so that if a player
!starts to type a command the first character isn't lost. See the ManualBuffer routine.
StatFont(1); StatFont(2); StatFont(-1);
rtrue;
];


The Summary_On Constant

By defining the SUMMARY_ON constant the top of your source code, this will create an additional window at the top of the screen which displays the Summary information after every turn (like an ordinary status bar). The constant should be set equal to the number of lines the Summary bar needs (for example, if it's just a location, Constant SUMMARY_ON = 1; will do) and a SummarySub should be written which will display the relevant information.

The SUMMARY_ON SummarySub routine is passed one argument: the current active window. The routine should begin by switching to the SummaryWin Window and finish by switching back to the original window.

[ Summary Sub oldwin;
SummaryWin.Activate(); SummaryWin.Erase();
...
oldwin.Activate();
];
This routine should not ask for keypresses, and not exceed the number of lines depth specified by the value of the SUMMARY_ON constant. You can set the cursor position within it using:
SummaryWin.SetCursor(row, col);
row and col[umn] are measured in "units", and the size of a character in "units" is given by the GetCharHeight and GetCharWidth properties. So, for example, to set the cursor to a point on the second row, four characters in:
SummaryWin.SetCursor( 2 * SummaryWin.GetCharHeight(), 4 * SummaryWin.GetCharWidth() );
See the ManualBuffer and StatFont routines for examples.

In version 5 output row and col are specified in characters, but here the GetCharWidth and GetCharHeight properties will always return a value of 1, so the same cursor-setting code is valid for both.

Inventory

The inventory display is a tricky one to do well in Novel mode, because it is just a ream of generated text. The library makes no attempt to simplfy this problem, which is probably best dealt with by lots of special cases and very few carryable objects indeed. (My Angel has around seven, in contrast to the author's previous work, which has about a hundred and fifty).

The best NovelLib will do for you is prevent the "list" format of inventory appearing whilst in NOVEL mode. Rather the inventory is displayed in its English (list) form, as a paragraph of perfunctory text. This can be changed by writing your own InvSub routine, and placing it before the inclusion of the "Novel.h" file.

Up to Contents


Other Points

Up to Contents



COPYRIGHT NOTICES

The Inform compiler is copyright Graham Nelson. The modifications in the distributed version were written by Sean T. Barret. The modified version is distributed with the kind permission of both.

The files "Novel.h", "NovelDef.h", "NovelEng.h" and "Novelpar.h" are modifications of standard Inform routines and a few initialisation routines for the interface, by Jon Ingold.

NovelLib may be used freely in any Inform-written non-commercial game under the same conditions as those controlling the release of any Inform game. Its use in a commercial game is allowed with permission from Jon Ingold. If a game has been compiled in the v6 format, also see the copyright notice at the start of the "v6.h" header file.

Up to Contents