# Welcome to Inform ## Preface ^^{Inform 6} ^^{inform-fiction.org+web+} ^^{borogove.app+web+} Welcome to Inform, a design system for interactive fiction based on natural language. Interactive fiction is a literary form which involves programming a computer so that it presents a reader with a text which can be explored. Inform aims to make the burden of learning to program such texts as light as possible. It is a tool for writers intrigued by computing, and computer programmers intrigued by writing. Perhaps these are not so very different pursuits, in their rewards and pleasures. > The sheer joy of making things... the fascination of fashioning complex puzzle-like objects of interlocking moving parts and watching them work in subtle cycles... the delight of working in such a tractable medium. The programmer, like the poet, works only slightly removed from pure thought-stuff. He builds his castles in the air, from air, creating by exertion of the imagination. > — ^{@Frederick P. Brooks}, The Mythical Man-Month, 1972 **Writing with Inform** is one of two interlinked books included with Inform: a concise but complete guide to the system, which emphasises getting started quickly. Each subsequent chapter then extends the range of techniques available to make livelier and more intriguing situations. The other book is **The Inform Recipe Book**, a comprehensive collection of examples, intended to be copied, borrowed, and adapted by users as needed. At one time, Inform looked to users like an app rather than a language — there is one app for MacOS, one for Windows, one for Linux — and those apps remain a very convenient and widely-used way to write interactive fiction in Inform. But nowadays there is also a well-designed online environment enabling Inform to be written using only a web browser, [borogove.app](https://borogove.app), and there is also extensive support for Inform as a suite of command-line tools for those who prefer to code from a terminal, or compile non-interactively in Docker containers, or GitHub actions. Those low-level tools have numerous housekeeping features which it wouldn't be sensible to cover here, because this is only a book about the Inform language. Manuals for the Inform toolchain can instead be found at [the core Inform repository on GitHub](https://github.com/ganelson/inform). What we now call Inform is strictly speaking "Inform 7", not its 20th-century predecessor, Inform 6. Here "6" and "7" are part of the _names_ of these two different programming languages, and not version numbers. (Inform does have a version number, but it's currently up around "v10.2.0".) In this book, "Inform" always means I7, but I6 notation does make occasional appearances because there are advanced Inform features where this notation is used to express some advanced, low-level coding effects. Most users will never need to know anything about I6, but for those who do, its website is at [inform-fiction.org](https://inform-fiction.org), and here is the [Inform 6 git repository](https://github.com/DavidKinder/Inform6). > Programming is best regarded as the process of creating works of literature, which are meant to be read... so we ought to address them to people, not to machines. > — ^{@Donald Knuth}, *Literate Programming,* 1981 ## Acknowledgements Inform 7 is dedicated to ^{@Emily Short} and ^{@Andrew Plotkin}, whose shrewd and sceptical suggestions made a contribution which can hardly be overstated. A long email correspondence with Andrew entirely subverted my original thoughts about natural-language IF, as he convinced me that the "new model" of rule-based IF was a truer foundation; while Emily's wry, witty analysis and how-about-this? cheered me at low moments, besides providing the impetus and often the specifics for a lot of the best ideas. From the outset, I have thought of Inform 7 as no longer being a command-line compiler, but a compiler in combination with a humanising user interface. All credit for the reference implementation under Mac OS X belongs to ^{@Andrew Hunter}. How simple the metaphor of an interactive book with facing pages may seem, but the coding was an enormous challenge. In 2014 ^{@Toby Nelson}, my brother, put months of time into the project by rewriting and modernising the Mac OS X application: sandboxing it for the Mac App Store, giving it a more contemporary design, and much more. He continues to maintain it today. Though ^{@David Kinder}'s Windows application does indeed visually follow the OS X original, the two programs were coded independently, and the programming task taken up by David was formidable indeed. ^{@Philip Chimento}'s Gnome-based user interface for Linux became officially part of the project in November 2007, when the first easy-to-install packages for Ubuntu and Fedora were offered. ^{@Adam Thornton} gave invaluable assistance in the closed-source age of Inform to make generic Unix binaries available, too. While Inform is not strictly speaking a project of the [Interactive Fiction Technology Foundation](https://iftechfoundation.org/) (IFTF), it benefits enormously from the Foundation's good work. In particular, the Narrascope conferences were invaluable in the period 2017-2022, and I thank ^{@Judith Pintar} and ^{@Andrew Plotkin} for arranging speaking slots at them. Inform in its widest sense incorporates work by so many people that it's simply impossible to thank all of them, but ^{@Zed Lopez}, ^{@Dannii Willis}, ^{@Mark Musante}, ^{@Brian Rushton}, ^{@Dan Fabulich}, ^{@Hugo Labrande}, ^{@Erik Temple}, ^{@Ron Newcomb}, ^{@Eric Eve}, ^{@Justin de Vesine} and ^{@Juhana Leinonen} all deserve special mention. Many hundreds of users have filed patient and careful bug reports, keeping us on the straight and narrow. They're contributors, too. The documentation for Inform is now a project in its own right, and ^{@Zed Lopez} deserves particular thanks for combing through all this text, and for work on the revision of 2024 when we migrated to using Markdown and a different set of tooling. The original development of Inform 7 was a long haul, and I would particularly like to thank ^{@Sonja Kesserich}, ^{@David Cornelson} and other volunteers for their early testing of a then-fragile system. The final months before the Public Beta release of Inform 7 were made more enjoyable, as well as more productive, by fruitful discussions leading to a cross-platform standard for bibliographic data and cover art. Special mentions to ^{@L. Ross Raszewski}, who wrote frighteningly efficient reference software in frighteningly little time; the librarians of the IF-Archive, Andrew Plotkin, David Kinder and ^{@Paul Mazaitis}; and my fellow authors of IF design systems – ^{@Mike Roberts} (of the Text Adventure Development System); ^{@Kent Tessman} (of Hugo); and ^{@Campbell Wild} (of ADRIFT). {EPUB:}This ePub edition of the documentation was greatly assisted by excellent advice published by ^{@Liza Daly}, an old friend of Inform's. ## The facing pages ^^{user interface <-- interface <-- IDE interface} ^^{user interface: facing pages layout} {OSX:}This Public Beta of Inform 7 runs on Mac OS X through the graphical user interface created by Andrew Hunter and Toby Nelson. {Windows:}This Public Beta of Inform 7 runs on Windows through the graphical user interface created by David Kinder. {Linux:}This Public Beta of Inform 7 runs on Linux through the text-only interface created by Adam Thornton. {GNOME:}This Public Beta of Inform 7 runs on Linux through the graphical user interface created by Philip Chimento. {OSX:}The main window is an opened book showing two facing pages, and as we shall see it behaves as if these pages are in dialogue with each other: for the most part we write on the left hand page and see responses appear on the right. But all is controllable. The margin between the two pages can be dragged back and forth like the slide on a trombone: each page can be made smaller that the other may grow larger. Moreover, each page can display one of a number of displays relevant to the current project, called "panels", one of them being the Documentation panel which displays this manual. The vertical strip of choices at the right hand margin of each page allows you to choose between panels. (The same panel can be showing on both pages at the same time, if that's useful.) {Windows:}The main window is an opened book showing two facing pages, and as we shall see it behaves as if these pages are in dialogue with each other: for the most part we write on the left hand page and see responses appear on the right. But all is controllable. The margin between the two pages can be dragged back and forth like the slide on a trombone: each page can be made smaller that the other may grow larger. Moreover, each page can display one of a number of displays relevant to the current project, called "panels", one of them being the Documentation panel which displays this manual. The horizontal strip of choices at the top of each page allows you to choose between panels. (The same panel can be showing on both pages at the same time, if that's useful.) {Linux:}The interface is extremely crude compared to that available on Mac OS X or Windows. The panels that exist are accessible via menu options, and anywhere you see reference to a button, it simply doesn't exist. Go and Release are implemented, as is Compile, which rebuilds the story but does not start it. There is a further settings panel available to you, the IDE settings, which allows you to control which editor you wish to use to edit your project, which browser allows you to view HTML files, which interpreters to use to play your stories, and whether or not these should be run in the background. Users with a graphical desktop are likely to want to choose the background option, while those running only with text terminals will not. To select an option, type the letter indicated on the screen and follow it with the Enter key. {GNOME:}The main window is an opened book showing two facing pages, and as we shall see it behaves as if these pages are in dialogue with each other: for the most part we write on the left hand page and see responses appear on the right. But all is controllable. The margin between the two pages can be dragged back and forth like the slide on a trombone: each page can be made smaller that the other may grow larger. Moreover, each page can display one of a number of displays relevant to the current project, called "panels", one of them being the Documentation panel which displays this manual. The vertical strip of choices at the right hand margin of each page allows you to choose between panels. (The same panel can be showing on both pages at the same time, if that's useful.) {^app:}On most computers, Inform runs in a single main window which is an opened book showing two facing pages. As we shall see it behaves as if these pages are in dialogue with each other: for the most part we write on the left hand page and see responses appear on the right. But all is controllable. The margin between the two pages can be dragged back and forth like the slide on a trombone: each page can be made smaller that the other may grow larger. Moreover, each page can display one of a number of displays relevant to the current project, called "panels", one of them being the Documentation panel which displays a screen-readable copy of this manual. The vertical strip of choices at the right hand margin of each page allows you to choose between panels. (The same panel can be showing on both pages at the same time, if that's useful.) At the start the only panels available are a blank space in which to write the first lines of a new interactive fiction – the Source panel – and this one, the Documentation. Clicking on the other choices will do nothing. The exception is the Settings panel, which contains some preference settings for the individual project – not the whole application. This is always available, but it controls settings which can be left alone almost all of the time. ## The Go! button {PM_StartsOutsideRooms} {PM_NoStartRoom} ^^{user interface: Go button} ^^{Go button+ui+} Clicking the Go button translates the text in the Source panel into a computer program which enacts the interactive fiction, and automatically sets it going (in the Story panel, which opens as needed). All Inform stories take place in one or more "rooms". These need not be indoor locations, and can represent anything from grassy fields to states of mind. If we click Go when there's no text at all in the Source panel, Inform will perhaps surprisingly still make a story, though a very empty one. It will create a room for the story to take place in, and put the player in it, but nothing else will exist and there will be nothing to do or look at. So instead we'll supply a title and a name for the opening room: {*}"Midsummer Day" The Gazebo is a room. Clicking Go with this text in the Source panel will result in a short delay, after which the Story panel will appear, from which we can explore this newly created world: an interactive fiction called "Midsummer Day". It will not be very exciting, since Inform has only five words to go on, but we can add more detail to the source at any point and then click Go again to try out the changes. (Note that there is no need to "quit" these explorations in the Story panel. When Go is clicked, any story already in progress is discarded in favour of the new version.) {OSX:}Typing Command-R has the same effect as clicking Go. If Inform is running on Mac OS 10.3.9 or later, clicking on a "text" icon ![paste](doc_images/paste.png) in this documentation copies the example text which follows it into the Source as if you had faithfully typed it out. (This icon is usually provided only for fairly long examples, but note that you can in fact copy and paste any text from this documentation into the source by selecting it with the mouse, typing Command-C, then clicking to a position in the source and typing Command-V.) {Windows:}Typing F5 has the same effect as clicking Go. Clicking on a "text" icon ![paste](doc_images/paste.png) in this documentation copies the example text which follows it into the Source as if you had faithfully typed it out. (This icon is usually provided only for fairly long examples, but note that you can in fact copy and paste any text from this documentation into the source by selecting it with the mouse, typing Ctrl-C, then clicking to a position in the source and typing Ctrl-V.) {Linux:}Typing "G" is the only way you can perform the Go action. {GNOME:}Typing Ctrl-R has the same effect as clicking Go. Clicking on a "text" icon ![paste](doc_images/paste.png) in this documentation copies the example text which follows it into the Source as if you had faithfully typed it out. (This icon is usually provided only for fairly long examples, but note that you can in fact copy and paste any text from this documentation into the source by selecting it with the mouse, typing Ctrl-C, then clicking to a position in the source and typing Ctrl-V.) {^app:}The keyboard shortcut Command-R (on Mac OS X), F5 (on Windows), or Ctrl-R (on Linux GNOME) has the same effect as clicking Go. ## The Replay button ^^{user interface: Replay button} ^^{Replay button+ui+} Replay works identically to Go, except that it does something further: once the story is created, it automatically plays through the same commands as were typed into the previous version. For instance: suppose we click Go to bring Midsummer Day into being, and find ourselves playing the story. We type ``LOOK`` and find that there is not much to see. Going back to the source, we add "A white canvas parasol raised up on stakes driven into the grass." so that the source now reads {*}"Midsummer Day" The Gazebo is a room. "A white canvas parasol raised up on stakes driven into the grass." Instead of clicking Go, we click Replay, and can sit back and watch what has changed. In this example, it only saves us the trouble of typing ``LOOK``, but once stories become long and elaborate, Replay is invaluable: and especially when we notice in play that something very minor is wrong – a spelling error, say – and want to fix it immediately, without fuss. {Linux:}Replay is not implemented in the text-mode Linux interface. ## The Index and Results panels ^^{user interface: Index panel} ^^{Index panel+ui+} ^^{user interface: Results panel} ^^{Results panel+ui+} If, when Go! is clicked, the text in the Source panel is not fully understood, then Inform will generate a report of the problems it found, which will open in the "Results" panel. (Other information is also available in "Results", but most of it is used for debugging Inform, and can be ignored.) On the other hand, if the text was fully understood then another new panel will become available: the "Index". This is a cross-referenced index of the source, or rather, of the interactive fiction which has been generated. The Index is only an optional convenience, but becomes more and more helpful as the fiction grows larger. Its exact format does not matter for now. The icon ![Reveal](doc_images/Reveal.png) always denotes a reference to a particular line in the Source text, that is, to something written in the source: clicking it opens the Source panel and jumps to that position. The icon ![Below](doc_images/Below.png) indicates that more detailed information can be read further down the text in the same panel: clicking it jumps down to this more detailed report. Lastly, the icon ![help](doc_images/help.png) hints that there is a relevant page of this manual: clicking this opens the Documentation panel and switches to it. {Linux:}The Index is accessible by typing "I" at the prompt, if you have set your browser. You can set the browser by typing "S" to get to the settings panel, and then "I" for the IDE panel. From the top-level Index you will be able to access Results as well as other information. ## The Skein or Testing panel ^^{user interface: Skein panel} ^^{Skein panel+ui+} ^^{user interface: Testing panel} ^^{Testing panel+ui+} ^^{user interface: Replay button} ^^{Replay button+ui+} The Replay button demonstrates that Inform must be quietly remembering the commands typed into the last run through the story. In fact it remembers, and automatically organises, *every* previous run. Inform's approach to testing interactive fiction is to treat it as being like the analysis of other turn-based games, such as chess. It would be prohibitively difficult to work out every possible combination of moves: instead, we analyse those which go somewhere, and look for significant choices. Every Queen's Gambit begins with the same first three moves (1. d4, d5; 2. c4), but then there is a choice, as the next move decides whether we have a Queen's Gambit Accepted (dxc4) or Declined (e6). Books about chess often contain great tables of such openings, which run together for a while but eventually diverge. To learn chess, one must explore all of these variations. How this looks is different in different Inform apps, but this is usually presented in a panel called either Skein or Testing, which presents the "skein", a sort of braid made up of the threads of past commands and responses. Because the user interface looks slightly different on different versions of the Inform apps (that is, the MacOS version is not quite the same as the Windows version, and so on), this manual is not the best place to describe it. In any case, the best way to find out about it is probably to experiment. # The Source Text ## Creating the world {PM_NoSuchVerb} {PM_NoSuchVerbComma} {PM_NegatedVerb1} {PM_TwoLikelihoods} {PM_CantAssertAdjective} {PM_CantAssertNegatedEverywhere} {PM_CantAssertNegatedRelations} {PM_CantAssertNonKind} {PM_CantAssertQuantifier} ^^{|is <-- to be} ^^{initial state of the world <-- beginning of story <-- introduction} ^^{starting conditions} ^^{assertions}^^^{initial state of the world <-- story structure: beginning} Designing an interactive fiction divides into two parts. One part is the creation of the world as it appears at the start of the story: where and what everything is. The other is to specify what people say and do when the story is running, by giving rules which shape how the player interacts with the world. A new Inform project starts with a world which is void and without form, so to speak, with nothing created: but it starts with hundreds of standard rules already in place. The same division between creating things, and laying down rules, is visible in Inform source text. The creation of the world is done by making unconditional factual statements (sometimes called "assertions") about it. For example: The Gazebo is a room. The wood-slatted crate is in the Gazebo. The crate is a container. The verb is always written in the present tense (so the crate `is`, not `will be`, in the Gazebo). But the verb is not necessarily `is`: Mr Jones wears a top hat. The crate contains a croquet mallet. Verbs like `is`, `wears` and `contains` are from a small basic stock built in to Inform: *to be*, *to have*, *to carry*, *to wear*, *to contain*, *to support* and a few others less frequently used. Authors can then add whatever new verbs make it easier to tell the story. For example, in a romance, *to love* might be convenient, but in other stories not. In the same way, sentences like `The Gazebo is a room.` and `The crate is a container.` use a very small built-in set of common nouns: in this case, `room` and `container`. But other common nouns can easily be added. Inform would initially reject the sentence `The Gazebo is a garden area.` because it does not know what a `garden area` is, but the author can teach it by writing `A garden area is a kind of room.` So, once again, a small core vocabulary will gradually be expanded by the author to meet the needs of the story. The world described by these assertions is the starting condition of the story: what happens when play begins is another matter. If somebody picks up the crate and walks off with it, then it will no longer be in the Gazebo. Mr Jones may remove his hat. This is what is done with _rules_, which are the subject of the next section. ## Making rules ^^{rules: defining} ^^{defining: rules}^^^{defining <-- creating} ^^{+to+if (a condition)} ^^{+to+now (a condition)} ^^{Phrases page of Index panel+ui+} ^^{user interface: Index panel: Phrases page} ^^{Index panel+ui+: Phrases page} So, then, part of the source text for a story is taken up with assertions like `The crate contains a croquet mallet.` Those describe only the initial situation. But the source text also has to say what happens as the player interacts with the situation. It does that with rules. Rules tell Inform what should happen in certain circumstances. They read like an instruction issued to someone: Instead of taking the crate, say "It's far too heavy to lift." This rule changes the crate's behaviour. The player who tries typing ``TAKE CRATE``, ``PICK UP THE CRATE`` or similar will be met only with the unhelpful reply ``It's far too heavy to lift.`` The many different kinds of thing which the player can do are called _actions_, and are always written as participles: `taking the crate`, for instance, or `putting the crate on the table`. Whereas the world of the story initially has no rooms, no people and no things, and the author has to create everything, it begins with a mass of several hundred rules, some quite complex, and it could even be said that Inform *is* that mass of rules. The aim is to provide a basic, penny-plain, vanilla flavoured sort of realism. It would be surprising if one could put the crate inside itself, so a rule exists to forbid this. It would be surprising if one could drop something on the ground if it was already on the ground, and so on. These hundreds of unseen rules can be browsed in the Index of a project, and we will later see how to modify or waive them, but almost all authors want these rules to apply almost all of the time. A rule always starts with a situation which it applies to, and then follows with one or more things to do. Here's an example where the situation is `Before taking the crate` – the player is just starting to try to pick the box up: Before taking the crate: if the player is wearing the hat: now the hat is in the crate; say "As you stoop down, your hat falls into the crate." The steps to follow here are called "phrases". Inform knows about 400 built-in phrases (and once again, authors can add more), but most of them are needed only occasionally. These three are used over and over again: * `if` tells Inform to do something only if some _condition_ holds, here `the player is wearing the hat`; * `now` tells Inform to change the situation, here so that the hat moves to the crate; and * `say` tells Inform to write some story text for the player to read. Every one of the built-in phrases has a definition somewhere in this book. The full definition of `say` will come later, but in the simple form above it writes out the given text for the player to read. (Normally this text is simply shown on screen, not spoken aloud, unless software adapted for partially sighted people is being used.) Phrase definitions are all linked to in the Phrases page of a project's Index. ## Punctuation {PM_UnendingQuote} {PM_UnendingComment} {PM_TooMuchQuotedText} {PM_WordTooLong} {PM_EnigmaticPronoun} {PM_EnigmaticThey} ^^{punctuation} ^^{punctuation: full stop: ending sentences with line breaks} ^^{|.: ending sentences with line breaks}^^^{punctuation: full stop <-- full stop <-- period}^^^{punctuation: full stop <-- punctuation: period}^^^{punctuation: square brackets <-- square brackets} ^^{punctuation: square brackets: comments} ^^{|[ ]: comments} ^^{punctuation: square brackets: text substitutions} ^^{|[ ]: text substitutions} ^^{punctuation: question mark, ending sentences <-- question mark} ^^{(?), ending sentences+sourcepart+} ^^{punctuation: exclamation mark, ending sentences <-- exclamation mark} ^^{(!), ending sentences+sourcepart+} ^^{punctuation: apostrophe: meaning quotation mark <-- apostrophe} ^^{|': meaning (")+sourcepart+}^^^{punctuation: quotation marks <-- quotation marks} ^^{punctuation: quotation marks: defining texts} ^^{|": defining texts} ^^{comments: in source text} ^^{line breaks: produced by sentence-ending punctuation} The first thing we all learn about punctuation is that full stops finish a sentence. So this is read as two sentences, not one: Mr Jones wears a top hat. The crate contains a croquet mallet. But a full stop also closes a sentence in Inform even when it occurs inside quotation marks, provided there is no indication to the contrary. Thus: An apple is here. The description is "Shiny." It is edible. is read as three sentences, not two. It is equivalent to: An apple is here. The description is "Shiny.". It is edible. (which also works). Sentence breaks like this occur only when the final character of the quoted text is a full stop `.`, question mark `?` or exclamation mark `!`, or one of these three followed by a close bracket `)`; and only when the next word of the source text begins with a capital letter. (So in this example, the `I` of `It` is the letter in question.) A paragraph break also divides sentences, behaving as if it were a full stop. So this: Mr Jones wears a top hat The crate contains a croquet mallet. is two sentences, not one with a strange vertical gap in it. But this is not good style, and authors should try to use normal English punctuation when possible. Also, note that a single line break is not a paragraph break. This: Mr Jones wears a top hat The crate contains a croquet mallet. ...is read as one sentence, not two, even though it doesn't make very good sense that way. All of this is to say that punctuation is not just decoration in Inform: it affects what the source text means. Material in square brackets `[like so]` is _comment_, in computing jargon: it is considered as being an aside, a private note by the author, and not read in by Inform. This allows us to make notes to ourselves like so: The China Shop is a room. [Remember to work out what happens if the bull gets in here!] Inform is all about text, so pieces of text are often quoted in Inform source. This example is typical: An apple is here. The description is "Shiny." It is edible. Quotations always use double-quotation marks, which aren't part of the text. So the description here is just the five letters and full stop in between the marks. That seems straightforward, but there are three conventions to watch out for. 1. Square brackets `[` and `]` inside quoted text don't literally mean "[" and "]". They're used to describe what Inform should say, but in a non-literal way. For example, "Your watch reads [time of day]." might produce ``Your watch reads 9:02 AM.`` These are called _text substitutions_. They're highly flexible, and can take many different forms. 2. Single quotation marks at the edges of words are printed as double. So: "Simon says, 'It's far too heavy to lift.'" produces ``Simon says, "It's far too heavy to lift."`` 3. Texts which end with sentence-ending punctuation – full stop, question mark, exclamation mark – are printed with a line break after them. So: say "I don't know how this ends"; say "I know just how this ends!"; would come out quite differently – this doesn't affect the appearance of the text, but only the position where the next text will appear. Something to be careful about is that this only applies when the punctuation occurs at the end of a `say`, as in these examples. (It doesn't apply when a varying textual value is printed, using some text substitution, because then the pattern of where line breaks occur would be unpredictable – sometimes the value might end in a punctuation mark, sometimes not.) These three punctuation rules for texts feel very natural with practice, and Inform users sometimes don't realise the third rule is even there, because it just seems the right thing to happen. But occasionally the rules get in the way of what we want to do. (For instance, how do we get a literal ``[`` or ``]``? What if we want a single quote mark where Inform thinks we want a double, or vice versa?) So we'll come back to these rules in more detail in the chapter on [Text]. Inform also reads other punctuation marks. Colon `:` and semicolon `;` turned up in the previous section, in the writing of rules. Before taking the crate: if the player is wearing the hat: now the hat is in the crate; say "As you stoop down, your hat falls into the crate." The colon `:` indicates that a run of instructions (called _phrases_ in Inform, for traditional reasons) follows, and note that there are two of them in this definition. The semicolon `;` divides one phrase from another. But this would be wrong: Before taking the crate: if the player is wearing the hat: now the hat is in the crate. say "As you stoop down, your hat falls into the crate." The only difference is the full stop `.` at the end of the third line. That ends the rule, so Inform then tries to read the `say` line is if it were a new sentence or rule, which will not make any sense. Rules can leave out the colon and replace it with a comma `,` in just one case, when there is only one phrase which follows. So this: Instead of taking the crate, say "It's far too heavy to lift." means the same as: Instead of taking the crate: say "It's far too heavy to lift." ### See Also - [How Inform reads quoted text] for a fuller exploration of the punctuation rules for text. ## Problems ^^{error messages: for source text} ^^{problem messages: for source text} The language used in the source reads as if it were English aimed at a human reader, but in reality Inform can only understand a very modest range of sentences and will complain if its limits are passed. Subtler problems arise if the source contains contradictions. For instance, the following "Problem" might be produced: > **Problem.** You wrote 'A starting pistol is in the cup' ![Reveal](doc_images/Reveal.png), but in another sentence 'A Panama hat is on the cup' ![Reveal](doc_images/Reveal.png): the trophy cup cannot both contain things and support things, which is what you're implying here. If you need both, the easiest way is to make it either a supporter with a container attached or vice versa. For instance: 'A desk is here. On the desk is a newspaper. An openable container called the drawer is part of the desk. In the drawer is a stapler.' As this one shows, some Problem messages give long explanations, or hints as to how to avoid them. If a similar problem were to occur in the same run through, the same Problem message would be curtailed to something briefer: > **Problem.** You wrote 'A firing pistol is in the box' ![Reveal](doc_images/Reveal.png), but in another sentence 'A fedora hat is on the box' ![Reveal](doc_images/Reveal.png): again, the croquet box cannot both contain things and support things. ## Headings {HEADINGS} {PM_HeadingOverLine} {PM_HeadingStopsBeforeEndOfLine} {PM_BadTitleSentence} ^^{headings} ^^{subheadings} ^^{source text: subdivisions} ^^{title+biblio+} ^^{author+biblio+} ^^{bibliographic data} ^^{(volume)+ofsource+ --> volume} ^^{(book)+ofsource+ --> book} ^^{(part)+ofsource+ --> part} ^^{(chapter)+ofsource+ --> chapter} ^^{(section)+ofsource+ --> section} {OSX:}Once the source grows beyond 1000 words or so, it can all too easily become disorganised, and by the time it reaches the size of a novella it can be difficult to find things (though the Mac OS X user interface provides a Find function, Command-F). {Windows:}Once the source grows beyond 1000 words or so, it can all too easily become disorganised, and by the time it reaches the size of a novella it can be difficult to find things (though the Windows user interface provides a Find function, Ctrl-F). {Linux:}Once the source grows beyond 1000 words or so, it can all too easily become disorganised, and by the time it reaches the size of a novella it can be difficult to find things (though nearly all editors provide a Find function). {^app:}Once the source grows beyond 1000 words or so, it can all too easily become disorganised, and by the time it reaches the size of a novella it can be difficult to find things. (Though nearly all editors provide a Find function, and the keyboard short-cuts Command-F (Mac OS X) or Ctrl-F (Windows) do the trick in the Inform application.) Inform provides for us to organise the source code in just the way that a printed book would be organised: with headings and subheadings. Firstly, we can put the title at the top. If the first paragraph consists only of a single quoted piece of text, then that's the title; and an author can also be given, as follows: ^^{@Dave Lebling} "Spellbreaker" by Dave Lebling We will later see that more bibliographic information can also be placed here, in the same way that the imprint page of a novel comes before the text gets going. The author's name can normally be given without quotation marks, so long as it contains no punctuation. For instance: ^^{@Jerome K. Jerome} "Three Men in a Boat" by "Jerome K. Jerome" needs quotes as otherwise the full stop after the K will be mistaken for the end of a sentence. A sentence which is the only one in its paragraph and which begins with any of the words `Volume`, `Book`, `Part`, `Chapter` or `Section` is considered to be a heading or a sub-heading. For instance: Section 2 - Flamsteed's Balloon It must not contain a typed line break, and in order to stand alone in its paragraph there should be a skipped line both before and after it. There's no need for a number to have any particular format, or to be used at all: Book of Locations Part II - The Sky Headings are hierarchical: a `Part` heading is considered more significant than a `Chapter` heading but not so significant as a `Book` heading, and so on. Most stories do not use all five levels, of course. ## Why using headings is a good idea ^^{headings <-- index+ofsource+} ^^{subheadings} ^^{source text: subdivisions} ^^{outline+ofsource+} ^^{Contents page of Index panel+ui+} ^^{user interface: Index panel: Contents page} ^^{Index panel+ui+: Contents page} ^^{disambiguation: of source text} Reports of problems, as we have seen, often quote back the source to justify themselves. Rather than quoting line numbers (```Midsummer Day, line 2017``` or something similar) Inform uses the ![Reveal](doc_images/Reveal.png) icon. The down side of this is that a glance at the list of problems might give little hint of whereabouts in the source the difficulties lie. So Inform also uses headings to give a general indication: > **In Part the First, Chapter 1 - Attic Area:** > > **Problem.** You wrote 'South of the Attic is the Winery' ![Reveal](doc_images/Reveal.png), but in another sentence 'South of the Attic is the Old Furniture' ![Reveal](doc_images/Reveal.png): this looks like a contradiction, which might be because I have misunderstood what was meant to be the subject of one or both of those sentences. > > **In Chapter 2 - Deeper In:** > > **Problem.** You wrote 'The Disused Observatory is south of the Dark Room' ![Reveal](doc_images/Reveal.png), but in another sentence 'South of the Dark Room is the Cupboard' ![Reveal](doc_images/Reveal.png): again, this looks like a contradiction. Secondly, headings are used in the Contents page of the Index, and they allow rapid navigation through the source, by jumping to any heading or subheading with a single click. Finally, headings are used when working out what a name refers to. Suppose the source contains both a `four-poster bed` and also a `camp bed`, and we write something like `The pillow is on the bed.` Inform decides which bed is meant by giving priority to whichever is defined in the current section (so far), or failing that the current chapter, or current part, or current book, or finally the current volume. This allows us to write, for instance, The four-poster bed is in the Boudoir. The pillow is on the bed. and not have the pillow mysteriously turn up on the `camp bed`, which hasn't been mentioned for a long time. ## The SHOWME command ^^{SHOWME+testcmd+} ^^{testing commands: >SHOWME} ^^{Map page of Index panel+ui+} ^^{user interface: Index panel: Map page} ^^{Index panel+ui+: Map page} ^^{user interface: Release button} ^^{Release button+ui+} Problem messages are generated when the source text does not make sense to Inform. Even if it does make sense, though, there is no guarantee that it does what the author intends, and the only way to find out is to test it. When testing, it is sometimes highly convenient to have the god-like powers which are every author's right. These are provided by special testing commands, which are present in the story right up until the final release version (generated by the Release button). They will be introduced in this manual as they become relevant: here is the first. The testing command ``SHOWME`` prints out a brief summary about a room or thing, and any contents or parts it may have. Typing ``SHOWME`` on its own shows the current room, but any item or room in the story, however distant, can be named instead. For instance: > SHOWME Boudoir - room four-poster bed - supporter yourself - person pillow > SHOWME DIAMONDS diamonds - thing location: in the strongbox on the dresser in the Drawing Room unlit; inedible; opaque; portable; singular-named; improper-named description: The diamonds glitter dangerously. printed name: diamonds Much of this can be seen, and seen more easily, in the World tab of the Index panel: but that only shows the initial state of play, whereas the ``SHOWME`` command reveals the situation in mid-story. (`Room`, `supporter` and so on are kinds, of which more in Chapter 3, [Things].) ### See Also - [The TEST command] for another frequently-used testing command. - [Testing commands to inspect the situation] for the full roster of them. ## The TEST command {PM_TestMultiWord} {PM_TestDuplicate} {PM_TestBadRequirements} {PM_TestContainsUndo} {PM_TestCommandTooLong} {PM_TestDoubleWith} {PM_UnknownInternalTest} ^^{TEST+testcmd+} ^^{testing commands: >TEST} ^^{transcripts: creating with the TEST command} ^^{test (test name) with (commands)+assert+} ^^{PURLOIN+testcmd+} ^^{testing commands: >PURLOIN} ^^{>AGAIN} The only way to thoroughly test a work of IF is to run a complete solution through it, and carefully check the resulting transcript of dialogue. But most works of interactive fiction contain occasional vignettes, either in terms of short scenes of narrative, or in the behaviour of particular things or rooms. The examples in the documentation are like this: in almost every example, typing ``TEST ME`` puts the story through its paces. Tests work through a script of commands, set up like so: Test balloon with "get balloon / blow balloon / drop balloon". This has no effect on the design itself, but ensures that when the story is played, typing ``TEST BALLOON`` will run through the given three commands in sequence, as if we had typed ``GET BALLOON`` and then ``BLOW BALLOON`` and then ``DROP BALLOON``. The name for the test (`balloon` in this example) has to be a single word. Typing just ``TEST`` at the story prompt gives a list of all the test scripts known to the story. Test scripts can make use of each other, for instance: Test all with "test balloon / test door". One convenient way to keep track of the solution for a work being written is to include a test script at the end of each section, and to place a master test script (like ``TEST ALL``) at the top of the source. But different designers will prefer different approaches, and this testing system is no more than an optional convenience. Many tests will only be sensible in given places, which may be hard to reach from the initial position; or with the aid of given things, which may be difficult to obtain. We are therefore allowed to add stipulations to test scripts: Test balloon with "get balloon / blow balloon / drop balloon" holding the balloon. The `holding the balloon` means that the balloon will be transferred to the player's ownership immediately before the test script is run, unless it is already held. Similarly: Test jam with "get jam / taste jam / eat jam" in the Kitchen. Or we might want to say both: Test jam with "get jam / taste jam / eat jam" in the Kitchen holding the jam. (Single quotation marks in test scripts are interpreted the same way in test scripts as they are in other text: that is, they are sometimes read as double-quotes unless they appear to be present as apostrophes. The notation `[']` forces a single quotation mark if necessary. Similarly, `[/]` forces a literal forward slash, and prevents the `/` from being read as dividing up two commands.) A word of warning: if the _first_ command in the test is ``AGAIN``, that will likely repeat the ``TEST`` command, sending Inform round in circles forever. But something like `"give tribute to minotaur / again"` is safe enough. ### See Also - [Testing commands to inspect the situation] for the full set of testing commands. ## Material not for release ^^{release version (of the story)} ^^{test version (of the story) <-- debug version (of the story)} ^^{omitting code, for release version} ^^{|not for release} ^^{|for release only} ^^{testing commands <-- debugging commands} ^^{testing commands: defining} ^^{defining: testing commands} ^^{headings} ^^{subheadings} ^^{source text: subdivisions} Special testing commands, like ``TEST`` and ``SHOWME``, are automatically excluded from the story if it is exported from the Inform application using the Release button. We sometimes want to write our own for-testing-purposes-only code, though, and for this purpose we are allowed to designate whole headings as being "not for release": {*}Section 10 - Open sesame - Not for release Universal opening is an action applying to nothing. Understand "open sesame" as universal opening. Carry out universal opening: now all doors are open. Report universal opening: say "Open Sesame!" Clearly we do not wish the final reader to be able to type ``OPEN SESAME``, so this whole heading will be disregarded in the Release version, as will any heading whose name includes `not for release`. Note that if a chapter, say, is marked as `not for release`, then its subheadings (mere sections) will also not be for release. If in doubt, check the "Contents" index: if any section is `not for release` then so are all of its subheadings. The reverse effect is produced by: Section 10 - Open sesame - For release only That is, it marks material included only in a Release version. ## Including extensions {PM_BogusExtension} {PM_IncludeExtQuoted} {PM_ExtVersionMalformed} {PM_ExtMiswordedBeginsHere} {PM_ExtInadequateVM} {PM_ExtMisidentifiedEnds} ^^{extensions: installing} ^^{files (compiling): extensions} ^^{extensions: using} ^^{include (extension) by (extension author)+assert+} ^^{Locksmith+ext+} ^^{extensions: specific extensions: Locksmith} _Extensions_ are additional packets of rules or other facilities which provide additional features to an Inform story. Writing and sharing extensions has always been a flourishing part of Inform culture. For the user of an extension, the advantage is clear: why go to great trouble to (say) work out how to make doors open automatically as needed, when somebody else has already perfected this? For the writer of an extension, there is the satisfaction of producing a good solution to a ticklish problem, and contributing to the public good. As a typical example of what extensions do, `Locksmith by Emily Short` provides a more detailed handling of locks and sets of keys. It would be invaluable for a story which a lot of locked doors, such as a murder mystery, but plenty of other stories would have no need of it. Because of that, these features are left to an extension to provide, rather than being built in. Extension names consist of a title, then `by`, then the name of an author. For example, this is a valid extension name: Following People by Mary Brown To be used, an extension must first be got hold of. There are several ways to do that: 1) download it from, say, Mary Brown's website; 2) copy it over from another project; 3) download it from the Public Library feature of the Inform apps, which offer access to some popular extensions from the Inform website. In cases (1) and (2), we would then need to use a feature of the Inform app to add an extension file to a project. An extension can either be a simple file with the file extension `.i7x` (say, `Locksmith.i7x`), or a mass of resources zipped up into a single file and with the extension `.i7xd`. The Inform app is equally happy to use either. In case (3), installation happens automatically when the download completes. Either way, an important change made to Inform in 2023 was that each project now has its own independent set of extensions. In the past, it was possible to download an extension to a central pool kept on the user's computer somewhere, and then they would be shared by all of that user's stories. This is no longer true. **Each project now has its own independent set of extensions.** The Extensions tab in the Inform app shows what is currently installed in a project. Once an extension is installed, it still needs to be _included_. This is done with a sentence in the source text for the project, usually somewhere at the top. For example: Include Locksmith by Emily Short. Note that it is compulsory to name both extension and author. Many extensions come with their own documentation. Again, the Extensions tab in the app shows this. Newcomers will probably not need extensions for quite some while, let alone need to write new ones, but they're quite straightforward to make. The final chapter of this book, [Extensions], covers the writing of new extensions. ## Use options {PM_UONotNumerical} {PM_UnknownUseOption} {OPTIONS} ^^{use options} ^^{use (options...)+assert+} ^^{punctuation: comma: displaying serial comma} ^^^{punctuation: comma <-- comma} ^^{|,: displaying serial comma} ^^{scoring: enabling} ^^{descriptions (displayed): full-length room descriptions / abbreviated room descriptions} ^^{rooms+kind+: descriptions <-- descriptions (displayed): room descriptions} ^^{use options: catalogue: |American dialect} ^^{American dialect+useopt+} ^^{use options: catalogue: |the serial comma} ^^{serial comma+useopt+} ^^{use options: catalogue: |scoring} ^^{scoring+useopt+} ^^{use options: catalogue: |full-length room descriptions} ^^{full-length room descriptions+useopt+} ^^{use options: catalogue: |abbreviated room descriptions} ^^{abbreviated room descriptions+useopt+} ^^{use options: catalogue: |VERBOSE room descriptions} ^^{VERBOSE room descriptions+useopt+} ^^{use options: catalogue: |nameless room descriptions} ^^{nameless room descriptions+useopt+} ^^{use options: catalogue: |BRIEF room descriptions} ^^{BRIEF room descriptions+useopt+} ^^{use options: catalogue: |SUPERBRIEF room descriptions} ^^{SUPERBRIEF room descriptions+useopt+} ^^{use options: catalogue: |undo prevention} ^^{undo prevention+useopt+} ^^{>UNDO} One more preliminary. Inform has a small number of optional settings which affect the result of translating the source. The sentence: Use American dialect. makes the resulting work of IF use American spellings (except where the designer spells otherwise) and the American convention for spelling out numbers (thus, ``one hundred seventeen`` not ``one hundred and seventeen``). Similarly: Use the serial comma. uses a comma when printing lists: thus ``Julian, Dick, George, and Anne`` rather than ``Julian, Dick, George and Anne``. A more profound change is made by Use scoring. which introduces the concept of a numerical score – something which modern authors of interactive fiction often feel is inappropriate, which is why Inform only provides it on request. Two alternative options: Use full-length room descriptions. Use abbreviated room descriptions. change the normal way room descriptions are shown: normally they are given in full, but in abbreviated mode, they're never given. (The latter is a bad idea in any publicly released story, but is provided for completeness and in case it may help testing.) Alternatively, we can set the traditional ^{Infocom}-style of room description to any of ``VERBOSE``, ``BRIEF`` and ``SUPERBRIEF``: Use verbose room descriptions. Use brief room descriptions. Use superbrief room descriptions. The default is ``VERBOSE``. Another option affecting room descriptions is: Use nameless room descriptions. This suppresses the usual boldface printed name of a room which appears at the top of a description. Next we have: Use undo prevention. which disables the ``UNDO`` verb, both in play and after death, for the benefit of stories which are heavily randomised and where we do not want players to keep on ``UNDO``-ing until they get a random outcome which is to their taste. (Many players consider ``UNDO`` to be their birthright, and that any work using this option is an abomination: indeed, it has even been suggested that this section of the Inform documentation be censored. To use the option is to court controversy if not outright hostility.) We can combine any number of options in a single "Use" sentence, so for example: Use American dialect and the serial comma. brings about both of these changes. ## Limits and the Settings panel {PM_BadICLIdentifier} {STORYFILES} ^^{limits: of Inform 6 compiler} ^^{limits: of story file} ^^{memory limits} ^^{memory economy+useopt+} ^^{Inform 6} ^^{Z-machine} ^^{Glulx} ^^{virtual machine} ^^{Z-machine: memory limits} ^^{Glulx: memory limits} ^^{virtual machine: memory limits} ^^{use options: catalogue: |memory economy} ^^{use options: catalogue: Inform 6 memory limits} ^^{PunyInform} ^^{Inform 6: PunyInform} No computer has unlimited capacity, and a large, complex project may eventually bump its head against the ceiling. Inform is a system for translating textual descriptions of interactive fiction into _story files_. No single format of story file is standard to the IF community. The formats developed over the history of IF differ in three key respects: - the range of computers or devices capable of playing them; - how large they are, that is, how much play they can express; - what extra-textual effects they can bring off. Inform can write to two different formats. Neither of these is proprietary, and neither was created by the authors of Inform: each format is a community property, defined by published standards documents. An individual Inform project can make its own choice of story file format, using that project's Settings panel. Outside the Inform app, Inform can even be used at the command line to generate C programs rather than story files, and those can be compiled to run on almost any computer. Newly created projects are set up with the Glulx format. This has largely taken over from an earlier format called the Z-machine, but Inform can still generate a version 8 Z-machine file (a so-called "z8") if required. The Z-machine is of great historic importance, but most users will want to keep the Glulx format set all of the time. The Z-machine itself came in a number of versions, and Inform 7 can only usefully make stories for its largest form (though even that was tiny by modern standards). Authors who want to use Inform to compile new works of IF for highly memory-constrained retro hardware — for example, vintage Commodore 64s or BBC Micros from the early 1980s, whose total memory is smaller than the storage now needed for a single app icon — are better off using Inform 6 than Inform 7, and using special libraries tailored for a low memory overhead. See for example [the Puny Inform project website](https://github.com/johanberntsson/PunyInform). But users who do select the Z-machine option should find that everything works well enough provided they keep the story modest in size. The first time one runs into hard limits on such a project, the issue can be postponed, by adding the following to the source: Use memory economy. (Economy cuts down the verbosity of some of the testing commands, but otherwise subtracts no performance.) Writing this into the source is the equivalent of a diver switching to an emergency oxygen tank: it gives us a generous safety margin, but also tells us that now is the time to wrap things up. Beyond that, genuine cuts would need to be made. As a general rule, the most memory-expensive ingredients of an Inform design are various-to-various relations between large kinds such as "thing" or, if there are many rooms, "room". Other than that, if a kind has been festooned with new properties and we have created dozens of items of that kind, then we can get a fairly large saving simply by doing without one of those properties; and so on. The ultimate memory-saving device, of course, is the one used by book publishers when there are too many pages to bind: to cut the design into two stories, Part I and Part II. ## What to do about a bug ^^{bugs in Inform} ^^{error messages: abject failures of Inform} ^^{problem messages: abject failures of Inform} ^^{inform7.com+web+} All software has bugs, and Inform is no exception. The most obvious bugs are the ones which Inform catches itself, when it confesses that it has halted in failure, or translated the source text into a program which cannot be compiled further. But sometimes it will also happen that Inform will issue a misleading Problem message, or appear to work normally but to produce a story which does not do what it should have done. It is very helpful for users to report faults, so that the program can be improved for everyone else. To report a fault, please first check with the Inform home page to make sure that the version of Inform you have used to detect the fault is the latest version available. You can find always find the latest versions at the [Inform 7 downloads page](http://inform7.com/downloads/). If the bug is still present in the latest version, please report the bug using Inform's bug tracking database. Links for this can be found from the [Inform source code page](https://github.com/ganelson/inform). It may be that someone else has already identified the bug and even that a workaround for users is suggested. If not, please make an account at the bug tracking system and submit the requested information to help Inform's maintainers track and fix the fault. ## Does Inform really understand English? ^^{English: really understanding} ^^{natural language, really understanding} No. No computer does, not even the AI voice assistants on modern phones, or large language models like ChatGPT. A true understanding of language means a true understanding of emotional life and culture too, and perhaps even of what it means to be alive. Some philosophers think it may be impossible for a computer to achieve that. But certainly plenty of modern software services seem able to _fake_ an understanding of language fairly well. Many queries seem to be handled very well, but others bizarrely, and often with users unable to see why one thing should be easy and another difficult. It's an approximate business, where users have no guarantee that what worked today will work tomorrow. Inform takes a different approach. It is a programming language, meaning that it gives a way for authors to express precisely what a computer should do. Authors may have trouble remembering the right way to do something, but once they do remember, they can rely on that working. Inform aims to be "legible", in the sense that a casual read-through of some source text usually gives a fairly good idea of what it does. `The gold chain is in the window-seat` is not hard to follow, for example. But Inform does not aim to accept everything a human might write. For instance, Inform understands something which is carried by the player but not (at present, anyway) something which the player carries even though both are perfectly good English. So it is not always safe to assume that Inform will understand any reasonable instruction it is given: when in doubt, we must go back to the manual. More philosophically, just because Inform recognises and acts on a sentence, does it really understand what we meant? It will turn out that Inform is both good and bad at this. For instance, from Mr Darcy wears a top hat. Inform will correctly deduce that Darcy is a person, because inanimate objects do not ordinarily wear clothes, and that the top hat is clothing. But it will not automatically know that Darcy is a man rather than a woman because it does not know the social convention implied by "Mr". Moreover, if instead we had written Mr Darcy carries a top hat. then Inform would not guess that the top hat is clothing. This is because it does not have the vast vocabulary and experience of a human reader: it is probably discovering the word "hat" for the first time. Finally, it is best to avoid ambiguities rather than rely on Inform to know which meaning is patently absurd. For instance, in > **Heatwave bone breaks clog hospital** (a headline once printed by the *Oxford Mail* newspaper) a human reader quickly realises that there is no clog hospital being broken by a heatwave bone. But if Inform had been taught the verbs *to break* and *to clog* then that is exactly the conclusion it would have drawn. Or an example which genuinely arose in beta-testing: The life support unit fits the egg. in which Inform construed the verb as `support` and not `fits`, and then created items called "the life" and "unit fits the egg". That disclaimer completes the groundwork, and we are ready to begin on simulating a world to explore. # Things ## Descriptions ^^{initial state of the world} ^^{starting conditions} ^^{assertions} ^^{punctuation: quotation marks: defining texts} ^^{|": defining texts} ^^{rooms+kind+: creating} ^^{defining: rooms} ^^{things+kind+: creating} ^^{defining: things}^^^{rooms+kind+ <-- places <-- locations} ^^^{things+kind+ <-- objects} ^^{player: initial location} ^^{initial location of player} At its simplest, the interactive fiction will be simulating a physical world to explore. The forerunner of today's IF is generally agreed to be a computer simulation by ^{@Will Crowther} of the exploration of a cave system in the Mammoth and Flint Ridge chain of caves in Kentucky, a part of which might be described in Inform thus: {*}"Cave Entrance" The Cobble Crawl is a room. "You are crawling over cobbles in a low passage. There is a dim light at the east end of the passage." A wicker cage is here. "There is a small wicker cage discarded nearby." The Debris Room is west of the Crawl. "You are in a debris room filled with stuff washed in from the surface. A low wide passage with cobbles becomes plugged with mud and debris here, but an awkward canyon leads upward and west. A note on the wall says, 'Magic word XYZZY'." The black rod is here. "A three foot black rod with a rusty star on one end lies nearby." Above the Debris Room is the Sloping E/W Canyon. West of the Canyon is the Orange River Chamber. Here we sketch in four of Crowther's locations, and two objects: just enough to be able to walk around the caves and pick up the rod and the cage. The text in quotation marks will appear verbatim as paragraphs shown to the player as the caves are explored. The first paragraph, as we have seen, is the title of the work. The other quotations describe the places and objects introduced. If we play this story, we find that we can type ``TAKE CAGE`` or ``TAKE WICKER CAGE``, for instance, but not ``TAKE SMALL CAGE``. Inform saw that we called this "a wicker cage" when it first appeared in the source text, and assumed that the player would call it that, too. (Whereas it didn't look inside the descriptive text to allow for ``TAKE SMALL CAGE`` or ``TAKE DISCARDED CAGE`` or ``TAKE NEARBY CAGE``.) A small limitation here is that probably only the first 9 letters of each word are read from the player's command. This is plenty for handling the wicker cage and the black rod, but it might be embarrassing at a meeting of the Justice League to find that ``KISS SUPERHERO`` and ``KISS SUPERHEROINE`` read as if they are the same command. So we have already found that Inform has made some assumptions about what we want, and imposed some limitations on how much computational effort to go to when the work of IF is finally played. If Inform guesses what we need wrongly, we need to know more advanced features of the language in order to overcome these problems. (We shall see how to change the way the player's commands are read in the chapter on [Understanding].) This is often how Inform works: make the standard way of doing things as simple as possible to describe, but allow almost any behaviour to be altered by more elaborate source text. As an example of that, the player begins in the Cobble Crawl because it was the first room created in the source text, but we could instead have written text like: The player is in the Cobble Crawl. to override that. This can make the source text easier to follow if the rooms are sometimes being created in a less obvious way. For example, if we write: The silver bars are in the Y2 Rock Room. The Cobble Crawl is a room. South of the Crawl is Y2. then the first room to be created will actually be the Y2 Rock Room, so that's where the player will be starting unless we say otherwise. ## Rooms and the map {kind_room} {MAP} {PM_SameKindEquated} {PM_DescriptionsEquated} ^^{rooms+kind+: connections between rooms} ^^{connections between rooms <-- exits <-- map: designing <-- going+action+: between rooms} ^^{index map <-- map: in Index panel} ^^{directions+kind+ <-- compass directions} ^^{|called: in creating rooms} ^^{|from: inside / outside from} ^^{|inside from} ^^{|outside from} ^^{use options: catalogue: |unabbreviated object names} ^^{unabbreviated object names+useopt+} ^^{abbreviations: object names} Rooms are joined together at their edges by "map connections", most of which are pathways in one of the eight cardinal compass directions: north, northeast (written without a hyphen), east, southeast, south, southwest, west, northwest. We also have up and down, suitable for staircases or ladders. In real life, people are seldom conscious of their compass bearing when walking around buildings, but it makes a concise and unconfusing way for the player to say where to go next, so is generally accepted as a convention of the genre. Two more directions are provided by Inform: "inside" and "outside". These are best used when one location is, say, a meadow and the other is a woodcutter's hut in the middle of it; we might then say Inside from the Meadow is the woodcutter's hut. The `from` is important, as it clarifies that we intend to link two different locations, not to create an item – the hut – in a single location – the meadow. A problem which sometimes arises when laying out maps is that Inform allows short forms of room names to be used as abbreviations. This is usually a good idea, but has unfortunate results if we write: The Airport Road is west of the Fish Packing Plant. The Airport is west of the Airport Road. ...because `Airport` is taken as a reference to `Airport Road`, so Inform makes only two locations, one of which supernaturally leads to itself. We can avoid this by writing: The Airport Road is west of the Fish Packing Plant. A room called the Airport is west of the Airport Road. Using `called` is often a good way to specify something whose name might give rise to confusion otherwise. It always makes something new, and it is also neatly concise, because we can establish something's kind and name in the same sentence. As another example, suppose we want to create a room called `South of the Hut`, to south of the Hut. We can't do so like this: South of the Hut is a room. South of the Hut is south of the Hut. ...because Inform will read that first sentence as placing a (nameless) room to the south of a room called `Hut`. Once again `called` can save the day: South of the Hut is a room called South of the Hut. It is best to use `called` in the simplest way possible, and in particular, best not to use `called` twice in the same sentence. Consider: The kitchen cabinet contains a container called a mixing bowl and a portable supporter called a platter. It is unlikely that anyone would want to name something "a mixing bowl and a portable supporter called a platter", but not impossible, and Inform tends not to be a good judge of what is likely. (If we really want to get rid of this issue once and for all, starting the source text with the use option `Use unabbreviated object names.` will do it, but the effect is drastic. This instructs Inform not to recognise names other than in full. For example: West of the Kitchen is the Roaring Range. South of the Range is the Pantry. is ordinarily read by Inform as constructing three rooms (Kitchen, Roaring Range, Pantry); but with this use option set, it makes four (Kitchen, Roaring Range, Range, Pantry), in two disconnected pieces of map. Handle with care.) ## One-way connections ^^{rooms+kind+: one-way connections between rooms} ^^{connections between rooms: one-way} ^^{one-way connections} ^^{connections between rooms: inconsistent directions} ^^{connections between rooms: to nowhere} ^^{|nowhere: in removing room connections} Connections are ordinarily two-way, but do not have to be. One of the map connections in the Mammoth Cave simulation was made by the sentence: The Debris Room is west of the Crawl. Besides reading this sentence at face value, Inform also deduced that the Crawl was probably meant to be east of the Debris Room: in other words, that the path between them is a two-way one. When Inform makes guesses like this, it treats them as being less certain than anything explicitly stated in the source. Inform will quietly overturn its assumption if information comes to hand which shows that it was wrong. That might happen in this case if another sentence read: The Hidden Alcove is east of the Debris Room. These two sentences are not contradictory: Inform allows them both, simply accepting that the world is more complicated than it first assumed. There are relatively few situations where Inform has to make educated guesses, but when it does, it tries always to follow Occam's Razor by constructing the simplest model world consistent with the information in the source text. We can even explicitly make a route which turns around as it leads between two rooms: West of the Garden is south of the Meadow. If we want to establish a route which cannot be retraced at all, we can specify that a particular direction leads nowhere: East of the Debris Room is nowhere. Finally, note that Inform's assumptions about two-way directions are only applied to simple sentences. When the source text seems to be saying something complicated, Inform takes it as a precise description of what's wanted. So, for example, in: The Attic is above the Parlour. [1] The Parlour is a room. The Attic is a dark room above the Parlour. [2] Inform makes guesses about the first sentence, and makes a two-way connection; but it accepts the second sentence more precisely, with just a one-way connection. ## Regions and the index map {kind_region} {REGIONS} {PM_ExistingRegion} {PM_RegionInTwoRegions} {PM_RegionRelation} ^^{kinds: catalogue: region} ^^{regions+kind+ <-- kinds: catalogue: region} ^^{rooms+kind+: grouping into regions} ^^{index map} ^^{Map page of Index panel+ui+} ^^{user interface: Index panel: Map page} ^^{Index panel+ui+: Map page} ^^{map region of (room)+prop+} ^^{map region of (room)+propcat+} Rooms represent individual places to which one can go, but we tend to think of the world around us in larger pieces: we think of a house and a garden, rather than each of the single rooms of the house and all corners of its garden. To Inform a collection of rooms is called a _region_, and we can create one like so: The Arboretum is east of the Botanical Gardens. Northwest of the Gardens is the Tropical Greenhouse. The Public Area is a region. The Arboretum and Gardens are in the Public Area. The real usefulness of creating regions like `Public Area` will only appear later, when we begin defining rules of play which apply in some areas but not others, but in the mean time we can see the effect by turning to the World tab of the Index. In the World Index, Inform draws a map – or at least a stylised attempt at a diagram of the rooms and their connections: this will not always correspond to how we imagine things, but with any luck it should mostly be right. Rooms are represented by coloured squares, and the colour-coding is done by region. In the above example, the two Public Area rooms are coloured green (as it happens); the Greenhouse, since it belongs to no region, is a neutral grey. Regions can be put inside each other: The University Parks is a region. The Public Area is in the University Parks. but they are not allowed to overlap other than by one being entirely inside the other. The effect of writing `The Arboretum is in the Public Area.` is that the Arboretum has a _property_ called its `map region` set to the `Public Area`. (More on properties later.) Every room has a `map region` property, but this is just set to `nowhere` unless the source text explicitly says otherwise: that is, by default rooms are not in any region at all. Where a room is in multiple regions, as in the case of the `Arboretum` being in both the `Public Area` and the `University Parks`, its `map region` is the innermost region it belongs to: so, in this case, `map region of the Arboretum` evaluates during play as `Public Area`. But the tests `if the Arboretum is in the Public Area` and `if the Arboretum is in the University Parks` are both true. ### See Also - [Improving the index map] for ways to adjust the way the index map is drawn or exported for publication. - [A word about in] for a fuller explanation of how Inform decides whether something is or isn't `in` something else, which has some special cases to handle regions. ## Kinds {KINDS} {PM_BothRoomAndSupporter} {PM_CantContainAndSupport} {PM_MiseEnAbyme} {PM_KindsIncompatible} ^^{kinds} ^^{kinds: catalogue: room} ^^{rooms+kind+ <-- kinds: catalogue: room} ^^{kinds: catalogue: supporter} ^^{supporters+kind+ <-- kinds: catalogue: supporter} ^^{kinds: catalogue: container} ^^{containers+kind+ <-- kinds: catalogue: container} ^^{kinds: catalogue: thing} ^^{things+kind+ <-- kinds: catalogue: thing} ^^{kinds: catalogue: direction} ^^{directions+kind+} ^^{|called: in creating things} The following description runs to only 33 words, but makes a surprisingly intricate design. It not only places things within rooms, but also places them very specifically with respect to each other: "Midsummer Day" East of the Garden is the Gazebo. Above is the Treehouse. A billiards table is in the Gazebo. On it is a trophy cup. A starting pistol is in the cup. Inform identifies eight _objects_ mentioned in this short scenario, which it groups together into different categories called _kinds_. Kinds affect the general behaviour of things. For instance, the pistol and the cup can be picked up but not walked inside, whereas the Gazebo and the Treehouse are the reverse. (This is obvious to someone who knows what these words mean, less obvious to a computer which does not, but the text contains sufficient clues.) Inform sorts out the situation above like so: Objects | Their kinds ----------------------------- | ----------- Garden, Gazebo, Treehouse | room billiards table | supporter cup | container starting pistol | thing east, up (implied by `above`) | direction Inform makes guesses at these kinds using some basic assumptions about how the world works. For example, it knows that if one thing is in another, then the second thing is either a room or a container, and if one thing is on another, then the second thing is a supporter. These guesses are usually right, but not always, so it can be necessary to say more. For example: In the Treehouse is a cardboard box. results in the cardboard box being made only a `thing`: because nothing has been put inside it, there is no reason for Inform – which does not know what a cardboard box looks like – to guess that it is a `container`. So we need to add: The box is a container. It is rather clumsy to have to write two sentences like this, so we would normally write this instead: In the Treehouse is a container called the cardboard box. ## Either/or properties ^^{properties} ^^{properties: either/or properties} ^^{either/or properties} ^^{immobile things: |fixed in place} ^^{things+kind+: immobile: |fixed in place} ^^{containers+kind+: open / closed} ^^{containers+kind+: transparent / opaque} ^^{containers+kind+: enterable} ^^{open / closed (container/door)+prop+} ^^{closed / open (container/door)+prop+} ^^{open (container/door)+propcat+} ^^{closed (container/door)+propcat+} ^^{fixed in place / portable (thing)+prop+} ^^{portable / fixed in place (thing)+prop+} ^^{fixed in place (thing)+propcat+} ^^{portable (thing)+propcat+} ^^{openable / unopenable (container)+prop+} ^^{unopenable / openable (container)+prop+} ^^{openable (container)+propcat+} ^^{unopenable (container)+propcat+} ^^{enterable (container)+prop+} ^^{enterable (container)+propcat+} ^^{transparent / opaque (container)+prop+} ^^{opaque / transparent (container)+prop+} ^^{transparent (container)+propcat+} ^^{opaque (container)+propcat+} Some containers, like bottles, can be opened: others, like buckets, cannot. If they can be opened, then sometimes they will be open, and sometimes closed. These are examples of properties, which can change during play. The following source sets some properties: The cardboard box is a closed container. The glass bottle is a transparent open container. The box is fixed in place and openable. There are only four different properties referred to here. `Closed` means not `open`, and vice versa, so these two adjectives both refer to the same property. (As might be expected, when a container is open, one can see inside and place things within, or take them out.) The glass bottle and the box being containers is a matter of their kinds, which is something fundamental and immutable, so `container` does not count as a property. A `transparent` container is one which we can see inside even when it is closed, and the opposite is an `opaque` container. The property of being `fixed in place` ensures that the player cannot pick the item up and walk away with it: this is useful for such things as oak trees or heavy furniture. The opposite condition is to be `portable`. A container which is `openable` can be opened or closed by the player; as might be expected, the opposite is `unopenable`. With a really large cardboard box, we might imagine that the player could get inside: such a container should be declared `enterable`. ## Properties depend on kind {PM_PropertyNotPermitted} ^^{properties} ^^{properties: dependence on kind} ^^{fixed in place / portable (thing)+prop+} ^^{portable / fixed in place (thing)+prop+} ^^{fixed in place (thing)+propcat+} ^^{portable (thing)+propcat+} ^^{immobile things: supporters made automatically immobile} ^^{things+kind+: immobile: because they're supporters} ^^{supporters+kind+: default immobility} Properties depend very much on kind. It makes no sense to ask whether a room is transparent or opaque, for instance, so Inform will not allow this either to be specified or queried. Another way that kind influences properties can be seen from an earlier example: The Gazebo is a room. A billiards table is in the Gazebo. On it is a trophy cup. A starting pistol is in the cup. The cup, the pistol and the table are all allowed to have the `fixed in place` property, but in fact only the table actually has it: the cup and the pistol are created as `portable` instead. This is because Inform knows that most things are `portable`, but that supporters – such as the table – are usually `fixed in place`. If this assumption is wrong, we need only add the line: The table is portable. ## Scenery ^^{scenery (thing)+prop+} ^^{scenery (thing)+propcat+} ^^{immobile things: |scenery} ^^{things+kind+: immobile: |scenery} ^^{hiding things: from room descriptions by making them scenery <-- concealment+rel+: in a room} ^^{descriptions (displayed): hiding things from room descriptions} ^^{rooms+kind+: printing the room contents: hiding things} ^^{supporters+kind+: mentioned because of supported things} As we have just seen, making something `fixed in place` will prevent it from being picked up or moved. But it remains substantial enough to be described in its own paragraph of text when the player visits its location. This can be unfortunate if it has also been described already in the body of the main description for that location. For instance, if we wrote: The Orchard is a room. "Within this quadrille of pear trees, a single gnarled old oak remains as a memory of centuries past." The gnarled old oak tree is fixed in place in the Orchard. This would end up describing the oak twice, once in the paragraph about the Orchard, then again in a list of things within it: ``` transcript Orchard Within this quadrille of pear trees, a single gnarled old oak remains as a memory of centuries past. You can see a gnarled old oak tree here. ``` We avoid this by making it `scenery` instead of `fixed in place`: The gnarled old oak tree is scenery in the Orchard. Any `thing` can be `scenery`, and this does not bar it from playing a part in the story: it simply means that it will be immobile and that it will not be described independently of its room. Being immobile, scenery should not be used for `portable` objects that are meant to be left out of the room description. If a `supporter` is `scenery`, it may still be mentioned in the room description after all, but only as part of a paragraph about other items, such as ``` transcript On the teak table are a candlestick and a copy of the Financial Times. ``` If the player takes the candlestick and the Times, the teak table will disappear from mention. (`Scenery containers` do not behave in this way: their contents are assumed to be less immediately visible, and will be mentioned only if the player looks inside them.) ## Backdrops {kind_backdrop} {PM_EverywhereNonBackdrop} {PM_CantChangeEverywhere} {PM_EverywhereMisapplied} ^^{kinds: catalogue: backdrop} ^^{backdrops+kind+ <-- kinds: catalogue: backdrop} ^^{scenery (thing)+prop+: backdrops made automatically scenery} ^^{rooms+kind+: things in more than one room} ^^{things+kind+: in more than one room} ^^{regions+kind+: backdrops in regions} ^^{(everywhere), placing backdrops+sourcepart+} ^^{|nowhere: placing backdrops} It is a cardinal rule that nothing can be in more than one place at the same time, but rules were made to be broken, and an exception is allowed for a special kind of thing called a `backdrop`. For instance: {*}"Streaming" The Upper Cave is above the Rock Pool. The stream is a backdrop. It is in the Upper Cave and the Rock Pool. Backdrops are ordinarily in the background: if the sky needed to be referred to in the course of play, it might be represented by a backdrop, for instance. Here we have a stream of water running through two rooms, though it might be any number. Backdrops are always fixed in place. Backdrops can be put in regions as well as rooms, and if so, then they are present at every room in the given region (or regions), as well as any specific rooms they may also be put into. For instance: The Outdoors Area is a region. The Moon is a backdrop. The Moon is in the Outdoors Area. The Moon is in the Skylight Room. The special place `everywhere` can be given as the location of a backdrop to make it omnipresent: The sky is a backdrop. The sky is everywhere. Inform assumes that backdrops are also scenery unless told otherwise, so this will not result in messages like ``You can also see the sky here.`` being included in room descriptions. In the case of the stream above, we could artfully mention it in passing in the room descriptions of the Upper Cave and the Rock Pool. ### See Also - [Moving backdrops] for ways to place backdrops in dynamically changing selections of rooms. ## Properties holding text ^^{properties: value properties} ^^{value properties} ^^{properties: holding text} ^^{description of (room)+prop+} ^^{description of (room)+propcat+} ^^{text: in properties} The properties we have seen so far have all been either/or: either `open` or `closed`, either `transparent` or `opaque`, either `fixed in place` or `portable`, either `openable` or not. However, some properties can have a much wider range of possibilities. For instance, the `description` of a room is the text revealed when the player first enters it, or types ``LOOK``. This needs to be textual: Inform would complain if, for instance, we tried to set the description of something to the number 42. We have already seen a concise way to set the description of a room: The Painted Room is north of the Undertomb. "This is the Painted Room, where strange wall drawings leap out of the dark at the gleam of your candle: men with long wings and great eyes, serene and morose." This does the same thing as: The Painted Room is north of the Undertomb. The description of the Painted Room is "This is the Painted Room, where strange wall drawings leap out of the dark at the gleam of your candle: men with long wings and great eyes, serene and morose." Or even: The Painted Room is north of the Undertomb. The description is "This is the Painted Room, where strange wall drawings leap out of the dark at the gleam of your candle: men with long wings and great eyes, serene and morose." ## Two descriptions of things {PM_TwoAppearances} {PM_TextWithoutSubject} ^^{description of (room)+prop+} ^^{description of (room)+propcat+} ^^{description of (thing)+prop+} ^^{description of (thing)+propcat+} ^^{initial appearance of (thing)+prop+} ^^{initial appearance of (thing)+propcat+} ^^{handled (thing)+prop+} ^^{handled (thing)+propcat+} ^^{descriptions (displayed): initial appearance of thing}^^^{descriptions (displayed) <-- appearance} ^^{Inform 6 equivalent: |initial} The player's first sight of something is the text used as its "initial appearance": The plain ring is here. "Cast aside, as if worthless, is a plain brass ring." This text appears as a separate paragraph in the text describing the Painted Room. It will continue to be used until the first time the player picks the ring up — if this ever happens — so it normally describes things in their original, undisturbed context. Inform uses an either/or property called `handled` to keep track of this: something is `handled` if it has at some point been carried or worn by the player. Thus when a piece of text stands alone as a sentence in its own right, then this is either the `description` of the most recently discussed `room`, or the `initial appearance` of the most recently discussed `thing`. Either way, it is used verbatim as a paragraph in the text shown to the player visiting the room in question. But a `thing` also has an ordinary `description`, which is used to give a close-up look at it. This text is ordinarily only revealed to the player when a command like ``EXAMINE RING`` is keyed in: The description of the plain ring is "No better than the loops of metal the old women use for fastening curtains." ### See Also - [Creating a scene] for the description of a scene, which is set in the same way. ## Doors {kind_door} {PM_BothWaysDoor} {PM_DoorUnconnected} {PM_DoorOverconnected} {PM_DoorToNonRoom} {PM_DoorInThirdRoom} {PM_RoomMissingDoor} {PM_BadMapCell} ^^{kinds: catalogue: door} ^^{doors+kind+ <-- kinds: catalogue: door} ^^{connections between rooms: doors} ^^{through+relverb+} The _map_ of an interactive fiction is the layout of rooms and the entrances and exits which connect them. So far, these map connections have always run from one room to another, like so: The Painted Room is north of the Undertomb. However, we can also interpose doors between rooms, like so: The heavy iron grating is east of the Orchard and west of the Undertomb. The grating is a door. The second sentence is needed since otherwise Inform will take `heavy iron grating` to be the name of a third room, whereas what we want is for the grating to be something physically present in both the Orchard and in the Undertomb, and acting as a conduit between them. To this end it needs to be a `door`, a kind we have not so far seen. In the absence of any other instruction, a newly created door will be `fixed in place`, `closed` and `openable`. The grating really does come in between the two rooms: the grating is what lies immediately east of the Orchard, not the Undertomb room. So if we wrote the following: The Undertomb is east of the Orchard. The heavy iron grating is east of the Orchard and west of the Undertomb. The grating is a door. then Inform would say that this is a contradiction: we said the Undertomb was east of the Orchard, but then we said that the grating was east of the Orchard. Inform's `door` kind can be used for all manner of conduits, so the word door need not be taken literally. In Ursula K. Le Guin's beguiling novel _The Tombs of Atuan_ (1970), from which the above rooms are stolen, it is not a grating which interposes, but: ^^{@Ursula K. Le Guin} The red rock stair is east of the Orchard and above the Undertomb. The stair is an open door. The stair is not openable. In real life, most doors are two-sided, and can be used from either of the rooms which they join, but this is not always convenient for interactive fiction. Here is a one-sided door: The blue door is a door. It is south of Notting Hill. Through it is the Flat Landing. (Note the use of `it` here as an optional abbreviation.) This will make a door visible only on the Notting Hill side; no map connection will be made in the reverse direction, unless we ask for one. So much for creating and describing individual doors. Once we need to write about doors in general, we are likely to want a way to find out where a given door sits in the map. The following phrases reveal this: > phrase: {ph_frontside} front side of (object) ... room > > This phrase produces the first of the one or two rooms containing a door – first in the order given in the source text. Example: if > > The red rock stair is east of the Orchard and above the Undertomb. > > then "front side of the red rock stair" produces the Orchard. For a one-sided door, this produces the only room containing the door. > phrase: {ph_backside} back side of (object) ... room > > This phrase produces the last of the one or two rooms containing a door – last in the order given in the source text. Example: if > > The red rock stair is east of the Orchard and above the Undertomb. > > then "back side of the red rock stair" produces the Undertomb. A one-sided door has no "back side." More often, we are dealing with a door and want to know what it leads to, but that depends where we're standing: > phrase: {ph_othersideof} other side of (door) from (room) ... object > > This phrase produces the room on the other side of the door, as seen from the given vantage point, which needs to be one of its sides. Example: if > > The red rock stair is east of the Orchard and above the Undertomb. > > then "other side of the red rock stair from the Undertomb" produces the Orchard, and vice versa. > phrase: {ph_directionofdoor} direction of (door) from (room) ... object > > This phrase produces the direction in which the door leads, as seen from the given vantage point, which needs to be one of its sides. Example: if > > The red rock stair is east of the Orchard and above the Undertomb. > > then "direction of the red rock stair from the Undertomb" produces up. ### See Also - [Adjacent rooms and routes through the map] for more phrases which can look at the current map layout. ## Locks and keys ^^{doors+kind+: locked} ^^{containers+kind+: locked} ^^{open / closed (container/door)+prop+} ^^{closed / open (container/door)+prop+} ^^{open (container/door)+propcat+} ^^{closed (container/door)+propcat+} ^^{locked / unlocked (container/door)+prop+} ^^{unlocked / locked (container/door)+prop+} ^^{locked (container/door)+propcat+} ^^{unlocked (container/door)+propcat+} ^^{lockable (container/door)+prop+} ^^{lockable (container/door)+propcat+} ^^{matching key of (container/door)+prop+} ^^{matching key of (container/door)+propcat+} ^^{unlocks+relverb+} ^^{Inform 6 equivalent: |with_key} It seems unwise for a door in Notting Hill to be unlocked, so: The blue door is lockable and locked. The matching key of the blue door is the brass Yale key. Since the second sentence here is a little clumsy, we can equivalently say The brass Yale key unlocks the blue door. Yet a third way to say this is: The blue door has matching key the brass Yale key. This introduces three new properties: a door can be `locked` or `unlocked`; `lockable` or not; and it can have a `matching key`, which must be another `thing`. The same thing can be the matching key of many different locks: and note that a door can be locked and even lockable without having a matching key at all, in which case the player trying to open it will be permanently out of luck. Doors are ordinarily unlocked, not lockable, and without a matching key. Containers can also have locks, in exactly the same way, and are allowed to have the same properties. On the other hand supporters never have locks: it makes no sense to be able to lock a tabletop, for instance, and Inform will not allow any discussion of the `matching key` of a `supporter`, or of a `supporter` being `locked` or `unlocked`. ## Devices and descriptions {kind_device} ^^{kinds: catalogue: device} ^^{devices+kind+} ^^{switched on / off (device)+prop+} ^^{switched on (device)+propcat+} ^^{switched off (device)+propcat+} ^^{Inform 6 equivalent: |switchable} ^^{turning devices on / off} ^^{descriptions (displayed): varying with properties} ^^{text substitutions <-- text: substitutions} A `device` is another of the standard kinds of thing, and should be used for anything which can be switched on or off: a light switch, say, or a slide projector. Devices are generally machines, clockwork or electrical. A device is always either `switched on` or `switched off`, but is switched off unless we specify otherwise. That makes three kinds of thing which will likely change their appearance according to which of their two possible states they are in: `doors` and `containers`, which can be `open` or `closed`; and `devices`, which can be `switched on` or `switched off`. We would like to produce text accordingly, and we can do this using Inform's ability to make (almost) any piece of text change with circumstances. For instance: The coffin is an openable container in the Undertomb. "[if open]The lid of a plank coffin yawns open.[otherwise]A plank coffin lies upon the dirt floor of the Tomb." We could use a similar trick to make the appearance of a device change `if switched on`. There will be much more about text substitutions, as instructions in square brackets like these are called, in later chapters. ### See Also - [Text with substitutions] for more on varying what is printed. ## Light and darkness ^^{light} ^^{darkness <-- light: lack of} ^^{lighted / dark (room)+prop+} ^^{dark / lighted (room)+prop+} ^^{lighted (room)+propcat+} ^^{dark (room)+propcat+} ^^{lit / unlit (thing)+prop+} ^^{unlit / lit (thing)+prop+} ^^{lit (thing)+propcat+} ^^{unlit (thing)+propcat+} ^^{containers+kind+: open / closed} ^^{containers+kind+: transparent / opaque} ^^{open / closed (container/door)+prop+} ^^{closed / open (container/door)+prop+} ^^{open (container/door)+propcat+} ^^{closed (container/door)+propcat+} ^^{transparent / opaque (container)+prop+} ^^{opaque / transparent (container)+prop+} ^^{transparent (container)+propcat+} ^^{opaque (container)+propcat+} Rooms can be `dark` or `lighted`, though they are lighted by default, and are lighted in all the examples we have seen so far. So a room must be explicitly declared `dark` for it to be such: The Sinister Cave is a dark room. "A profoundly disquieting rock formation, apparently sculptured by some demonic hand, this is not a cave in which to relax." When the player is in a `dark` room, they can still go in various directions, but they cannot see the room description or interact with any of the objects in the room, except those they are holding. This means that, unless we should change the Cave in some way during play, the text above (`"A profoundly..."`) will only be read if the player succeeds in bringing light into the Cave, perhaps by bringing along the following: The flaming torch is in the Sandy Passage. "Stuck loosely into the sand is a flaming torch." The flaming torch is lit. A thing with the property of being `lit` will enable the player to see inside dark rooms, and to carry out other actions requiring light, such as examining things. A `lit thing` in an `open container` will still light up a room; a `lit thing` in a `closed container` will not, unless the container has been given the `transparent` property. It is possible to adjust the way darkness behaves, and we will see more on this topic in the chapter on [Activities]. ### See Also - [Printing a refusal to act in the dark] for the first of several ways to control what is printed in the dark. ## Vehicles and pushable things {kind_vehicle} ^^{kinds: catalogue: vehicle} ^^{vehicles+kind+} ^^{containers+kind+: vehicle as kind of container} ^^{enterable (container)+prop+: vehicles made automatically enterable} ^^{pushing things} ^^{things+kind+: pushable between rooms} ^^{pushable between rooms (thing)+prop+} ^^{pushable between rooms (thing)+propcat+} ^^{animals+kind+: rideable} ^^{Rideable Vehicles+ext+} ^^{extensions: specific extensions: Rideable Vehicles} Next in the tour of standard kinds is the `vehicle`. This behaves like (indeed, is) an `enterable container`, except that it will not be `portable` unless this is specified. In the Garage is a vehicle called the red sports car. The player can enter the sports car and then move around riding inside it, by typing directions exactly as if on foot: and the story will print names of rooms with ``(in the red sports car)`` appended, lest this be forgotten. We have already seen that some things are portable, others fixed in place. In fact we can also make a third sort of thing: those which, although not portable, can be pushed from one room to another with commands like ``PUSH THE WHEELBARROW NORTH``. At a pinch, we might just be willing to allow: The red sports car is pushable between rooms. But of course this is a property which almost any `thing` can have, not just a `vehicle`. (Only "almost" because Inform will not allow a `door` to be `pushable between rooms`, in the interests of realism rather than surrealism.) If we need vehicles which the passenger sits on top of, like a tractor, the standard `vehicle` kind will not be ideal. The extension `Rideable Vehicles by Graham Nelson` can help with this, and also allows animals such as horses to be rideable. ### See Also - [Going by, going through, going with] for further ways to customise vehicle behaviour. ## Men, women and animals {kind_person} ^^{kinds: catalogue: person} ^^{person+kind+ <-- people <-- kinds: catalogue: person} ^^{kinds: catalogue: man} ^^{man+kind+ <-- men+kind+} ^^{kinds: catalogue: woman} ^^{woman+kind+} ^^{kinds: catalogue: animal} ^^{animals+kind+} ^^{pronouns} ^^{male / female / neuter (person)+prop+} ^^{female / male / neuter (person)+prop+} ^^{neuter / male / female (person)+prop+} ^^{male (person)+propcat+} ^^{female (person)+propcat+} ^^{neuter (person)+propcat+} Rounding out the standard kinds provided by Inform are four for living things: `person`, which is a kind of thing, and `man`, `woman` and `animal`, all kinds of person. For instance: In the Ballroom is a man called Mr Darcy. For the time being, men and women will be little more than waxworks: they will come to life only when we go beyond the present stage of creating an initial state of the world. People can be `male` or `female`: this is an either/or property for the `person` kind, and it affects play at run-time a little, because the player can use ``HIM`` and ``HER`` to refer to male or female people encountered. Men and women are always male and female respectively, and for animals we can choose either way, for example making a stallion male or a nanny goat female. If our animal is instead something like a beetle or an earthworm, where gender doesn't seem to matter or even to exist, we can use the further property `neuter`: The spider is a neuter animal in the Bathroom. The Standard Rules don't make people behave differently according to their genders, and the main difference comes down to language: whether we want the animal to be called "HER", or "IT". Because of the existence of `neuter`, we sometimes need to be cautious about the use of the adjective `male`: since Inform, partly for historical reasons, uses an either/or property for masculinity, neuter animals are also `male`. ## Articles and proper names ^^{articles} ^^{definite articles: when creating things} ^^{indefinite articles: when creating things} ^^{mass nouns} ^^{|some: article} ^^{|a / an / the --> a: in defining things} ^^{|an / a / the --> an: in defining things} ^^{|the / a / an --> the: in defining things} ^^{singular-named / plural-named (thing)+prop+} ^^{plural-named / singular-named (thing)+prop+} ^^{singular-named (thing)+propcat+} ^^{plural-named (thing)+propcat+} ^^{ambiguously plural (thing)+propcat+} ^^{proper-named / improper-named (thing)+prop+} ^^{improper-named / proper-named (thing)+prop+} ^^{improper-named (thing)+propcat+} ^^{proper-named (thing)+propcat+} ^^{indefinite article of (object)+prop+} ^^{indefinite article of (object)+propcat+} Suppose we have said that: In the Ballroom is a man called Mr Darcy. When the Ballroom is visited, the man is listed in the description of the room as ``Mr Darcy``, not as ``a Mr Darcy``. This happened not because Inform recognised that Darcy is a proper name, or even because men tend to have proper names, but because Inform noticed that we did not use `a`, `an`, `the` or `some` in the sentence which created him. The following shows most of the options: The Belfry is a room. A bat is in the Belfry. The bell is in the Belfry. Some woodworm are in the Belfry. A man called William Snelson is in the Belfry. A woman called the sexton's wife is in the Belfry. A man called a bellringer is in the Belfry. In the Belfry is a man called the vicar. The indefinite article of the vicar is "your local". In the resulting story, we read: ``` transcript You can see a bat, a bell, some woodworm, William Snelson, the sexton's wife, a bellringer and your local vicar here. ``` The subtlest rule here is in the handling of `the`. We wrote `The bell is in the Belfry`, but this did not result in the bell always being called ``the bell``: in fact, writing `A bell is in the Belfry` would have had the same effect. On the other hand, `A woman called the sexton's wife is in the Belfry.` led to the wife always being known as ``the sexton's wife``, not ``a sexton's wife``, because Inform thinks the choice of article after `called` shows more of our intention than it would elsewhere. These rules will never be perfect in all situations, so we are also allowed to specify indefinite articles by hand, as the vicar's case shows. `Some` is worth a closer look, because English uses it in several different ways. By introducing the woodworm with `some`, above, we established that it was plural. We might imagine that there are many worms, even though they are represented by a single thing in Inform. We can expect to see text in the story such as ``The woodworm are fixed in place.``, rather than ``...is fixed in place.`` But suppose we wanted something which there is an amount of, but which is not made up of individual items – a so-called mass noun like "water", or "bread". Now we can write: The water is here. The indefinite article is "some". and this time Inform does not treat the `some water` thing as a plural, so the story might produce sentences like ``The water is hardly portable.`` rather than ``The water are hardly portable.`` Finally, we can override these settings, if they still come out not as we intend, by explicitly changing the either/or properties `singular-named` (vs `plural-named`) and `proper-named` (vs `improper-named`). On rare occasions, the same item might be referred to in either a singular or plural way: for example, a box of matches, or a book of lottery tickets. In their full names, they are singular nouns ("box of matches" is a singular), but abbreviated descriptions of them (like "matches") are plural nouns. A story in play generally writes these names in full, so this ambiguity doesn't matter. But players might abbreviate them. For example: On the silver salver is a bouquet of flowers. Now, there is only one bouquet of flowers here, so this is a `singular-named` item. If the player types ``TAKE BOUQUET``, the story will reply ``Taken.``, and the player can then ``EXAMINE IT``, because the pronoun ``IT`` is understood as meaning the last singularly-named item referred to which wasn't a person. But what if the player instead types ``TAKE FLOWERS``, and then on the next command, ``EXAMINE THEM``? Now ``THEM`` will not be understood. This small lapse in command parsing is what the property `ambiguously plural` is intended to avoid: On the silver salver is a bouquet of flowers. The bouquet of flowers is ambiguously plural. Now when the player's commands refer to the bouquet of flowers, the words ``IT`` and ``THEM`` are both set to it. The effect is that ``TAKE BOUQUET. EXAMINE IT`` and ``TAKE FLOWERS. EXAMINE THEM`` will both work. ## Carrying capacity ^^{containers+kind+: carrying capacity} ^^{supporters+kind+: carrying capacity} ^^{person+kind+: carrying capacity} ^^{player: carrying capacity} ^^{carrying capacity of (container/supporter/person)+prop+} ^^{carrying capacity of (container/supporter/person)+propcat+} The containers and supporters created so far have been boundlessly capacious: or rather, though we seldom notice the difference, have had a maximum `carrying capacity` of 100, meaning that they can contain or support at most 100 items directly. This is clearly unrealistic for a small purse or a modest mantelpiece. We can impose upper limits with sentences like so: The carrying capacity of the jewelled purse is 2. The bijou mantelpiece has carrying capacity 3. Attempts by the player to overfill, or overload, will now be rebuffed with a message such as ``There is no room on the mantelpiece.`` The player is not a `container` or a `supporter`, but is a `person`, and so nevertheless does have a `carrying capacity`: this is interpreted to mean the maximum number of items which can be carried at once. The carrying capacity of the player is 4. These restrictions constrain the actions of the fictional characters in the story. But they do not constrain us, as the omnipotent creator of their world. So nothing prevents this: The carrying capacity of the jewelled purse is 2. The diamond, the ruby and the sapphire are in the purse. During play, all three items will be able to be extracted from the purse with commands like ``TAKE DIAMOND``, but only two can then be put back. (We might occasionally want an initially over-filled container like this: perhaps to create a sack stuffed almost to bursting point.) ## Possessions and clothing ^^{possessions} ^^{carrying+rel+} ^^{carrying+relcat+} ^^{wearing+rel+} ^^{wearing+relcat+}^^^{wearing+rel+ <-- clothing: wearing relation} ^^{wearable (thing)+prop+ <-- clothing} ^^{wearable (thing)+propcat+} ^^{Inform 6 equivalent: |clothing} ^^{worn (thing)+adj+} ^^{carried (thing)+adj+} ^^{held (thing)+adj+} We have seen how to place objects in rooms, and in containers or on supporters. But what about people? Perhaps it could be said that they "contain" the fillings in their teeth, or "support" a top hat, but this is not very natural. Inform therefore never speaks of things being `in` or `on` people. Instead, they have two sorts of possessions: the things they `carry`, and the things they `wear`. (Body parts, such as arms and legs, are different again: see [Parts of things] below for a clue to how to do these.) Thus: Mr Darcy wears a top hat. Mr Darcy carries a silver sword. In fact, Inform deduces from this not only who owns the hat and the sword, but also that Darcy has the kind `person`, because only people can wear or carry. As all the assertion verbs do, "to wear" and "to carry" have participles which Inform knows about. So we could equally well write: The scarlet coat is worn by Mr Wickham. The duelling pistol is carried by Mr Wickham. If we do not specify who does the wearing, or carrying, then this is assumed to be the player. Thus: A brass lantern and a rusty iron key are carried. The mosquito-repellent hat is worn. It would make no sense to `wear` the key, for instance, so Inform needs to distinguish between what is clothing and what is not. It does this with an either/or property called `wearable`: if something has this property then the player will be allowed to wear it, provided it can first be picked up. Anything which is worn by somebody at the start of play is assumed to be `wearable` (unless we say otherwise). But if nobody is initially wearing the item in question, then we have to be explicit: The player carries a scarlet gown. The gown is wearable. "To carry" and "to wear" are different verbs, with different meanings. For example, `if Lancelot carries the plate armour` will not be true if he is wearing it rather than carrying it under his arm. As we will later see, we can instead vaguely say `if Lancelot has the plate armour` if what we mean is "if he is either carrying or wearing the armour". ### See Also - [To carry, to wear, to have] for a more detailed explanation of carrying, wearing, and possessing as Inform understands them. ## The player's holdall {kind_player's} ^^{hold-all <-- sack object} ^^{kinds: catalogue: player's holdall} ^^{player's holdall+kind+} ^^{Inform 6 equivalent: |SACK_OBJECT} ^^{possessions: a hold-all for the player's posessions} ^^{carrying capacity of (container/supporter/person)+prop+: avoid overflowing player's capacity using a hold-all} When the player has only limited carrying capacity, play is likely to be tiresome, but we can make life easier by providing a way for the player to carry endless items without dozens of free hands to hold them all: {*}"Sackcloth" The Attic is a room. The old blue rucksack is a player's holdall. The player is wearing the rucksack. The carrying capacity of the player is 3. In the Attic are a CD entitled No Smoke Without Fire, a 70s photograph of an American winning Wimbledon, a fraxinus branch, an urn holding your late great-aunt's remains, a convention badge from the American Society of Hypertension and a ghost story by M R James. This example story introduces a new kind of container, the `player's holdall`. This is a kind of which most stories will contain at most one example, but in principle there can be any number. A `player's holdall` is a capacious bag into which the player automatically places surplus items whenever their hands are full: trying the above example story and getting the items one by one will give the general idea. Of course, if the `carrying capacity` of the player is never reached then there will never be any surplus items and a `player's holdall` will behave just like any other (`portable`, usually `openable`) `container`. ### See Also - [Units] for the tools to implement a more sophisticated capacity system. ## Food ^^{food} ^^{eating+action+} ^^{edible / inedible (thing)+prop+} ^^{inedible / edible (thing)+prop+} ^^{edible (thing)+propcat+} ^^{inedible (thing)+propcat+} We have nearly reached the end of the chapter on Things, but one either/or property for things remains: every thing is either `edible` or `inedible`. Unless we say otherwise, things are `inedible`. But for instance we might write: The player carries a Macintosh apple. The Macintosh is edible. (The type of computer is named after a variety of apple descended from a tree cultivated in 1811 by John McIntosh of Ontario.) Edible things are just like inedible ones, except that the player can ``EAT`` them. This will usually only consume the foodstuff in question, effectively destroying it, but using techniques from later chapters we could make the consequences more interesting. ## Parts of things {PM_PartOfRoom} {PM_RoomOrDoorAsPart} ^^{incorporation+rel+ <-- part of+relverb+} ^^{incorporation+relcat+} ^^{components} ^^{things+kind+: parts of things} Everything has one and only one kind. This is both good and bad: good for clarity, bad if something needs to behave in two different ways at once. How might we simulate a car with an ignition key, given that no single thing can be both a `vehicle` and a `device` at the same time? The Inform world model takes the view that such a car is too complicated to be simulated with a single thing. Instead it should be simulated as a `vehicle` (the car) which has a `device` (the ignition) attached. This is done using a new relationship: `part of`. {*}"Buttons" The Confectionary Workshop is a room. The Chocolate Machine is here. "The Chocolate Machine has pride of place. A lever and two buttons, one white, the other brown, seem to be the only controls. On top is a hopper." A container called the hopper is part of the Chocolate Machine. The lever, the white button and the brown button are parts of the Chocolate Machine. The Chocolatier's desk is here. "The Chocolatier evidently works at the imposing green-leather topped desk facing the Machine. It has three drawers with brass handles." The upper drawer, the middle drawer and the lower drawer are parts of the desk. The upper drawer, the middle drawer and the lower drawer are openable closed containers. In the middle drawer is a sugared almond. In the lower drawer is a Battenburg cake. On the desk is a liquorice twist. The cake, the twist and the almond are edible. The machine and the desk each have several _parts_ representing subsidiary pieces of themselves. The desk is a `supporter` (it needs to be, for the liquorice twist to be on top) but also has three `containers` attached, each of which can be opened or closed independently. In the interests of realism, the standard rules of play protect these composite things. Thus if the desk were to be moved elsewhere (rolling on sugar casters perhaps) then its parts would move with it, and the player is not allowed to detach parts of things: the drawers can be opened or closed, but not pulled out altogether. Note that `rooms` and `regions` are not allowed to have parts. (Rooms are already parts of regions, and to divide up rooms, we can either make several rooms or place containers or other obstacles in a single one.) ## Directions {kind_direction} {PM_TooManyDirections} {PM_ImproperlyMadeDirection} {PM_DirectionTooLong} {PM_NamelessDirection} ^^{kinds: catalogue: direction} ^^{directions+kind+} ^^{opposite of (direction)+prop+} ^^{opposite of (direction)+propcat+} ^^{directions+kind+: defining} ^^{defining: directions} ^^{index map} ^^{Map page of Index panel+ui+} ^^{user interface: Index panel: Map page} ^^{Index panel+ui+: Map page} `Direction` is a kind which is quite unlike most of those seen so far. While it has to do with the physical world, a direction does not exactly belong to it. One cannot find `southeast` sitting on a shelf. `Direction` is not a kind of `thing`, and nor is it a kind of `room`: it is a kind in its own right. Every direction has an `opposite` property, which is always another `direction`. These occur in matched pairs. The opposite of north is south, just as the opposite of south is north. The opposite of southeast is northwest, the opposite of inside is outside, and so on. When Inform reads a sentence like... Bangkok is south of Nakhon Sawan. ...it assumes that the opposite map connection is probably also valid, so that Nakhon Sawan is north of Bangkok. The chapter began with the twelve directions built into Inform: north, northeast, east, southeast, south, southwest, west, northwest, up, down, inside, outside. That basically compass-based frame of reference is traditional in interactive fiction, but it doesn't suit every story. Terry Pratchett's _Discworld_ comedies (1983-2015), set on a rotating disc, use the directions turnwise, widdershins, hubwards and rimwards. Or suppose a story takes place on board a Zeppelin airship, which constantly changes its course. The cockpit then has no fixed compass bearing from the passenger cabin, and is not very naturally "north". Instead, it's fore rather than aft. For such situations, it's possible to create new directions. These have to be created in opposing pairs, and each **must** be declared with a clear simple sentence of the form `X is a direction.` For instance: Turnwise is a direction. The opposite of turnwise is widdershins. Widdershins is a direction. The opposite of widdershins is turnwise. Hubwards is a direction. The opposite of hubwards is rimwards. Rimwards is a direction. The opposite of rimwards is hubwards. It is then possible to write, say, that: Ankh-Morpork is hubwards of Lancre and turnwise from Borogravia. The Map page of the Index for a project relies on regular compass bearings, so it will get a little befuddled by this. Purely as a convenience for the author (since players never see the Index), it's possible to give Inform hints to improve the map's legibility. More on this later, but for now note that Index map with turnwise mapped as east. maps turnwise directions as if they were east, that is, pointing rightwards on the page. But to reiterate: this has no effect on the story as experienced by a player. ## Concealment ^^{concealment+rel+} ^^{concealment+relcat+} ^^{concealed (thing)+adj+} ^^{hiding things: carried by other characters} ^^{concealed possessions} ^^{deciding the concealed possessions of something+activity+} ^^{deciding the concealed possessions of something+activitycat+} ^^{possessions: deciding the concealed possessions of something+activity+} ^^{particular possession (- thing)+glob+} ^^{described / undescribed (thing)+prop+} ^^{undescribed / described (thing)+prop+} ^^{described (thing)+propcat+} ^^{undescribed (thing)+propcat+} ^^{yourself (- person)+const+} The final sections of this chapter can safely be skipped on a first reading. Though realism can become tiresome in interactive fiction, there are times when we cannot go along with Inform's normal assumption that all of a person's possessions are visible to everybody else. People are not like containers, which either show all of their holdings or not, according to whether they are `open` or `transparent`. If a man is carrying a fishing rod and a wallet, one will be on open show, the other not. Some clothing is outwardly visible, but not all. Whether or not something is _concealed_ is not like the either/or properties we have seen so far – such as being `open` or `closed` – because it is not really a property of the thing itself, but depends on the behaviour of its owner. To talk about behaviour we have to use sentences of a kind not seen so far, and which will not fully be explained for some chapters to come. But straightforward cases are easy to write, if only by imitating the following examples. Here we make the Cloaked Villain invariably conceal anything she is holding or wearing: Rule for deciding the concealed possessions of the Cloaked Villain: yes. At which point we think about it more carefully, and then rewrite: Rule for deciding the concealed possessions of the Cloaked Villain: if the particular possession is the sable cloak, no; otherwise yes. (A rule which concludes neither `yes` nor `no` will decide yes, but it's best to spell out exactly what's wanted.) Parts are treated exactly as if clothes or items being held, and the following will make the face and inscription on a coin invisible unless the player is holding it – the idea being that they are too small to be seen from farther away. {*}The coin is in the Roman Villa. The face and inscription are parts of the coin. Rule for deciding the concealed possessions of the coin: if the coin is carried, no; otherwise yes. There is also an either/or property called `described` versus `undescribed`, intended to be used only as a last resort, but which has the ability to hide something from room descriptions. The idea is that `undescribed` should be used only for cases where some other text already reveals the item, or where its presence is implicit. Even then, it should only be used when the item is intended to be taken or moved by the player at some point – if the item isn't intended to move, it's much better to make it `scenery`. (There's only one commonly-found example – the player's own body, a `person` called `yourself`, is undescribed.) Note that the `undescribed` property is automatically removed from anything carried by, worn by or part of the player, even indirectly; and that nothing on top of an `undescribed supporter` will be visible in a room description, even if it itself is `described`. (`Scenery supporters` don't suffer from that restriction, which is one reason `scenery` is a better option when possible.) ## The location of something ^^{non-existence: starting things out of play} ^^{things+kind+: starting out of play} ^^{out of play} ^^{things+kind+: location of} ^^{enclosure+rel+} ^^{enclosure+relcat+} ^^{indirect containment} ^^{containment+rel+: indirect} ^^{location (- object)+glob+} ^^{Inform 6 equivalent: |IndirectlyContains} The model world created by Inform is partitioned into rooms. This means that everything which exists in the model world, exists in one of the rooms. If we write a sentence such as Professor Wilderspin is a man. and say nothing more about Wilderspin, then he does not physically exist at the start of the story: he is said to be `out of play`, and stays that way until we move him into one of the rooms. A better metaphor might be that he is waiting in the wings, ready to come onto the stage. Every thing is either out of play, or can be found in one of the rooms, and the phrase `location of X` gives us the room in question. The following condition tests, in effect, whether Wilderspin is in play: if the location of Wilderspin is a room, ... More formally: > phrase: {ph_locationof} location of (object) ... room > > This phrase produces the room which, perhaps indirectly, contains the object given. Example: if the player stands in Biblioll College and wears a waistcoat, inside which is a fob watch, then > > location of the fob watch > > is Biblioll College. In general, a thing cannot be in two rooms at once, but there are two exceptions: two-sided doors, present on both sides, and backdrops. The "location of" a door is its front side, but a backdrop has no location. (Objects which are not things at all, such as rooms and directions, also have no location.) We very often want to know the location of the player, and this is more simply called just "the location". (This is actually a value that varies rather than a phrase, but that's a technicality we can ignore here.) The idea of indirect containment is useful enough to have a name: Inform calls it _enclosure_. A thing encloses whatever is a part of itself, or inside itself, or on top of itself, and it also encloses anything that they enclose. And when something moves around, anything it encloses will move with it. In the example above, Biblioll College (a room) and the player (a person) both enclose the fob watch and the waistcoat. For a more exhausting definition of enclosure, which is a little more subtle than it seems, see [The built-in verbs and their meanings]. Enclosure is only useful when being used as a question. So the following is fine: if the player encloses the fob watch, ... But these will produce problem messages: The player encloses the fob watch. The location of the trilobite is the Museum. because they are too vague. Inform needs to know exactly where the fob watch and the trilobite will begin the story, whereas these sentences leave room for doubt about who or what is actually holding them. # Kinds ## New kinds {NEWKINDS} ^^{kinds <-- types} ^^{kinds: defining} ^^{defining: kinds} ^^{kinds: hierarchy of kinds} ^^{kinds: of value} ^^{kinds: of thing} ^^{kinds: defining: kinds of thing} ^^{defining: kinds of thing} ^^{things+kind+: kinds of} ^^{things+kind+: object kind, as distinct from thing} ^^{rooms+kind+} ^^{things+kind+} ^^{directions+kind+} ^^{regions+kind+} ^^{animals+kind+} ^^{man+kind+} ^^{woman+kind+} ^^{Inform 6 equivalent: classes} ^^{Kinds page of Index panel+ui+} ^^{user interface: Index panel: Kinds page} ^^{Index panel+ui+: Kinds page} Values in Inform are the nouns in its sentences. They represent numbers, times of day, pieces of text, places, people, doors, and so on. Because values have such an enormous variety, and because we often want to talk about what some of them have in common, we need a way to sort these values into categories, and those are called _kinds_. Some examples: The Kinds index panel shows the kinds present in the current Inform project, which will always include a wide range of built-in kinds, and usually also some new ones created in that project. Some kinds are more general than others. For example, if we write: The Savannah is a room. The time of day is 11:30 am. Growler is an animal in the Savannah. "Growler crouches in the tall grass." then Growler is an `animal`, which is a kind of `person`, which is a kind of `thing`, which is a kind of `object`. When we talk about _the_ kind of Growler, we mean `animal`, the most specific one, but actually Growler belongs to all of those kinds. The Savannah is a `room`, which is a kind of `object`, too, but not everything is. To diagram the values involved in the story above: > `time` ▹ the constant `11:30 am` > > `time` ▹ the variable `time of day` > > `text` ▹ the constant `"Growler crouches in the tall grass."` > > `object` ▸ `room` ▹ the Savannah > > `object` ▸ `thing` ▸ `person` ▸ `animal` ▹ Growler > > `object` ▸ `thing` ▸ `person` ▹ yourself As we see from this example, kinds have a whole hierarchy. Browsing the Kinds index for a project will show what kinds it has. At first sight this is a complicated diagram, but really Inform aims to start each new story with as simple a set of kinds as it can. It has some fundamental kinds like `room`, `thing`, `direction` and `region`, but not `mammal` or `Bengal tiger`. Every story will have different needs, so the idea is to create new kinds as we need them. For example, we could write: A Bengal tiger is a kind of animal. Growler is a Bengal tiger in the Savannah. In general, it's best always to create kinds using the singular, because Inform knows how to turn singulars into plurals but not vice versa. Now that we have defined `Bengal tiger`, Inform will understand the phrase `three Bengal tigers`, for example, because it knows that `Bengal tigers` is the plural of `Bengal tiger`. But this is not a good idea: Bengal tigers are a kind of animal. So much for a specific kind like `Bengal tiger`. How about a more general one, like `mammal`? This looks awkward because it seems to belong in between. All Bengal tigers are mammals, but not all animals are mammals. But Inform can sort this out: A mammal is a kind of animal. A Bengal tiger is a kind of mammal. So now we have: > `object` ▸ `thing` ▸ `person` ▸ `animal` ▸ `mammal` ▸ `Bengal tiger` ▹ Growler Of course, a zoologist would say that a human being is a sort of animal, and indeed a mammal, so that this layout is all wrong. But Inform is for narratives, not for doing science. When people ask if an animal is in the garden, they wouldn't normally count somebody who is cutting the grass. In its everyday meaning, "animal" implies non-human, and Inform goes along with that. If we really want to rearrange Inform's default ideas, we can in fact do so: A man is a kind of animal. A woman is a kind of animal. Or indeed we could say: A human being is a kind of mammal. A man and a woman are kinds of human being. Making more specific kinds of existing ones is an excellent way to build out the physical world, but doesn't make sense for every sort of value. For instance, A glob is a kind of number. isn't allowed. The numbers are fixed and all exist already; we can write a story where the world has no Bengal tigers, but not a story where the world has no number between 4 and 6. That doesn't mean numbers are all alike, of course, and we will later see that we can use words like `even` and `odd` to describe numbers, and even create new adjectives like `unlucky` or `perfect` for them. But these are not kinds. Saying that 2 is an even number does not create a new number, and saying that 3 is an even number makes no sense. So it is not possible in Inform to create a `kind of number`. But what we can do is to invent entirely new sorts of quantity, like so: A distance is a kind of value. We will see more of these later. The word `value` here does not count as a kind (it's too vague to be useful), so `distance`, like `number`, is a top-level kind and not a specialised form of something else. ## Using new kinds ^^{descriptions (displayed): default descriptions using new kinds} ^^{kinds: defining: kinds of thing} ^^{defining: kinds of thing} ^^{things+kind+: kinds of} ^^{kinds: uses of new kinds} ^^{kinds: must define before using} This seems a good point to see what we can do with new kinds. Here we invent a new kind to provide a new sort of room: A dead end is a kind of room. Any `dead end` that we make is also a `room`, so it has all of the properties and behaviour of a room. For instance, every room is either `lighted` or `dark`, and the default is to be lighted. But we can reverse that convention for `dead ends`, and we can also fill in some other properties: A dead end is a kind of room with printed name "Dead End" and description "This is a dead end. You'll have to go back the way you came." A dead end is usually dark. The Undertomb is a dark room. East is a dead end. South is a dead end with printed name "Collapsed Dead End". Northwest is a dead end called the Tortuous Alcove. In the Undertomb is the candle lantern. It is lit. As a result of this, three different `rooms` adjoin the Undertomb, all `dead ends`. This is much more concise than spelling them out one at a time would be. > `object` ▸ `room` ▹ "The Undertomb" > > `object` ▸ `thing` ▹ candle lantern > > `object` ▸ `room` ▸ `dead end` ▹ "Dead End" > > `object` ▸ `room` ▸ `dead end` ▹ "Collapsed Dead End" > > `object` ▸ `room` ▸ `dead end` ▹ "Tortuous Alcove" Inform often doesn't mind in what order it is told about the world, but it may need to know the name of a kind before that kind can be used. For example, A coffer is a kind of container. In the Crypt is an open coffer. makes sense to Inform and results in the creation of a new thing, just called `coffer` in the absence of any other name to give it, whose kind is `coffer` and which is initially `open`. Whereas if Inform reads: In the Crypt is an open coffer. without knowing that `coffer` is a kind, it simply makes a thing called `open coffer` (and which is not a `container`). Inform has to be careful like this: English is simply too overflowing with multiple meanings. An `open railway ticket`, for instance, is not a `railway ticket` that one can put objects into. ## Degrees of certainty ^^{(always / never), in assertions+sourcepart+} ^^{(never / always), in assertions+sourcepart+} ^^{(usually / seldom), in assertions+sourcepart+} ^^{(seldom / usually), in assertions+sourcepart+} ^^{default properties of kinds} ^^{kinds: default properties} ^^{properties: defaults for kind} When we write: A dead end is a kind of room with printed name "Dead End" and description "This is a dead end. You'll have to go back the way you came." A dead end is usually dark. that last sentence is saying that it will be `dark` rather than `lighted` unless we should specify otherwise. So it would be fine to write: The Tortuous Alcove is a lighted dead end. because although `dead ends` are usually dark, this one is evidently an exception. On the other hand, if we had originally written A dead end is always dark. then Inform would not have permitted any exception to be made, and would have reported a problem if we had tried to make the Tortuous Alcove `lighted`. Besides `usually` and `always`, we can also employ `seldom` and `never`, which are their negatives. Thus, `seldom lighted` means the same as `usually dark`, and `never lighted` means `always dark`. ## Plural assertions {PM_PluralOfQuoted} {PM_PluralIsQuoted} ^^{assertions: plural} ^^{defining: things: using plurals} ^^{things+kind+: creating: using plurals} ^^{kinds: defining: kinds of thing} ^^{defining: kinds of thing} ^^{things+kind+: kinds of} ^^{|plural of: in source text} ^^{plurals: defining} ^^{defining: plurals} ^^{English: defining plural forms} As the following examples show, sentences can make several assertions at once by using the plural. Suppose we have defined a kind called `high-up fixture`, for instance like so: A high-up fixture is a kind of thing. A high-up fixture is usually fixed in place. Then the following sentence creates two such objects and puts them in their place: The high shelf and the skylight window are high-up fixtures in the Lumber Room. since it is equivalent to saying: The high shelf is a high-up fixture. The skylight window is a high-up fixture. The high shelf is in the Lumber Room. The skylight window is in the Lumber Room. Such plurals are allowed in almost any context, and we could even define two kinds at once: Bucket and basket are kinds of container. Inform constructs plurals by a form of Conway's pluralisation algorithm, which is quite good – for example, it gets oxen, geese (but mongooses), sheep, wildebeest, bream, vertebrae, quartos, wharves, phenomena, jackanapes and smallpox correct. But English is a very irregular language, and multiple-word nouns sometimes pluralise in unexpected ways. So we sometimes need to intervene: A brother in law is a kind of man. The plural of brother in law is brothers in law. We are allowed to define more than one `plural of` the same singular text, and for the names of things, rooms or kinds, all alternative versions will be used interchangeably. (For instance, Inform defines both `people` and `persons` as plurals of `person`.) ## Kinds of value {KINDSVALUE} ^^{kinds: of value <-- |enumerated value} ^^{kinds: defining: kinds of value} ^^{defining: kinds of value} ^^{values: kinds of value} ^^{kinds: enumerated values} ^^{units of measure} So much for making new and more specialised kinds of `object` – for example, new kinds of `room`, or of `animal`. This allows us to describe the physical world in elegant ways, but what about pieces of information which aren't so physical? To Inform, numbers like 1, 2, 3, ... and texts like `"Jackdaws love my big sphinx of quartz"` are not physical. They are values, but not objects, so they don't belong to the `object` kind. In fact, `number` and `text` are not kinds of any greater kind. > `number` ▹ 1821 > > `text` ▹ `"Jackdaws love my big sphinx of quartz"` Inform already has a good stock of this sort of concept built in, so it may not immediately seem clear why we need to create new ones. Most stories are not very calculational, after all, and don't obviously need new sorts of values. To see why we might, let's turn to a classic novel: ^{@Thomas Hardy}'s _The Return of the Native_ (1878). Here the narration involves a colour: > When he drew nearer he perceived it to be a spring van, ordinary in shape, but singular in colour, this being a lurid red. Hardy doesn't tell us that the wavelength of the light is 700nm, he tells us that the colour is "lurid red", and we understand. Colours turn up often in this novel: > He was a brown spot in the midst of an expanse of olive-green gorse. So perhaps we need an idea of colour where the values include `lurid red`, `brown` and `olive-green`. But on the other hand, we also have sentences like this one: > The loads were all laid together, and a pyramid of furze thirty feet in circumference now occupied the crown of the tumulus. and now we do have a quantitative measurement: "thirty feet". These are the two ways in which writers size up the world, so Inform provides both sorts of measurement: the qualitative and the quantitative. 1) Here is a qualitative example. Suppose we would like a candle lantern to burn down, gradually diminishing in brightness. Then we'll need a way to talk about the current strength of the flame, but only in vague terms. Here goes: Brightness is a kind of value. The brightnesses are guttering, weak, radiant and blazing. So this creates, for example, > `brightness` ▹ `guttering` This makes `Brightness` a kind of value on a par with `number` or `text`. But whereas they both have an almost infinite range of possible values, there are just four possible values of `brightness`, named as above. Kinds of value like this, with just a few named possibilities, are extremely useful, as we'll see. 2) Now a quantitative example: Weight is a kind of value. 1kg specifies a weight. The difference here is not the way we create the kind, but the way we tell Inform what the possible values are. Instead of a list, we teach Inform some notation. So now, for example: > `weight` ▹ `26kg` And this, like `number`, has an enormous range of possible values. Quantitative kinds like this are sometimes called "units", because – as in this example – they're often units in the sense of measuring things. Many Inform projects never need units, but they can still be very useful, and they're described in detail in the chapter on [Quantities and Equations]. ## Abstract objects and concepts ^^{kinds: catalogue: abstract object} ^^{abstract objects+kind+ <-- kinds: catalogue: abstract object} ^^{kinds: catalogue: concept} ^^{concepts+kind+ <-- kinds: catalogue: concept} The objects seen so far have almost all been physical, in one way or another, and have all belonged to the kinds `thing`, `room`, `region` or `direction`. But Inform also has a kind called `abstract object`. This can be used for something which does exist in the world, but has no spatial location. Rather than creating individual abstract objects, it's best to create kinds for them, to avoid what might be a very miscellaneous collection. One such kind exists already: `concept`. So, for example: The paranormal is a concept. Understand "supernatural" as the paranormal. produces: > `object` ▸ `abstract object` ▸ `concept` ▹ `paranormal` By default there are no concepts, and none are created automatically. Abstract objects have no physical existence, of course, so it throws a problem message to write something like: The paranormal is a concept in the Dining Room. And this would produce a run-time problem: After rubbing the lamp: now the paranormal is in the Cave. Another point of difference has to do with abbreviated names as used in sentences. Consider: The West Dining Hall is a room. Binky Henderson is in the Hall. Binky is a woman. Here the `West Dining Hall` is called just the `Hall` in the second sentence, and `Binky Henderson` is called just `Binky` in the third. This is not allowed for abstract objects: their names must be given in full at all times. This is a useful convention since abstract objects are sometimes used for large sets of values with complicated names; if these could also be abbreviated, many ambiguities would arise. Why do we need abstract objects? It's all very well to write something like: An emotion is a kind of abstract object. Hope, fear and chagrin are emotions. But we could just as well have written: Emotion is a kind of value. Hope, fear and chagrin are emotions. The answer is that for almost all purposes a kind of value works just as well or better. But there are occasionally times when we want a property or a variable to hold a value which could be either physical or abstract. For example, somebody might want to talk about the lamp, or might want to talk about chagrin. How could a single value represent either? The answer is that if `chagrin` is set up so that it is an `abstract object`, then an `object` variable could indeed hold either the value `lamp` or the value `chagrin`. ## Properties again {PM_ValueCantHaveProperties} {PM_ValueCantHaveVProperties} ^^{properties} ^^{relations} ^^{properties: either/or properties} ^^{either/or properties} ^^{properties: value properties} ^^{value properties} ^^{properties: holding text} ^^{Kinds page of Index panel+ui+} ^^{user interface: Index panel: Kinds page} ^^{Index panel+ui+: Kinds page} ^^{even / odd (number)+adj+} ^^{odd / even (number)+adj+} So now we have seen two fundamental ideas: _value_ and _kind_. We have seen how to make a source text which refers to many values – for example, Growler the Bengal tiger, 23kg, "Collapsed Dead End", blazing, 7, all values of different kinds. But we don't just want a way to refer to values, we want to lay out facts about them. Inform understands two sorts of fact, which it calls _properties_ and _relations_. Properties are about single values in isolation: Growler is male. Relations are about how values interact with each other: Growler likes Bambi. (Or would like to eat Bambi, anyway.) Relations are really the central organising idea of Inform, and we've seen them many times already: Growler is in the Savannah. expresses that the `containment relation` holds between the Savannah and Growler. Much more about this in the chapter on [Relations]: for now, let's go back to the simpler idea of properties. In Inform terms, a _property_ is any fact about a single value (other than its kind). For example, Growler is an animal. Growler is male. The description of Growler is "What immortal hand or eye could frame thy fearful symmetry?". The first of these sentences talks about Growler's kind, but the other two sentences tell Inform about his properties. Properties are divided into _either/or properties_ – `male` versus `female` – and _value properties_ – such as the `description` of something, which can be any `text`. Not all values can have properties. All objects can, so Growler is fine. There is only a finite number of Bengal tigers in the world (fewer than three thousand, alas), so Inform can easily store individual description texts for each one. But there is an infinite range of numbers. Although Inform does allow adjectives like `even` or `odd` to be used about numbers, those are descriptions and not properties. The author can declare that `Growler is female`, setting a property, but cannot declare that `7 is even.` That's not something which is up to the author to decide. _Footnote added in 2024_. During the lifetime of Inform 7, the Bengal Tiger has made a very slight comeback, and there are perhaps four thousand now. ## New either/or properties {PM_EitherOrAsValue} {PM_QualifiedCanBe} {PM_NonObjectCanBe} {PM_MiscellaneousEOProblem} {PM_ThisIsEitherOr} ^^{properties: either/or properties: defining} ^^{either/or properties: defining} ^^{defining: either/or properties} ^^{Inform 6 equivalent: attributes} Properties can't be handed out completely freely. In the previous chapter, [Things], we saw that we were allowed to make a chair `portable` and to make a room `dark`. But if we try this the other way round, Inform produces a Problem message. This is because every kind has its own set of permitted properties: or to put it the other way round, every property has its own set of kinds it can belong to. The Standard Rules built into Inform say that A thing can be fixed in place or portable. and as a result it won't allow `The Savannah is portable` because the Savannah is a `room`, not a `thing`. We must do the same. To go back to our example `dead end` kind: A dead end is either secret or ordinary. This creates just one new property, not two. The names are taken as the two states of a single either/or property: `secret` means `not ordinary`, `ordinary` means `not secret`. Alternatively, we could just say: A dead end can be secret. in which case the only way to express the opposite of `secret` would be to write `not secret`. By giving them new properties, we can add to the definitions of any kinds which already exist, including those built into Inform: for instance, A room is either indoors or outdoors. If we make the above definitions then all `dead ends` will be `ordinary` and all rooms `outdoors` unless the source text says otherwise. That is, in the absence of other information it's assumed that an either/or property is _not_ true. We could reverse by writing: A dead end is usually secret. A room is usually indoors. A property can be used by several kinds at once. For example, the built-in either/or property `open` is used by both `doors` and `containers`, even though `door` isn't a kind of `container` and `container` isn't a kind of `door`. In fact, although it's more usual to declare properties for whole kinds, they can actually be given to single values one at a time, if we like: The umbrella is carried by the player. The umbrella can be open. And now the umbrella, which is a `thing` and not a `door` or `container`, can also have the property. But other things cannot, unless further sentences like this are written. ## New value properties {PM_PropertyOfKind1} {PM_PropertyCalledArticle} {PM_PropertyCalledPresence} {PM_PropertyNameForbidden} {PM_PropertyUninitialisable} {PM_BadVisibilityWhen} {PM_PropertyTooSpecific} {PM_PropertyKindUnknown} {PM_PropertyKindVague} {PM_PropertyKindClashes} {PM_BadProvides} {PM_RedundantThatVaries} ^^{properties: value properties: defining} ^^{value properties: defining} ^^{defining: value properties} ^^{(has), for defining properties+sourcepart+} ^^{kinds: default values of kinds} ^^{Kinds page of Index panel+ui+} ^^{user interface: Index panel: Kinds page} ^^{Index panel+ui+: Kinds page} ^^{Inform 6 equivalent: properties} So much for either/or properties. Now we move on to properties which have values attached. The same principles apply, but the wording is different. For example, A dead end has some text called the river sound. The river sound of a dead end is usually "a faint whispering of running water". The Tortuous Alcove has river sound "a gurgle of running water". The property `river sound` is now applicable only to `dead ends`, so we would not be allowed to talk about `the river sound of the Savannah`, say. Moreover, it's required to hold a piece of `text`. If we tried the following: The river sound of the Tortuous Alcove is 7. ...then Inform would object, because the number 7 is the wrong kind of value to go into the `river sound` property. If we need a numerical property, we can try this instead: A dead end has a number called the difficulty rating. The Tortuous Alcove has difficulty rating 7. Suppose that we were to add: The Exquisitely Narrow Defile is a dead end. The Defile must have a `river sound`, of course, because we said that every `dead end` would have one. We haven't said what that sound will be, but Inform can work it out, because we did say this: The river sound of a dead end is usually "a faint whispering of running water". If there are no instructions at all about the value of a property, Inform fills in the default value of the appropriate kind – in this case, it would be a blank `text`. (A table of the kinds which can be used for properties, and their default values, can be found in the Kinds index.) ## Using new kinds of value in properties ^^{kinds: defining: kinds of value} ^^{defining: kinds of value} ^^{values: kinds of value} ^^{kinds: enumerated values} ^^{text substitutions: new kinds of value} ^^{values: displaying} ^^{text substitutions: enumerated values} ^^{properties: holding a new kind of value} ^^{properties: value properties: defining} ^^{value properties: defining} ^^{defining: value properties} ^^{(of), for properties+sourcepart+} It turns out to be very useful to create a new kind of value, and then create a property to hold it. So useful, in fact, that Inform provides two shortened forms for doing so. Here is the first, and the second (making _conditions_) is in the section following. Suppose we go back to our example of the candle lantern whose brightness we have to measure. It's clear that what we want to do is to define: Brightness is a kind of value. The brightnesses are guttering, weak, radiant and blazing. And now we can use the technique of the previous section: The lantern has a brightness called the flame strength. The flame strength of the lantern is blazing. This works very nicely. The `flame strength` property is now only allowed to have one of four values we allowed: `guttering light`, `weak light`, `radiant light` or `blazing light`. So we have succeeded in recording our measurement. But it seems artificial to call the brightness of the lantern `flame strength`, when we could instead simply call it `brightness`. Much simpler to write: The lantern has a brightness. The lantern is blazing. Now `brightness` is the name of _both_ the property _and_ the kind of value. What's particularly nice is that we can now use the names of the possible brightnesses – `weak`, `blazing` and so on – as adjectives. Inform knows that `The lantern is blazing.` must be talking about the `brightness` property, because `blazing` is a `brightness`. Now we can improve our dead ends: A dead end is a kind of room with printed name "Dead End" and description "This is a dead end, where crags in the uneven rock are caught by the [brightness of the lantern] flame you hold aloft. Despite [river sound] there is no sign of the stream." A dead end is usually dark. The `"[brightness of the lantern]"` is printed not as literal text, but as whatever the brightness currently is. (The square brackets mark it as what is called a text substitution, which will be the subject of the next chapter, [Text].) So we get something like this: This is a dead end, where crags in the uneven rock are caught by the blazing flame you hold aloft. Despite a faint whispering of running water there is no sign of the stream. So now we have a lantern, which has a `brightness` as a property. But we can build on this further if we like. A `brightness` such as `guttering` is a value, so it can have properties in its own right. That can be quite useful, in fact: A brightness can be adequate or inadequate. A brightness is usually adequate. Guttering is inadequate. This is convenient because it divides up the brightnesses: The player carries a book. The description of the book is "[if the brightness of the lantern is adequate]Many secrets are now yours.[otherwise]No, the print's too tiny by this awful light." And while we're at it, let's give each `brightness` its own corresponding `temperature`: Temperature is a kind of value. 100C specifies a temperature. A brightness has a temperature. The temperature of a brightness is usually 700C. The temperature of blazing is 1400C. The temperature of radiant is 1100C. The description of the lantern is "The lantern shines with a flame at [temperature of the brightness of the lantern]." (Candle flames are hotter than most people think.) ### See Also - [Text with substitutions] for more on varying what is printed. ## Conditions of things {PM_EitherOnThree} ^^{kinds: defining: kinds of value} ^^{defining: kinds of value} ^^{values: kinds of value} ^^{kinds: enumerated values} ^^{properties: holding a new kind of value} ^^{properties: value properties: defining} ^^{value properties: defining} ^^{defining: value properties} ^^{(condition), as name for value property+sourcepart+} Now for an even more abbreviated way to create a new kind of value, and at the same time create a property to hold it. Suppose we have something, say a wine cask, which we know is always in one of three different states. We can write: The cask is either customs sealed, liable to tax or stolen goods. This is just like our example of the lantern having possible brightnesses, but it's quicker to do, because we don't need to create or name the kind of value. (The trade-off is that we can't use it for anything else as well.) Initially the cask will be `customs sealed`, the first value we gave. We could now write, for instance, The description of the cask is "A well-caulked Spanish wine cask.[if liable to tax] It really is a shame to have to pay duty on it!" Or, as a second example, here we're going to allow a whole kind to have the property, not just a single object: Colour is a kind of value. The colours are red, green and white. A colour can be bright, neutral or flat. Green is neutral. Now in fact these properties are not anonymous: Inform has worked out names for them, even though we didn't give any. The usual arrangement is that the name is the name of the object with the word `condition` tacked on: for instance, `cask condition`. So we could write: The printed name of the cask is "wine cask ([cask condition])". so that sometimes this would be written out in the story as ``wine cask (liable to tax)``, sometimes ``wine cask (stolen goods)`` and so on. But only usually, because we might need to define several different conditions of the same thing, and then the names would collide. For instance, suppose we write: A fruit is a kind of thing. A fruit can be citrus, berry, melon, or pome. This makes a property and a kind of value each called `fruit condition`. But now suppose we add that: A fruit can be unripened, ripe, overripe, or mushy. This is a quite unrelated property – a fruit could have any combination of these two properties, in fact. Left to itself, Inform will call the second one `fruit condition 2`, which isn't really ideal if we ever do need to refer to it in other source text. So we are also allowed to give these conditions names of our own choosing: A fruit can be unripened, ripe, overripe, or mushy (this is its squishiness property). And now the resulting property and kind of value would be called `squishiness`. ## Default values of kinds ^^{kinds: default values of kinds <-- default properties of kinds} ^^{values: kinds of value: default values} ^^{Kinds page of Index panel+ui+} ^^{user interface: Index panel: Kinds page} ^^{Index panel+ui+: Kinds page} Just about every kind has a _default value_. Inform needs this when it knows that something has to be a value of a given kind, but it hasn't been told what the value is. For example, in the previous chapter on [Things], we saw that every `thing` has a `description` text, but we also created plenty of things without describing them. So if Inform reads The conference pear is in the bowl. and it isn't told anything else about the pear, what should it set the description of the pear to? The answer is that Inform knows the description has to be a value of the kind `text`, so it uses the default value of `text`. Not very interestingly, this is just the blank text `""`. Being uninteresting is exactly the idea, of course. The default number is 0, for instance. Default values are tabulated in the Kinds index. It's sometimes useful to be able to refer to the default value of a kind without having to spell out what this is (especially if the kind is something obscure, or we're trying to write a rule for an extension which has to work in situations we don't fully know about). > phrase: {ph_defaultvalue} default value of (name of kind) ... value > > Produces the default value of the kind named. Examples: > > The silver repeater is here. "You catch sight of a silver repeater watch, hands immobile at [default value of time]." > > produces the output: > > You catch sight of a silver repeater watch, hands immobile at 9:00 am. > > because nine in the morning is the default time in Inform. If we have: > > Brightness is a kind of value. The brightnesses are guttering, weak, radiant and blazing. > > then `default value of brightness` is guttering, the first `brightness` created. When it comes to kinds of object, we sometimes have to be a little careful. For example, > > default value of room > > is always going to be fine (it's always the first room created in the source text). But > > default value of vehicle > > would produce a Problem message if there were no vehicles in the world. ## Values that vary {var_location} {VARIABLES} {PM_EmptyKind} ^^{variables: global <-- values: varying <-- global variables} ^^{defining: global variables} ^^{Inform 6 equivalent: global variable} ^^{(that varies), in defining global variables+sourcepart+} ^^{(which varies), in defining global variables+sourcepart+} ^^{(initially), in defining global variables+sourcepart+} ^^{location (- object)+glob+} ^^{kinds: default values of kinds} ^^{type-checking: for global variables} ^^{Kinds page of Index panel+ui+} ^^{user interface: Index panel: Kinds page} ^^{Index panel+ui+: Kinds page} Sometimes a value important to the simulated world will not naturally belong to any `thing` or `room`, because it is not a property of anything in particular. In fact, we have seen a value that varies already: `location`, which holds the `room` in which the story is presently taking place (properly speaking, which encloses the player's body). Here's how we might make a new one: The prevailing wind is a direction that varies. The prevailing wind is southwest. Or `which varies` would also be allowed, as would the more traditional computing term `variable`: The prevailing wind is a direction variable. The prevailing wind is southwest. A briefer way to do this is to use the word `initially`, which alerts Inform to the possibility that the value will change in future: The prevailing wind is initially southwest. This _both_ creates the variable _and_ gives it an initial value, in a single sentence. It's not compulsory to give an initial value. If we do not, Inform will use the default value for its kind. (For more on that, see [Default values of kinds].) For example, writing just The grand tally is a number that varies. will start it at the value 0, because that's the default value for the kind `number`. We can have variables of any of the kinds of value, including new ones, but should watch out for a potential error. If we write: The receptacle is a container that varies. in a world which has no `containers` at all, Inform will object, because it will be unable to put any initial value into the `receptacle` variable. A similar complaint will be made if we write: Colour is a kind of value. The fashionable shade is a colour that varies. without ever having defined any `colours`. Something else we are not permitted is: The receptacle is an open container that varies. because the openness of a given `container` may change during play, so that the value in the variable might suddenly become invalid even though the variable itself had not changed. As a final note on kinds, when Inform reads something like this: Peter is a man. The accursed one is initially Peter. it has to make a decision about the kind of `accursed one`. Peter is a `man`, so Inform makes this a `man that varies`. But this means it can't later to change to a woman called Jane, say, or a black hat. So Inform allows us to be override its guesses: The accursed one is a thing that varies. Peter is a man. The accursed one is initially Peter. ## Values that never vary ^^{constant values <-- values: constant <-- global constants} ^^{defining: constant values} ^^{Inform 6 equivalent: constants} ^^{(always), in defining constant values+sourcepart+} It's sometimes useful to name even values which don't change. For example, suppose the story involves driving, and the same speed limit value comes up in many places. Rather than typing `55` (say) every time it comes up, we might prefer to write: The speed limit is always 55. at the start of the source text, and then talk about `the speed limit` every time we would otherwise have typed `55`. Just as the word `initially` alerts Inform that we want the named value to change during play, the word `always` tells it that we don't. This might seem pointless, because `speed limit` only means the same thing as `55` and takes more typing. But there are two reasons why authors might want to use this feature anyway. One is that it's easier for a human reader to understand the significance of a line like: if the speed is greater than the speed limit, ... Another is that it makes it easier to change our minds about the value, because if we decide we want 70 as the limit and not 55, we only need to make one change at the start of the source text: The speed limit is always 70. which is much easier than combing through a long source text trying to find many individual things which need changing. `Speed limit` is then a `number` constant. Any attempt to set this elsewhere, or change its value, will result in a Problem message, and moreover it can be used in contexts where only constant values are allowed. For example, The generic male appearance is always "He is a dude." Trevor is a man. The description of Trevor is the generic male appearance. means that typing ``EXAMINE TREVOR`` produces the reply ``He is a dude.`` ## Duplicates {PM_TooManyDuplicates} ^^{duplicates <-- multiple copies of things} ^^{things+kind+: creating: multiple identical things with counts} ^^{defining: things: multiply with counts} ^^{use options: catalogue: |maximum things understood at once} ^^{use options: catalogue: |no automatic plural synonyms} ^^{maximum things understood at once+useopt+} ^^{no automatic plural synonyms+useopt+} Although it is only useful to a limited extent, we can make any number of copies of something: {*}"Polygons" A shape is a kind of thing. A square is a kind of shape. A triangle is a kind of shape. The Geometry Lab is a room. In the Geometry Lab are three triangles and two squares. The description `three triangles` makes three identical things, each of the kind `triangle`, and similarly for the squares. When the above is compiled, the player can type ``TAKE TWO TRIANGLES`` or ``TAKE ALL THE TRIANGLES`` and so forth. Four caveats: 1) Firstly, a counted-out description like `two squares` is only allowed if it combines a number with the name of a kind which is already known (perhaps modified with adjectives, so `two open doors` is fine). If we say: Two circles are in the Lab. without having defined `circle` as a kind in advance, then only a single object will be created – whose name is `two circles`. (This is because many natural names start with numbers: `six of clubs`, for instance, referring to a single playing card, or `12 Hollywood Close` meaning a single house. We wouldn't want such names to be misinterpreted.) 2) Excessive duplication is expensive in memory and running time. It is perfectly legal to say In the Lab are 75 triangles. but the resulting story may be a little sluggish: and Inform draws the line at 100, refusing to create more duplicates than that in any single place. If we really need more than about fifty duplicated objects – say, a tombola containing raffle tickets numbered 1 to 1000 – it is usually better to find some less literal way to simulate this: for instance, only having a single raffle ticket, but with a randomly chosen number on it. If there are very many items in the same place, commands like ``TAKE ALL`` and ``DROP ALL`` may mysteriously not quite deal with all of them – this is because the parser, the run-time program which deciphers typed commands, has only limited memory to hold the possibilities. It can be raised with a use option like so: Use maximum things understood at once of at least 200. (The default is, as above, 100. Note the `at least`.) 3) Inform's idea of "identical" is based on what the player could type in a command to distinguish things. In a few cases this can make items unexpectedly identical. For example: The Lab is a room. A chemical is a kind of thing. Some polyethylene and polyethylene-terephthalate are chemicals in the Lab. results surprisingly in ``You can see two chemicals here.``, because the run-time system truncates the words that are typed – ``POLYETHYLENE`` and ``POLYETHYLENE-TEREPHTHALATE`` look like the same word in a typed command. So Inform decides that these are indistinguishable chemicals. Words are typically truncated after 9 letters. The best way to avoid trouble is simply to use more easily distinguishable names. For example: Some polyethylene and polyethylene terephthalate are chemicals in the Lab. works fine, because now only one chemical can be called ``TEREPHTHALATE``, and that means they can be distinguished. 4) Finally: numbers up to twelve may be written out in words in the source text, but larger ones must be written as numerals. So `twelve` or `12`, but `13` only. Whenever a kind of object is created, Inform allows the pluralised name of the kind to be used to refer to such objects in typed commands. That's why creating `A coin is a kind of thing.` enables commands like ``TAKE THREE COINS`` to work: Inform takes the name `coin` and pluralises it as ``COINS``. But some authors prefer not to have this feature, and to enable all plural nouns in commands by hand. For those authors, this use option is provided: Use no automatic plural synonyms. Then, for example, in the following story: Use no automatic plural synonyms. A badger is a kind of animal. Understand "brocks" as a badger. An acorn is a kind of thing. The Night Garden is a room. Two badgers and six acorns are in the Night Garden. the player could type ``GET BADGERS`` (do _not_ try this in real life) but not ``GET ACORNS``. ### See Also - [Plural assertions] for how to change Inform's guesses about plurals of nouns. ## Assemblies and body parts {PM_AssemblyLoop} {PM_AssemblyRegress} {PM_ComplexEvery} ^^{assemblies} ^^{components: for kinds} ^^{things+kind+: parts of} ^^{incorporation+rel+} ^^{incorporation+relcat+} ^^{body parts} ^^{|every: creating assemblies} ^^{defining: things: using relations} ^^{things+kind+: creating: using relations} ^^{relations: creating things in relation to} In the previous chapter, [Things], we saw that it was possible to make sub-parts of things. For instance, The white door is in the Drawing Room. The handle is part of the white door. creates a door with an attached handle. But what if we want to say that not just this door, but every door, should have a handle? To do this we first need to create a kind called `handle`, since there will clearly need to be many handles. The solution is: A handle is a kind of thing. A handle is part of every door. `Every` is a loaded word and best used sparingly. A sentence like `A handle is part of every handle.` would, if taken literally, mean that a `handle` takes forever to make and is never finished. Inform will reject this, but the moral is clear: we should think about what we are doing with `every`. We will usually want to work with smaller collections – not literally every room, but with a whole set of them all the same. We can do that like so: A silver coin is a kind of thing. A banking room is a kind of room. Five silver coins are in every banking room. The effect of sentences like these is to make so-called _assemblies_ instead of single things. When a banking room is created, so are five more silver coins; when a door is created, so is another handle. Such sentences act not only on items created later on in the source text, but also on all those created so far. This is especially useful for body parts. If we would like to explore Voltaire's suggestion that history would have been very different if only Cleopatra's nose had been shorter, we will need noses: A nose is a kind of thing. A nose is part of every person. Of course, if we make an assembly like this then we had better remember that the player is also a person and also gets a nose. In fact slightly odd things can happen if we combine this with changing the identity of the player. This works: Cleopatra is a woman in Alexandria. The player is Cleopatra. A nose is a kind of thing. A nose is part of every person. but if those lines are in reverse order then Cleopatra's nose is assembled before she becomes the player, with the result that it ends up called ``Cleopatra's nose`` rather than ``your nose`` in play – which is very regal but probably not what we want. To avoid this, settle the player's identity early on in the source text. All of the assemblies above make objects. Most make these new objects `part of` existing ones, but as we saw, they can also be `in` or `on` them. In fact, though, assemblies work in much more general ways: they can assemble values of almost any kind, placed in almost any relationship. To make use of that, we need to create a new verb, a topic which won't be covered properly until a later chapter, but here goes: A colour is a kind of value. The colours are red, green and blue. Liking relates various people to various colours. The verb to like means the liking relation. Every person likes a colour. Now every time a `person` is created, so is a `colour` which that person will like. If there are two `people` in the world, the player and Daphne, then we now have five `colours`: red, green, blue, Daphne's colour and the player's colour. Alternatively, we can assemble the other way around: A person likes every colour. Now we're telling Inform that every time a `colour` is made, a new `person` is also made – someone who will like that `colour`. So this sentence effectively makes three new people, one who likes red, one who likes green, and one who likes blue. ## Names made in assembly ^^{|called: in creating assemblies} ^^{|every: creating assemblies} ^^{defining: things: using relations} ^^{things+kind+: creating: using relations} ^^{relations: creating things in relation to} ^^{names: for things created in assemblies} ^^{assemblies: names in} Something skated over in the previous section is the question of how Inform gives names to objects (or other values) it creates in an assembly. The standard thing naming combines the names of what's being assembled. For example: A nose is a kind of thing. A nose is part of every person. Antony and Cleopatra are people. might result in the creation of "Antony's nose", part of Antony, and "Cleopatra's nose", part of Cleopatra. In this way, Inform names the noses after their owners. It can safely do that because these noses are _part of_ their owners: there is something individual about Antony's nose. With other relations, or where multiple indistinguishable things are being created, names are not normally confected. For example: The Herb Garden is east of the Floral Display. A trowel is a kind of thing. Three trowels are in every room. A vehicle is in every room. results in each room containing four items simply called "trowel", "trowel", "trowel", "vehicle". But for single items, those names can be changed using `called`. For example: The Herb Garden is east of the Floral Display. Every room contains a vehicle (called its buggy). A trowel is a kind of thing. A trowel (called agricultural implement) is in every room. produces "Herb Garden's buggy" and "agricultural implement" in the HG, and "Floral Display's buggy" and "agricultural implement" in the FD. `it` can be used, too: Rex is an animal in the Garden. Every animal wears a thing (called the collar belonging to it). This causes Rex to be wearing "collar belonging to Rex". Looking back at the original case of noses, we can now see that: A nose is a kind of thing. A nose is part of every person. Antony and Cleopatra are people. was just an abbreviation for: A nose is a kind of thing. A nose (called his nose) is part of every person. Antony and Cleopatra are people. And this could be customised by: A nose is a kind of thing. A nose (called his noble schnozzle) is part of every person. which would mean that "Antony's noble schnozzle" and "Cleopatra's noble schnozzle" exist. So will "your noble schnozzle", incidentally, since the player is also normally a person, and indeed "Rex's noble schnozzle", since Rex is an animal and therefore also a person. Assemblies need to be used cautiously, or they will get out of control with all the items they create. Assemblies are not confined to physical relationships. Suppose we set up: A colour is a kind of value. The colours are lime green, signal red and cerulean blue. We could then assemble like so: A person (called its fan) likes every colour. which creates "lime green's fan", "signal red's fan" and "cerulean blue's fan", three new people, or alternatively like so: Every person likes a colour (called their favourite colour). which would produce new colours with names like "Antony's favourite colour". (And indeed "Rex's favourite colour", despite dogs being colour-blind.) So much for an informal description. Here is exactly what Inform does: 1) If multiple things are being created in a single assembly, they are each anonymously named after their kinds. Example: `Three vehicles are in every room.` 2) If a single thing is being created, but no `called` text is given, and the relation is not `incorporation` (i.e., `part of`), then its name will likewise be just the name of its kind. Example: `A door is in every room.` 3) If a single thing is being created, and the relation is `incorporation` (i.e., `part of`), and there is no `called` text given, then it will have a name generated from the thing it is a part of. Example: `A container is part of every door.` 4) If a single thing is being created, and a `called` text is given, then it will have a name generated from this text, expanding out `its` (or `his` or `her` or `their`) to a possessive form of the name of the owner, so to speak, and `it` (or `he` or `she` or `they` or `him` or `them`) to the name itself. Example: `A vehicle (called its buggy) is in every room.` 5) If values rather than objects are created, rules (1) to (4) apply in the same way, but Inform tacks on a number if necessary to force each new name to be different from existing ones: e.g., "Daphne's colour 2", "Daphne's colour 3", ... (This is because, unlike objects, values must have unique names.) ## Implications {PM_ImplicationCertain} {PM_ImplicationValueProperty} ^^{properties: implications} Implications are a feature of Inform which may be best avoided unless the need really arises. They can be tricky, and can have unforeseen consequences. We should handle them with care. They are most useful when setting up kinds which have multiple properties, where those properties have overlapping duties in some slightly complicated way. As a result, they are more often used by Inform extensions than in the main source text of a story, but of course they're available to both. For example, consider Inform's built-in `locked` property. If a door is locked, then it cannot be opened, which seems fair enough. But a player who then tries to unlock the door might then be told: ``` transcript That doesn't seem to be something you can unlock. ``` Which does not seem right. In real life, almost all locked items have outwardly exposed locks which it is perfectly sensible to try to unlock, given a key. The problem is that our door has the `locked` property, but not the `lockable` one. The Standard Rules (included automatically in all Inform stories) solve this problem with the following _implication_: Something locked is usually lockable. And this ensures that any door said by the author only to be `locked` will be `lockable` as well, and adds a small but worthwhile touch of realism. This sentence has a form roughly like "if Condition A holds then probably Condition B does as well". Note that the two conditions must be quite simple ones, without relative clauses: they need to consist only of adjectives for either-or properties, possibly with the names of kinds added. Thus: A room in the Open Desert is usually lighted. will not work because `a room in the Open Desert` is a more complicated grammatical construction than, say, `lighted` or `a lighted room`: it contains a relative clause. Inform can only deal with simple implications. Inform never overrides certainties with mere implications, and is cautious about allowing them to build overly long chains of argument. This is to prevent the following kind of difficulty: An open door is usually closed. A closed door is usually open. Implications work just the same for values which aren't objects, so: Colour is a kind of value. The colours are red, green and blue. A colour can be zesty or flat. A colour can be bright or dull. Red and blue are bright. Blue is flat. A bright colour is usually zesty. results in red being zesty, but blue and green being flat; blue because the source text explicitly says so (which trumps the `usually`), and green because this isn't a bright colour, so the implication doesn't arise. # Text ## Text with substitutions {PM_TSWithPunctuation} ^^{text <-- strings of characters} ^^{text: displaying} ^^{text substitutions: text} ^^{descriptions (displayed): with substituted text} ^^{rooms+kind+: descriptions: with substituted text} ^^{punctuation: square brackets: text substitutions} ^^{|[ ]: text substitutions} ^^{punctuation: quotation marks: defining texts} ^^{|": defining texts} In the previous chapter, [Kinds], we gave properties to certain kinds of things in order to change their appearance and behaviour, and saw brief glimpses of one of Inform's most useful devices: _text substitution_. The following gives a more complete example: {*}"The Undertomb" A dead end is a kind of room with printed name "Dead End" and description "This is a dead end. You'll have to go back the way you came, consoled only by [river sound]." A dead end is usually dark. The Undertomb is a dark room. East is a dead end. South is a dead end with printed name "Collapsed Dead End". Northwest is a dead end called the Tortuous Alcove. In the Undertomb is the lantern. It is lit. A dead end has some text called river sound. The river sound of a dead end is usually "a faint whispering of running water". The Tortuous Alcove has river sound "a gurgle of running water". The novelty here is the text in square brackets in the first paragraph. They imply more or less what they would when a journalist is quoting something in a newspaper article: "This is a dead end. You'll have to go back the way you came, consoled only by [river sound]." The actual words `river sound` are not part of the text. Instead, when Inform prints up the description of a dead end, it will substitute the appropriate river sound in place of these words. Looking in the Collapsed Dead End, a player reads: ``` transcript This is a dead end. You'll have to go back the way you came, consoled only by a faint whispering of running water. ``` Whereas in the Tortuous Alcove: ``` transcript This is a dead end. You'll have to go back the way you came, consoled only by a gurgle of running water. ``` And this is because `[river sound]` was substituted with the value of the `river sound` property of each of the rooms. And so, as the player explores these dead ends, subtle differences will appear in their room descriptions. Most of the time it's very convenient not to have spell out the owner of the property, in texts like this, but ambiguity can occasionally arise. One case in particular is when a property name coincides with the name of a kind, and then is used by this name in a test within some text. For example: Polish is a kind of value. The polishes are gleaming, stippled, and dull. A thing has a polish. A brass plaque is here. "A brass plaque on one wall is [if polish is gleaming]highly[otherwise]barely[end if] reflective." The plaque is dull. This does _not_ result in the plaque being called ```barely reflective```, as might have been expected. That is because the word `polish` in the test is read by Inform as a common noun (the name of a kind which refers to all forms of polish), not as a proper noun (the specific polish property which the plaque has at the moment). The test `if polish is gleaming` then passes, because Inform asks itself if one of the values of `polish` is `gleaming`... which of course it is. And so, even though the plaque is dull, the description says it is ```highly reflective```. So, when writing conditions about properties whose names are the same as kinds inside of text like this, it's safer to spell things out: "A brass plaque on one wall is [if the polish of the plaque is gleaming]highly[otherwise]barely[end if] reflective." ## How Inform reads quoted text ^^{text substitutions: punctuation} ^^{punctuation: square brackets: text substitutions} ^^{|[ ]: text substitutions} ^^{punctuation: quotation marks: defining texts} ^^{|": defining texts} ^^{punctuation: apostrophe: meaning quotation mark} ^^{|': meaning (")+sourcepart+} ^^{punctuation: full stop: ending sentences with line breaks} ^^{|.: ending sentences with line breaks} ^^{punctuation: exclamation mark, ending sentences} ^^{(!), ending sentences+sourcepart+} ^^{punctuation: question mark, ending sentences} ^^{(?), ending sentences+sourcepart+} ^^{line breaks: produced by sentence-ending punctuation} ^^{+to+say "[']"} ^^{+tosay+"[']" --> '} ^^{source text: quoted text} ^^{comparisons: of text} ^^{text: comparing} ^^{empty / non-empty+adj+: for texts} ^^{non-empty / empty+adj+: for texts} ^^{text: empty / non-empty+adj+} Text is so fundamental to Inform that the basics had to be covered back in the [The Source Text] chapter, so let's begin this new chapter with a recap. Literal text is written in double-quotation marks. It's mostly true that what you see is what you get: the literal text `"The Hands of the Silversmith"` prints back as ``The Hands of the Silversmith``. But four characters are read in unexpected ways: `[`, `]`, `'` and `"`. The rules are as follows: **Exception 1.** Square brackets `[` and `]` are used to describe what Inform should say, but in a non-literal way. For example, "Your watch reads [time of day]." might produce ``Your watch reads 9:02 AM.`` These are called _text substitutions_. They're highly flexible, and they can take many different forms. But as useful as they are, they do seem to stop us from making actual ``[`` and ``]`` characters come through on screen. To get around that: > phrase: {phs_bracket} say "[bracket]" > > This text substitution expands to a single open square bracket, avoiding the problem that a literal [ in text would look to Inform like the opening of a substitution. Example: > > "He [bracket]Lord Astor[close bracket] would, wouldn't he?" > > prints as ``He [Lord Astor] would, wouldn't he?``. > phrase: {phs_closebracket} say "[close bracket]" > > This text substitution expands to a single close square bracket, avoiding the problem that a literal `]` in text would look to Inform like the closing of a substitution. Example: > > "He [bracket]Lord Astor[close bracket] would, wouldn't he?" > > prints as ``He [Lord Astor] would, wouldn't he?``. **Exception 2.** Single quotation marks at the edges of words are printed as double. So: "Simon says, 'It's far too heavy to lift.'" produces ``Simon says, "It's far too heavy to lift."`` This is good because typing a double quotation mark inside the quote wouldn't work – it would end the text then and there. Single quotation marks inside words, such as the one in "It's", remain apostrophes. The rule looks odd at first, but turns out to be very practical. The only problem arises if we need an apostrophe at the start or end of a word, or a double inside one. Again, substitutions can fix this: > phrase: {phs_apostrophe} say "[apostrophe/']" > > This text substitution expands to a single quotation mark, avoiding Inform's ordinary rule of converting literal single quotation marks to double at the edges of words. Example: > > Instead of going outside, say "Lucy snaps, 'What's the matter? You don't trust my cookin[apostrophe] mister?'" > > produces ``Lucy snaps, "What's the matter? You don't trust my cookin' mister?"`` > > A more abbreviated form would be: > > Instead of going outside, say "Lucy snaps, 'What's the matter? You don't trust my cookin['] mister?'" > > which has exactly the same meaning. > phrase: {phs_quotemark} say "[quotation mark]" > > This text substitution expands to a double quotation mark. Most of the time this is unnecessary because of Inform's rule of converting literal single quotation marks to double at the edges of words, so it's needed only if we want a double-quote in the middle of a word for some reason. Example: > > "The compass reads 41o21'23[quotation mark]E." > > which produces: ``The compass reads 41o21'23"E.`` (Note that `["]` is not allowed; a double-quotation mark is never allowed inside double-quoted text, not even in a text substitution.) **Exception 3.** Texts which end with sentence-ending punctuation – full stop, question mark, exclamation mark – are printed with a line break after them. So: say "i don't know how this ends"; say "I know just how this ends!"; would come out quite differently – this doesn't affect the appearance of the text, but only the position where the next text will appear. Again, sometimes this is not what we want – the full rules are complicated enough to be worth a whole section later in the chapter. **A note about texts as values.** At this stage we have mostly seen text used in properties or in `say` phrases, but texts are values. Getting a little ahead of ourselves, we can write rules or phrases which manipulate texts, or test them, in the same way we might calculate with numbers. For example, if `T1` and `T2` are text values, then if T1 is T2, ... is a condition which is true if they both currently work out to the same contents. Because of text substitutions, this can be true even if they appear to be different. For example, if a story contains rooms called `Draughting Office` and `Shipyards`, then whether `"[the Office]"` and `"[the location]"` are equal depends on where the player is. (If they _are_ equal, they will both be equivalent to the unsubstituted text `"Draughting Office"`; if not, one will be `"Draughting Office"` and the other `"Shipyards"`.) Inform provides the adjectives `empty` and `non-empty` for texts, but again care is needed over substitutions. `if T is empty` is never true for text with a substitution in it, so it is not quite the same test as `if T is ""`. For more on this, see [Defining adjectives for values]. ## Text which names things ^^{text substitutions: numbers} ^^{numbers: displaying} ^^{text substitutions: values} ^^{values: displaying} ^^{text substitutions: things} ^^{things+kind+: displaying} ^^{definite articles: when displaying things} ^^{indefinite articles: when displaying things} ^^{|a / an / the --> a: in displaying things} ^^{|an / a / the --> an: in displaying things} ^^{|the / a / an --> the: in displaying things} ^^{case sensitivity: in text substitutions with objects}^^^{+tosay+"[(sayable value)]" --> sayable value}^^^{+tosay+"[(number)]" --> number}^^^{+tosay+"[a (object)]" --> a object}^^^{+tosay+"[A (object)]" --> A object}^^^{+tosay+"[the (object)]" --> the object}^^^{+tosay+"[The (object)]" --> The object} We can put almost any description of a value in square brackets in text, and Inform will work out what kind of value it is and print something accordingly. (Only almost any, because we aren't allowed to use commas or more quotation marks inside a square-bracketed substitution.) > phrase: {ph_say} say "[(sayable value)]" > > This text substitution takes the value and produces a textual representation of it. Most kinds of value, and really all of the useful ones, are `sayable` – numbers, times, objects, rules, scenes, and so on. Example: > > The description of the wrist watch is "The dial reads [time of day]." > > Here `time of day` is a value – it's a `time` that varies, and `time` is a `sayable` kind of value, so we might get ``The dial reads 11:03 AM.`` The values we say most often are objects. If we simply put the name of what we want into square brackets, this will be substituted by the full printed name. For example, saying `"You admire [lantern]."` might produce ``You admire candle lantern.`` But this reads oddly – clearly "the" or "a" is missing. So the following substitutions are used very often: > phrase: {phs_a} say "[a (object)]" & say "[an (object)]" > > This text substitution produces the name of the object along with its indefinite article. Example: > > Instead of examining something (called the whatever): > "You can only just make out [a whatever]." > > which might produce ``You can only just make out a lamp-post.``, or ``You can only just make out Trevor.``, or ``You can only just make out some soldiers.`` The `a` or `an` in the wording is replaced by whatever indefinite article applies, if any. > phrase: {phs_A} say "[A (object)]" & say "[An (object)]" > > This text substitution produces the name of the object along with its indefinite article, capitalised. Example: > > Instead of examining something (called the whatever): > "[A whatever] can be made out in the mist." > > which might produce ``A lamp-post can be made out in the mist.``, or ``Trevor can be made out in the mist.``, or ``Some soldiers can be made out in the mist.`` The `A` or `An` in the wording is replaced by whatever indefinite article applies, if any. > phrase: {phs_the} say "[the (object)]" > > This text substitution produces the name of the object along with its definite article. Example: > > Instead of examining something (called the whatever): > "You can only just make out [the whatever]." > > which might produce ``You can only just make out the lamp-post.``, or ``You can only just make out Trevor.``, or ``You can only just make out the soldiers.`` The `the` in the wording is replaced by whatever definite article applies, if any. > phrase: {phs_The} say "[The (object)]" > > This text substitution produces the name of the object along with its definite article, capitalised. Example: > > Instead of examining something (called the whatever): > "[The whatever] may be a trick of the mist." > > which might produce ``The lamp-post may be a trick of the mist.``, or ``Trevor may be a trick of the mist.``, or ``The soldiers may be a trick of the mist.`` The `The` in the wording is replaced by whatever definite article applies, if any. This may not look very useful, because why not simply put "the", or whatever, into the ordinary text? The answer is that there are times when we do not know in advance which object will be involved. For instance, as we shall later see, there is a special value called `the noun` which is the thing to which the player's current command is applied (thus, if the player typed ``TAKE BALL``, it will be the ball). So: After taking something in the Classroom: "You find [a noun]." might produce replies like ``You find a solid rubber ball.``, ``You find an ink-stained blouse.``, ``You find some elastic bands.``, or even ``You find Mr Polycarp.`` (the school's pet hamster, perhaps). ## Text with numbers ^^{text substitutions: numbers} ^^{numbers: displaying} ^^{plurals: displaying} ^^{English: displaying simple plurals} ^^{English: displaying numbers in words} ^^{use options: catalogue: |American dialect} ^^{American dialect+useopt+} ^^{turn count (- number)+glob+} When a numerical value is given in a square-bracketed substitution, it is ordinarily printed out in digits. Thus: "You've been wandering around for [turn count] turns now." might print as ``You've been wandering around for 213 turns now.``, if the story has been played out for exactly that many commands. But if we prefer: > phrase: {phs_numwords} say "[(number) in words]" > > This text substitution writes out the number in English text. Example: > > "You've been wandering around for [turn count in words] turns now." > > might produce ``You've been wandering around for two hundred and thirteen turns now.`` The ``and`` here is natural on one side of the Atlantic but not the other – so with the `Use American dialect.` option in place, it disappears. Either way, though, there is some risk of the following: You've been wandering around for one turns now. We can avoid this using the special substitution: > phrase: {phs_s} say "[s]" > > This text substitution prints a letter ``s`` unless the last number printed (or referred to with `[regarding ...]`) was 1. Example: > > "You've been wandering around for [turn count in words] turn[s] now." > > produces ``... for one turn now.`` or ``... for two turns now.`` as appropriate. Note that it reacts only to numbers, not to other arithmetic values like `times`. This only solves one case, but it's memorable, and the case is one which turns up often. Sometimes it's good to pad numbers out so that they occupy a fixed number of digits: > phrase: {phs_indigits} say "[(number) in (number) digit/digits]" > > This text substitution writes out the number in decimal, with leading zeros as needed so that it will not be shorter than the given number of digits. Example: > > "'Do stop flirting, [agent number in 3 digits],' says M." > > might render the number `7` as ``007`` not ``7``; `1860`, a lesser agent despite the larger number, would come out as ``1860``; and `0` as ``000``. Note that the number is printed _unsigned_, since minus signs don't really make sense when padding with zeros. So `-5` is printed, perhaps unexpectedly, as ``4294967281`` (if the Glulx setting is used, as it is by default). ### See Also - [Numbers, ranges, overflows, and number bases] for how to deal with writing numbers in binary or hexadecimal, and a little more on unsigned numbers. - [Adapting text about the player] for how `[regarding ...]` can be used with `[s]`. ## Text with lists ^^{text substitutions: lists} ^^{lists: displaying} ^^{punctuation: comma: displaying serial comma} ^^{|,: displaying serial comma} ^^{use options: catalogue: |the serial comma} ^^{serial comma+useopt+} ^^{definite articles: when displaying lists} ^^{indefinite articles: when displaying lists} ^^{|a / an / the --> a: in displaying lists} ^^{|an / a / the --> an: in displaying lists} ^^{|the / a / an --> the: in displaying lists} ^^{case sensitivity: in text substitutions with lists} We often want running text to include lists of items. > phrase: {phs_listof} say "[list of (description of objects)]" > > This text substitution produces a list, in sentence form, of everything matching the description. Example: > > "Mr Darcy glares proudly at you. He is wearing [list of things worn by Darcy] and carrying [list of things carried by Darcy]." > > And, if this were from a dramatisation of the novel by Miss Fielding rather than Miss Austen, we might find: > > ```transcript`` > Mr Darcy glares proudly at you. He is wearing a pair of Newcastle United boxer shorts and carrying a self-help book. > ``` > > If the description matches nothing – for instance, if Darcy has empty hands – then ``nothing`` is printed. As with all lists in Inform, the serial comma is only used if the "Use serial comma." option is in force. So by default we would get "a fishing pole, a hook and a sinker", rather than "a fishing pole, a hook, and a sinker". We then need variations to add indefinite or definite articles, and to capitalise the first item. For example, "Mr Darcy impatiently bundles [the list of things carried by Darcy] into your hands and stomps out." might result in ``` transcript Mr Darcy impatiently bundles the self-help book and the Christmas card into your hands and stomps out. ``` > phrase: {phs_alistof} say "[a list of (description of objects)]" > > This text substitution produces a list, in sentence form, of everything matching the description. Each item is prefaced by its indefinite article. Example: > > ``` transcript > a maritime bill of lading, some hemp rope and Falconer's Naval Dictionary > ``` > phrase: {phs_Alistof} say "[A list of (description of objects)]" > > This text substitution produces a list, in sentence form, of everything matching the description. Each item is prefaced by its indefinite article, and the first is capitalised, so that it can be used at the beginning of a sentence. Example: > > ``` transcript > A maritime bill of lading, some hemp rope and Falconer's Naval Dictionary > ``` > phrase: {phs_thelistof} say "[the list of (description of objects)]" > > This text substitution produces a list, in sentence form, of everything matching the description. Each item is prefaced by its definite article. Example: > > ``` transcript > the maritime bill of lading, the hemp rope and Falconer's Naval Dictionary > ``` > phrase: {phs_Thelistof} say "[The list of (description of objects)]" > > This text substitution produces a list, in sentence form, of everything matching the description. Each item is prefaced by its definite article, and the first is capitalised, so that it can be used at the beginning of a sentence. Example: > > ``` transcript > The maritime bill of lading, the hemp rope and Falconer's Naval Dictionary > ``` So much for articles. A more insidious problem comes with something like this: ``` inform7 "The places you can go are [list of rooms]." ``` The trouble is that the list may end up either singular or plural. We might be expecting something like: ``` transcript The places you can go are Old Bailey, Bridget's Flat and TV Centre. ``` But if there is only one room, then the result might be: ``` transcript The places you can go are Bridget's Flat. ``` which is wrong. We can get around this with careful wording and a slightly different substitution: "Nearby [is-are list of rooms]." > phrase: {phs_islistof} say "[is-are list of (description of objects)]" > > This text substitution produces a list, in sentence form, of everything matching the description. The whole list starts with "is" (if there's one item or none) or "are" (more than one). Examples: > > - ``is marlin-spike`` > - ``are maritime bill of lading, hemp rope and Falconer's Naval Dictionary`` > phrase: {phs_isalistof} say "[is-are a list of (description of objects)]" > > This text substitution produces a list, in sentence form, of everything matching the description. Each item is prefaced by its indefinite article, and the whole list starts with ``is`` (if there's one item or none) or ``are`` (more than one). Examples: > > - ``is a marlin-spike`` > - ``are a maritime bill of lading, some hemp rope and Falconer's Naval Dictionary`` > phrase: {phs_isthelistof} say "[is-are the list of (description of objects)]" > > This text substitution produces a list, in sentence form, of everything matching the description. Each item is prefaced by its definite article, and the whole list starts with ``is`` (if there's one item or none) or ``are`` (more than one). Examples: > > - ``is the marlin-spike`` > - ``are the maritime bill of lading, the hemp rope and Falconer's Naval Dictionary`` > phrase: {phs_alistofconts} say "[a list of (description of objects) including contents]" > > This text substitution produces a list, in sentence form, of everything matching the description, noting any contents in brackets. This is really intended only to be used by the Standard Rules. ## Text with variations {PM_SayIfNested} {PM_SayOtherwiseWithoutIf} {PM_SayEndIfWithoutSayIf} ^^{text substitutions: variations} ^^{line breaks} ^^{paragraph breaks <-- breaks} ^^{punctuation: full stop: before text substitutions} ^^{|.: before text substitutions} Text sometimes needs to take different forms in different circumstances. Perhaps it needs an extra sentence if something has happened, or perhaps only one altered word. > phrase: {phs_if} say "[if (a condition)]" > > This text substitution produces no text. It's used only for a side-effect: it says that the text following should be said only if the condition is true. That continues until the end of the text, or until an `"[end if]"` substitution, whichever comes first. If the `"[otherwise]"` and `"[otherwise if]"` substitutions are also present, they allow alternatives to be added in case the condition is false. Example: > > The wine cask is a container. The printed name of the cask is "[if open]broached, empty cask[otherwise]sealed wine cask". > > we find that the cask is described as ``a broached, empty cask`` when open, and ``a sealed wine cask`` when closed. A longer example which begins and ends with fixed text, but has two alternatives in the middle: > > The Customs Wharf is a room. "Amid the bustle of the quayside, [if the cask is open]many eyes stray to your broached cask. [otherwise]nobody takes much notice of a man heaving a cask about. [end if]Sleek gondolas jostle at the plank pier." > phrase: {phs_unless} say "[unless (a condition)]" > > This text substitution produces no text. It's used only for a side-effect: it says that the text following should be said only if the condition is false. That continues until the end of the text, or until an `"[end if]"` substitution, whichever comes first. If the `"[otherwise]"` and `"[otherwise if]"` substitutions are also present, they allow alternatives to be added in case the condition is true. Example: > > The Customs Hall is a room. "With infinite slowness, with ledgers and quill pens, the clerks ruin their eyesight.[unless the player is a woman] They barely even glance in your direction." > phrase: {phs_otherwise} say "[otherwise]" & say "[else]" > > This text substitution produces no text, and can be used only following an `"[if ...]"` or `"[unless ...]"` text substitution. It switches from text which appears if the condition is true, to text which appears if it is false. Example: > > The wine cask is a container. The printed name of the cask is "[if open]broached, empty cask[otherwise]sealed wine cask". > phrase: {phs_endif} say "[end if]" > > This text substitution produces no text, and can be used only to close off a stretch of varying text which begins with `"[if ...]"`. > phrase: {phs_endunless} say "[end unless]" > > This text substitution produces no text, and can be used only to close off a stretch of varying text which begins with `"[unless ...]"`. > phrase: {phs_elseif} say "[otherwise/else if (a condition)]" > > This text substitution produces no text, and can be used only following an `"[if ...]"` or `"[unless ...]"` text substitution. It gives an alternative text to use if the first condition didn't apply, but this one does. Example: > > The wine cask is a container. The printed name of the cask is "[if open]broached, empty cask[otherwise if transparent]sealed cask half-full of sloshing wine[otherwise]sealed wine cask". > phrase: {phs_elseunless} say "[otherwise/else unless (a condition)]" > > This text substitution produces no text, and can be used only following an `"[if ...]"` or `"[unless ...]"` text substitution. It gives an alternative text to use if the first condition didn't apply, and this one is false too. We sometimes need to be careful about the printing of line breaks: The Cell is a room. "Ah, [if unvisited]the unknown cell. [otherwise]the usual cell." This room description has two possible forms: ``Ah, the unknown cell. ``, at first sight, and then ``Ah, the usual cell.`` subsequently. But the second form is rounded off with a line break because the last thing printed is a ``.``, whereas the first form isn't, because it ended with a space. The right thing would have been: The Cell is a room. "Ah, [if unvisited]the unknown cell.[otherwise]the usual cell." allowing no space after ``unknown cell.`` When varying descriptions are being given for kinds of rooms or things, it can be useful to make use of a special value called `item described`, which refers to the particular one being looked at right now. For example: A musical instrument is a kind of thing. The tuba and the xylophone are musical instruments. The description of a musical instrument is usually "An especially shiny, well-tuned [item described]." The tuba now has the description ``An especially shiny, well-tuned tuba.``, and similarly for the xylophone. The `item described` value can similarly be used in any textual property of a room or thing, and in particular can be used with the `initial appearance` and `printed name` properties, which are also forms of description. ## Text with random alternatives {PM_ComplicatedSayStructure} {PM_ComplicatedSayStructure2} {PM_ComplicatedSayStructure5} {PM_ComplicatedSayStructure4} {PM_ComplicatedSayStructure3} ^^{text substitutions: random variations} ^^{text substitutions: sequential variations} ^^{randomness: text variations} Sometimes we would like to provide a little quirky variation in text, especially in messages which will be seen often. We can achieve this with the `[one of]... [or] ... [or] ...` construction. > phrase: {phs_oneof} say "[one of]" > > This text substitution produces no text. It's used only for a side-effect: it switches between a number of alternative texts, which follow it and are divided by `"[or]"` substitutions, according to a strategy given in a closing substitution. Example: > > "You flip the coin. [one of]Heads[or]Tails[purely at random]!" > > Here there are just two alternatives, and the choice made is random. Exactly half of the time the text will be printed as ``You flip the coin. Heads!``; and the other half, ``You flip the coin. Tails!``. But as with tossing coins, nothing's to stop the same outcome coming up time after time just by luck. > phrase: {phs_or} say "[or]" > > This text substitution produces no text, and can be used only in a `"[one of]..."` construction. It divides alternative wordings. Example: > > "You flip the coin. [one of]Heads[or]Tails[purely at random]!" There are seven possible endings, each making the choice of which text to follow in a different way: > phrase: {phs_purelyrandom} say "[purely at random]" > > This text substitution produces no text, and can be used only to end a `"[one of]..."` construction. It indicates that the alternatives are chosen uniformly randomly. > phrase: {phs_thenpurelyrandom} say "[then purely at random]" > > This text substitution produces no text, and can be used only to end a `"[one of]..."` construction. It indicates that the alternatives are chosen in sequence until all have been seen, but that after that they are chosen uniformly randomly. > phrase: {phs_random} say "[at random]" > > This text substitution produces no text, and can be used only to end a `"[one of]..."` construction. It indicates that the alternatives are chosen at random _except that the same choice cannot come up twice running_. This is useful to avoid the deadening effect of repeating the exact same message. Example: > > "The light changes randomly again; now it's [one of]green[or]amber[or]red[at random]." > > Here we can safely say the light "changes", because the new colour cannot be the same as the one printed the last time. > phrase: {phs_thenrandom} say "[then at random]" > > This text substitution produces no text, and can be used only to end a `"[one of]..."` construction. It indicates that the alternatives are chosen in sequence until all have been seen, and then after that, at random except that the same choice cannot come up twice running. Example: > > "Maybe the murderer is [one of]Colonel Mustard[or]Professor Plum[or]Cardinal Cerise[then at random]." > phrase: {phs_sticky} say "[sticky random]" > > This text substitution produces no text, and can be used only to end a `"[one of]..."` construction. It indicates that a random choice is made the first time the text is printed, but that it sticks from there on. Example: > > "The newspaper headline is: [one of]War Casualties[or]Terrorists[or]Banks[sticky random] [one of]Continue To Expand[or]Lose Out[sticky random]." > > Although the newspaper headline will change with each playing, it will not alter during play. > phrase: {phs_decreasing} say "[as decreasingly likely outcomes]" > > This text substitution produces no text, and can be used only to end a `"[one of]..."` construction. It indicates that the alternatives are chosen at random, except that the first is most likely to be chosen, the second is next most likely, and so on down to the rarest at the end. Example: > > "Zorro strides by, [one of]looking purposeful[or]grim-faced[or]deep in thought[or]suppressing a yawn[or]scratching his ribs[or]trying to conceal that he has cut himself shaving[as decreasingly likely outcomes]." > > There are six outcomes here: the first is six times as likely as the last, and those in between are similarly scaled, so Zorro cuts himself shaving only once in 21 tries, while he looks purposeful almost a third of the time. But suppose we want to tuck some useful information in these messages, and we want to be sure that the player will see it. Because all of the above options involve randomness, it's possible that an unlucky player might miss a clue placed into only one variant of the message. One fix for this is to make sure that everything turns up sooner or later: > phrase: {phs_order} say "[in random order]" > > This text substitution produces no text, and can be used only to end a `"[one of]..."` construction. A random order is chosen for the alternative passages of text, and they are used in that order as the text is printed again and again. When one random cycle finishes, a new one begins. The effect is somewhat like the "shuffle album" feature in a music-playing app. Example: > > "You dip into the chapter on [one of]freshwater fish[or]hairless mammals[or]extinct birds[or]amphibians such as the black salamander[in random order]." > > One small restriction: if there are more than 32 variations, purely random choices will be printed, and there will be no guarantee that repeats are prevented. Another fix is to avoid randomness altogether: > phrase: {phs_cycling} say "[cycling]" > > This text substitution produces no text, and can be used only to end a `"[one of]..."` construction. It indicates that the alternatives are used one at a time, in turn: after the last one is reached, we start again from the first. Example: > > "The pundits discuss [one of]the weather[or]world events[or]celebrity gossip[cycling]." > phrase: {phs_stopping} say "[stopping]" > > This text substitution produces no text, and can be used only to end a `"[one of]..."` construction. It indicates that the alternatives are used one at a time, in turn: once the last one is reached, it's used forever after. Example: > > "[one of]The phone rings[or]The phone rings a second time[or]The phone rings again[stopping]." Finally, here's a convenient shorthand for one of the commonest things needed: > phrase: {phs_firsttime} say "[first time]" & say "[only]" > > This pair of text substitutions causes whatever is between them to be printed only the first time the text is printed. Example: > > "The screen door squeaks loudly as when you open it. [first time]Well, you'll get used to it eventually. [only]" > > This is exactly equivalent to > > "The screen door squeaks loudly as when you open it. [one of]Well, you'll get used to it eventually. [or][stopping]"; > > but easier to read. Something to watch out for is that texts are sometimes being printed internally for purposes other than actual output which the player can see, and this is particularly true of names. For example: Before printing the name of the traffic signal: say "[one of]green[or]amber[or]red[cycling] ". This looks good for some purposes, but may not cycle in the sequence expected, and can result in incorrect indefinite articles being printed – ``an red traffic signal``, for example. What's happening is that the name is being printed internally to see whether it begins with a vowel; that prints ``amber traffic signal``, but invisibly to us, and since this does begin with a vowel, ``an`` is visibly printed; then the name is visibly printed, but now it has changed to ``red traffic signal``, and so the result on screen is ``an red traffic signal``. There are many ways to avoid this (for example, to give the traffic signal a state which changes every turn, not every time the name is printed), but it's a trap to look out for. ## Line breaks and paragraph breaks ^^{line breaks} ^^{line breaks: produced by sentence-ending punctuation} ^^{paragraph breaks} ^^{punctuation: full stop: ending sentences with line breaks} ^^{|.: ending sentences with line breaks} Inform controls the flow of text being said so that it will read, to the player, in a natural way. There are two principles: 1) pieces of text ending with full stop, exclamation or question marks will be followed by line breaks; and 2) pieces of text produced by different rules in Inform will be separated by paragraph breaks. The effect is that authors can forget about paragraph spacing most of the time, but the mechanism is not impossible to fool, so text substitutions are provided to override the usual principles. First, to manipulate line breaks: > phrase: {phs_linebreak} say "[line break]" > > This text substitution produces a line break. Example: > > "There is an endless sense of[line break]falling and[line break]falling." > > Line breaks are not paragraph breaks, so the result is: > > ``` transcript > There is an endless sense of > falling and > falling. > ``` > > with no extra vertical spacing between these lines. > phrase: {phs_nolinebreak} say "[no line break]" > > This text substitution produces no text. It's used only for a side-effect: it prevents a line break where Inform might otherwise assume one. Example: > > "The chorus sing [one of]Jerusalem[or]Rule, Britannia![no line break][at random]." > > Here the `"[no line break]"` stops Inform from thinking that the exclamation mark means a sentence ending – it's part of the name of the song _Rule, Britannia!_ (1740). So we get > > The chorus sing Rule, Britannia!. > > with no line break between the ``!`` and ``.``. And similarly for paragraph breaks. Because Inform can be pretty trigger-happy with these, the first need is for a way to stop them: > phrase: {phs_runparaon} say "[run paragraph on]" > > This text substitution produces no text. It's used only for a side-effect: it prevents a paragraph break occurring after the present text is printed, in case Inform might be tempted to place one there. Example: > > Before taking something, say "Very well. [run paragraph on]". > > This allows the reply to, say, ``TAKE ENVELOPE`` to be > > ``` transcript > Very well. Taken. > ``` > > rather than > > ``` transcript > Very well. > > Taken. > ``` > > which is how texts produced by different rules would normally be shown. (It's a traditional printer's term. See _Oldfield's Manual of Typography_, 1892, under "When two paragraphs are required to be made into one, or, in technical language, 'to run on'.") But sometimes we actually want paragraph breaks in unexpected places. One way is to force them outright: > phrase: {phs_parabreak} say "[paragraph break]" > > This text substitution produces a paragraph break. Example: > > "This is not right.[paragraph break]No, something is terribly wrong." > > Paragraph breaks have a little vertical spacing in them, unlike mere line breaks, so the result is: > > ``` transcript > This is not right. > > No, something is terribly wrong. > ``` More subtly, we can give Inform the option: > phrase: {phs_condparabreak} say "[conditional paragraph break]" > > This text substitution either produces a paragraph break, or no text at all. It marks a place where Inform can put a paragraph break if necessary; in effect it simulates what Inform does every time a `before` or similar rule finishes. If there is text already printed, and text then follows on, a paragraph break is made. But if not, nothing is done. This is sometimes useful when producing a large amount of text which changes with the circumstances so that it is hard to predict in advance whether a paragraph break is needed or not. Really finicky authors might possibly want to know this: > phrase: {ph_breakpending} if a paragraph break is pending: > > This condition is true if text has recently been said in such a way that Inform expects to add a paragraph break at the next opportunity (for instance when the present rule ends and another one says something, or when a `"[conditional paragraph break]"` is made). Finally, there are two special sorts of paragraph break for special circumstances. They are mainly used by the Standard Rules, and imitate the textual layout styles of traditional IF. > phrase: {phs_clarifbreak} say "[command clarification break]" > > This text substitution produces a line break, and then also a paragraph break if the text immediately following is a room description brought about by having gone to to a different room and looking around, in which case a line break should be added. In traditional IF, this is used when clarifying what Inform thinks the player intended by a given command. Example: > > say "(first opening [the noun])[command clarification break]"; > > might result in > > ``` transcript > (first opening the valise) > You rummage through the valise for tickets, but find nothing. > ``` > phrase: {phs_runparaonsls} say "[run paragraph on with special look spacing]" > > This text substitution produces no text. It's used only for a side-effect: it indicates that the current printing position does not follow a skipped line, and that further material is expected which will run on from the previous paragraph, but that if no further material turns up then a skipped line would be needed before the next command prompt. (It's very likely that only the Standard Rules will ever need this.) ## Text with type styles ^^{proportional-spaced text} ^^{monospaced text} ^^{fonts: fixed-width / variable-width <-- variable-width <-- fixed-width} ^^{fonts: italic / bold / roman <-- italics <-- bold <-- roman} Inform does not go in for the use of fonts: a work of IF will be rendered with different fonts on different machines anyway, from tiny personal organisers up to huge workstations. However, it does allow for a modest amount of styling. > phrase: {phs_bold} say "[bold type]" > > This text substitution produces no text. It's used only for a side-effect: to make the text following it appear in bold face. `"[roman type]"` should be used to switch back to normal. Example: > > "Jane looked down. [bold type]Danger[roman type], the sign read." > phrase: {phs_italic} say "[italic type]" > > This text substitution produces no text. It's used only for a side-effect: to make the text following it appear in italics. `"[roman type]"` should be used to switch back to normal. Example: > > "This is [italic type]very suspicious[roman type], said Peter." > phrase: {phs_roman} say "[roman type]" > > This text substitution produces no text. It's used only for a side-effect: to return to ordinary Roman type after a previous use of `"[bold type]"` or `"[italic type]"`. but there is one other effect we can employ: > phrase: {phs_fixedspacing} say "[fixed letter spacing]" > > This text substitution produces no text. It's used only for a side-effect: to make the text following it appear with fixed letter spacing. In variable letter spacing, a lower case "m" is much wider than an "l", which is natural to the eye since it has been printing practice since the Renaissance. Fixed letter spacing is more like typewriting, and it is best used to reproduce typewritten text or printed notices; it can also be convenient for making simple diagrams. Example: > > "On the door is written: [fixed letter spacing]J45--O-O-O[variable letter spacing]." > phrase: {phs_varspacing} say "[variable letter spacing]" > > This text substitution produces no text. It's used only for a side-effect: to return to ordinary letter spacing after a previous use of `"[fixed letter spacing]"`. Whichever effect we use, we should be careful to ensure that we return to normal – roman type and variable letter spacing – after any specially-treated text has been printed. Combining these effects (for, say, bold fixed-spaced lettering) is not guaranteed to work, though on some platforms it will. ## Accented letters ^^{characters (letters): accented and exotic letters and symbols}^^^{characters (letters) <-- letters <-- accented letters}^^^{characters (letters) <-- symbols} Inform 7 is infused by the English language, so it's a challenge using it to write a work of IF in any other language. (With that said, extensions do exist which have made considerable progress on this problem: nil desperandum.) But even a book in English contains occasional quotations or words borrowed from other tongues, so we are going to need more than plain A to Z. The world has a bewildering range of letters, accents, diacritics, markers and signs. Inform tries to support the widest range possible, but a degree of caution is needed when using those not in common use in America or Europe, because players might not have the necessary fonts installed on their computers: few players will have an Ethiopian font, for example. (a) **Definitely safe to use.** Inform's highest level of support is for the letters found on a typical English typewriter keyboard, including both the $ and £ signs (but not the Yen or Euro symbols ¥ and €), and in addition the Spanish inverted punctuation marks ¡, ¿, and the following extended letter forms: Lower case | Upper case ----------------- | ---------- ä, á, à, ã, å, â | Ä, Á, À, Ã, Å,  ë, é, è, ê | Ë, É, È, Ê ï, í, ì, î | Ï, Í, Ì, Î ö, ó, ò, õ, ø, ô | Ö, Ó, Ò, Õ, Ø, Ô ü, ú, ù, û | Ü, Ú, Ù, Û ÿ, ý | Ý but not Ÿ ñ | Ñ ç | Ç æ but not œ | Æ but not Œ ß | no upper case form: use SS These characters can be typed directly into the Source panel, and can be used outside quotation marks. We can write `The Église is a room.`, for instance. (b) **Characters which can safely be used, but will be simplified.** As it reads in the text, Inform silently converts all kinds of dash (en-rules, em-rules, etc.) to simple hyphens; converts the multiplication symbol to a lower case "x"; converts all kinds of space other than tabs (em-spaces, non-breaking spaces, etc.) to simple spaces, and all kinds of quotation marks to "straight" (non-smart) marks. (c) **Characters which can be used provided they are in quoted text, and which will probably but not certainly be visible to the player**. All other Latin letter-forms, including the œ ligature, East European forms such as ő, ş and ž, and Portuguese forms such as ũ; the Greek and Cyrillic alphabets, with their associated variants and accents; and the principal currency symbols, such as € and ¥. Caution should be used with such characters outside of quotation marks: the outcome may depend on the format Inform is compiling to. For example, `Łodz Churchyard is a room.`, which uses the Polish `Ł`, works well enough if the story uses the Glulx setting (which is the default), but not the Z-machine. Should that be necessary, the following provides a way to get the `Ł` safely into quotation marks: The Churchyard is a room. The printed name of the Churchyard is "Łodz Churchyard". It should also be remembered that the player may not be able to type such characters in commands, or may have difficulty working out how to. Still, recent improvements to the Glulx virtual machine, which is used by Inform by default to run stories, allow this sort of thing to work: Understand "βράχος" as the rock. Understand "παίρνω [things]" as taking. Or even, since emoji are now very widely supported: Café Emoji is a room. A bagel is here. The bagel is edible. Understand "🥯" as the bagel. Understand "🍽️ [thing]" as eating. Test me with "🍽️ 🥯". If the Z-machine setting is used, this _definitely_ will not work. (d) **Characters which might work in quoted text, or might not**. The Arabic and Hebrew alphabets are fairly likely to be available, but right-to-left support for them is another matter; miscellaneous symbols are sometimes legible to the player, sometimes not. Other alphabets are chancier still. (If a work of IF depends on these being visible, it may be necessary to instruct players to use specific interpreters, or to test that the effect looks right in multiple browsers on each of MacOS, Windows and Linux.) ## Unicode characters {PM_SayUnicode} {PM_MidTextUnicode} {PM_UnicodeOutOfRange} ^^{characters (letters): Unicode (arbitrary symbols)} ^^{characters (letters) <-- Unicode}^^^{+tosay+"[(unicode character)]" --> unicode character} As we have seen, Inform allows us to type a wide range of characters into the source text, although the more exotic ones may only appear inside quotation marks. But they become more and more difficult to type as they become more obscure. Inform therefore allows us to describe a letter using a text substitution rather than typing it directly. Unicode characters can be named (or numbered) directly in text. For example: "[unicode U+0141]odz Churchyard" produces a Polish slashed L, that is, prints as ``Łodz Churchyard``. The notation `unicode U+0141` uses hexadecimal digits, and actually refers to the character whose number is 321, because 321 in base 16 is 141. (Inform would also have accepted `unicode 321` in decimal, but it's far more usual for Unicode to be quoted in hexadecimal.) Characters can also be named as well as numbered: "[unicode Latin capital letter L with stroke]odz Churchyard" The Unicode standard assigns character numbers to essentially every marking used in text from any human language: its full range is enormous. This means, for instance, that we can write text such as: "Dr Zarkov unveils the new [unicode Hebrew letter alef] Nought drive." "Omar plays 4[unicode black spade suit] with an air of triumph." Admittedly, character names can get a little verbose: "[unicode Greek small letter omega with psili and perispomeni and ypogegrammeni]" Occasionally, the presence of words like "with" in the names of Unicode characters can cause ambiguities — for example, in this sentence: The secret sign is initially unicode Latin capital letter L with stroke. This can be avoided by using brackets around the name, to make clear how the sentence should be read: The secret sign is initially unicode (Latin capital letter L with stroke). Inform can "only" handle codes in the range `unicode U+20` to `unicode U+1FFFF`, that is, 32 to 131071 in decimal, and note that if the project Settings are to compile to the Z-machine, this range stops at `unicode U+FFFF`: thus many emoji characters – say, `unicode fish cake with swirl design` – can only be used if the story will compile to Glulx or another modern target. But by default, stories are compiled the modern way, so this should not be a problem in practice. There are far too many possible names to list here: formally, any character name in the Basic Multilingual Plane or the Supplementary Multilingual Plane of version 15.0.0 of the Unicode standard can be used. Still another alternative is to write `unicode "C"`: this is no use inside a text substitution because the double-quotation marks can't be used there, but something like: The secret sign is initially unicode "☣". ...will work fine. `unicode "☣"`, `unicode U+2623`, `unicode 9763` and `unicode Biohazard Sign` are all ways to write the same value, which has the kind `unicode character`. > [!CAUTION] > Before getting carried away, we should remember the hazards: Inform allows us to type, say, `unicode Saturn` (an astrological sign) but it appears only as a black square if the resulting story is played using a font which lacks the relevant sign. (Another issue is that the fixed letter spacing font, such as used in the status line, may not contain all the characters that the font of the main text contains.) To write something with truly outré characters is therefore a little chancy. Inform also sometimes deals with Unicode characters when reading the keyboard. If the player types an `A`, that comes back as its everyday Unicode value, 65, or `Unicode "A"`. But what if the player types the f3 function key, or the page down button? Inform then needs codes to represent those not-really-a-character-at-all characters, and the codes it uses are as follows: Inform name | Unicode value | Notes --------------- | ---------------- | ----------------- `delete key` | `unicode U+0008` | Some people call this "backspace", Inform does not `tab key` | `unicode U+0009` | `return key` | `unicode U+000A` | Some people call this "enter", Inform does not `escape key` | `unicode U+001B` | `left key` | `unicode U+2190` | Same as `unicode leftwards arrow` `right key` | `unicode U+2192` | Same as `unicode rightwards arrow` `up key` | `unicode U+2191` | Same as `unicode upwards arrow` `down key` | `unicode U+2193` | Same as `unicode downwards arrow` `home key` | `unicode U+21F1` | Same as `unicode north west arrow to corner` `end key` | `unicode U+21F2` | Same as `unicode south east arrow to corner` `page up key` | `unicode U+21DE` | Same as `unicode upwards arrow with double stroke` `page down key` | `unicode U+21DF` | Same as `unicode downwards arrow with double stroke` `f1 key` | `unicode U+EF01` | This is in the Unicode Private Use area `f2 key` | `unicode U+EF02` | This is in the Unicode Private Use area `f3 key` | `unicode U+EF03` | This is in the Unicode Private Use area `f4 key` | `unicode U+EF04` | This is in the Unicode Private Use area `f5 key` | `unicode U+EF05` | This is in the Unicode Private Use area `f6 key` | `unicode U+EF06` | This is in the Unicode Private Use area `f7 key` | `unicode U+EF07` | This is in the Unicode Private Use area `f8 key` | `unicode U+EF08` | This is in the Unicode Private Use area `f9 key` | `unicode U+EF09` | This is in the Unicode Private Use area `f10 key` | `unicode U+EF0A` | This is in the Unicode Private Use area `f11 key` | `unicode U+EF0B` | This is in the Unicode Private Use area `f12 key` | `unicode U+EF0C` | This is in the Unicode Private Use area `unknown key` | `unicode U+FFFD` | Same as `unicode replacement character`: used only for damaged or unreadable input Some of these characters (in particular delete, tab, escape, the function keys and the unknown key value) can only safely be used for input, not output. If said, they are likely to print back as nothing at all, or a square, or question mark. Others can in principle be printed back, but probably not in a useful way. `say unicode left key` does not move the cursor backwards on the screen: if it does anything, it draws a small leftward arrow. All in all, these named values are best used for input, not output. > [!IMPORTANT] > At one time, Inform could only use named Unicode values in a story which had first included an extension: > > Include Unicode Character Names by Graham Nelson. > Include Unicode Full Character Names by Graham Nelson. > > This is no longer the case: no such inclusion need now be made, and indeed, those extensions have been removed from Inform as redundant. ## Displaying quotations ^^{quotations: displaying in boxes} ^^{boxed quotations} ^^{Inform 6 equivalent: |box} A feature of Inform now best avoided is that, in a limited way and only on a narrow set of platforms now rarely used, it can display a message in a sort of floating window over the main text. This is called a _boxed quotation_ for historical reasons, and Inform allows one to be produced. But time has moved on from the simple terminal emulators which enabled crude text effects like this, and now boxed quotations will either be missing altogether or will look ugly on almost any modern platform. Text is normally printed in between the typed commands of the player, rolling upwards from the bottom of the screen, as if a dialogue is being typed by an old-fashioned teletype. But it can also be displayed in a bolder way, floating above the main text, and this is sometimes used to display quotations. > phrase: {ph_boxed} display the/-- boxed quotation (text) > > This phrase displays the given text on screen in an overlaid box. For reasons to do with the way such quotations are plotted onto the screen, their text is treated literally: no substitutions in square brackets are obeyed, and no non-Latin characters can be used in it. The quotation will only ever appear once, regardless of the number of times the `display the boxed quotation ...` phrase is reached. Rather than being shown immediately – and thus, probably, scrolling away before it can be seen – the display is held back until the next command prompt is shown to the player. Example: > > After looking in the Wabe, display the boxed quotation > "And 'the wabe' is the grass-plot round > a sun-dial, I suppose? said Alice, > surprised at her own ingenuity. > Of course it is. It's called 'wabe,' > you know, because it goes a long way > before it, and a long way behind it — > — Lewis Carroll". This was the original example used in *Trinity*, by ^{@Brian Moriarty}, which invented the idea. A player exploring Kensington Gardens comes upon a location enigmatically called The Wabe; and by way of explanation, this quotation pops up. Charming in the 1980s, the feature should probably not have been revived. ^^{@Lewis Carroll} ## Making new substitutions ^^{text substitutions: defining} ^^{defining: text substitutions} ^^{to say (substitution)...+assert+} ^^{case sensitivity: in text substitutions} If we have some textual effect which needs to occur in several different messages, we might want to create a new text substitution for it. For instance: The Missile Base is a room. "[security notice]Seems to be a futuristic missile base." M's Office is east of the Missile Base. "[security notice]Admiral Sir M.- M.- glares up from his desk." To say security notice: say "This area is a Prohibited Place within the meaning of the Official Secrets Act 1939. " This is only the tip of the iceberg in how to define ways to do things using `To...`, as we shall see. The definition makes `say the security notice` a new phrase known to Inform. A text substitution is exactly a phrase whose name begins with `say` (well – except for the `say` phrase itself), so the effect is that `"[security notice]"` is a new text substitution. Several of the examples in this chapter make use of this trick. Inform often ignores the casing of the text it reads, but sometimes uses it as a clue to meaning. We have already seen that `"[an item]"` and `"[An item]"` produce different results, for instance. Similarly, it's possible to define two text substitutions which are the same except for the initial casing. We might write: To say Security Notice: say "THIS AREA IS A PROHIBITED PLACE WITHIN THE MEANING OF THE OFFICIAL SECRETS ACT 1939. " And now Inform will act on `"[Security Notice]"` differently from `"[security notice]"`. ### See Also - [The phrasebook] for other forms of phrase besides To say.... # Generalisations ## Giving general descriptions {DESCRIPTIONS} ^^{descriptions (references to things)} ^^{things+kind+: references to (descriptions)} ^^{+tosay+"[list of (description)]" --> list of} ^^{+to+say "[list of (description)]"} One of the reasons natural languages like English are so concise and expressive is that they can describe things in so many ways. As well as being literal about exactly what we mean — "the Z-ray beam locator" — we can be vague, and talk about "a switched on device in the Laboratory", or for that matter just "a device". We can even talk about "three devices". People who study languages call these "noun phrases", but Inform calls them _descriptions_. They allow us to give general instructions in a highly flexible way. Note that this is a quite different meaning of the word from the `description` property of a thing. This chapter is all about how we describe values when we're writing source text, not about how the story describes things to the eventual player when it runs. The simplest descriptions consist of a noun alone. Some refer to single things (`lantern`, or `wine cask`), others to kinds of thing (`dead end` or `container`). But we have also seen adjectives alone: The oaken desk is fixed in place. Here, `fixed in place` is a description which, to Inform's simple-minded grammar, is a single adjective. And of course adjectives and nouns can be combined: The cargo trunk is an openable container. The description `openable container` consists of the noun `container`, meaning a kind of thing, and the adjective `openable`, which means one of the two possible states of an either/or property held by that thing. As the next chapter, [Basic Actions] will show, rules also make great use of descriptions: Instead of throwing something at a closed openable door, say "Or you could just use the handle like anyone else, of course." That time, `something` and `closed openable door` were both descriptions. We have already seen a text substitution for saying the list of everything matching a given description, as in this example, where the description is `things in the basket`: "You look down at [the list of things in the basket]." It's also sometimes convenient to count the number of eligible values: > phrase: {ph_numberof} number of (description of values) ... number > > This phrase counts the number of values matching the description, which may of course be 0. Example: > > number of open doors > > produces the number of doors, anywhere in the model world, which are currently open. A Problem message is produced if the number is potentially infinite, or impractical to count: for instance, Inform rejects `number of odd numbers`. It is because descriptions are so widely useful that they deserve a chapter of their own, and this is it. ## Adjectives and nouns ^^{descriptions (references to things): syntax} ^^{nouns: in descriptions} ^^{adjectives: in descriptions} ^^{quantifiers: existential} ^^{existence: descriptions of any such thing} ^^{pronouns: |something, anything...} ^^{|someone: in descriptions} ^^{|something: in descriptions} ^^{(somewhere), in descriptions+sourcepart+} ^^{(anyone), in descriptions+sourcepart+} ^^{(anything), in descriptions+sourcepart+} ^^{(anywhere), in descriptions+sourcepart+} ^^{(somebody), in descriptions+sourcepart+} ^^{(anybody), in descriptions+sourcepart+} Descriptions can contain a noun, but need not, and can contain any number of adjectives. There can also be so-called determiners, but those tend to say which things matching the description are meant, rather than what it means to match. For example: description | determiner | adjective(s) | noun ------------------------ | ---------- | ---------------- | ---- `supporter` | | | supporter `closed` | | closed | `a closed openable door` | a | closed, openable | door `the open wine cask` | the | open | wine cask `something portable` | a | portable | thing `six containers` | six | | container Inform does not allow more than one noun in the same description, as English very occasionally does for emphasis, as in "the man Jenkins". Nouns divide into common nouns, which we use for kinds like `door`, and proper nouns, which are specific values like `wine cask`. Composite words such as `something` are best understood by breaking them up: for example `something` is `some thing`, so is actually a reference to the kind `thing`. description | determiner | adjective(s) | noun ------------------------ | ---------- | ---------------- | ---- `something` | a | | thing `anything` | a | | thing `someone` | a | | person `anyone` | a | | person `somebody` | a | | person `anybody` | a | | person `somewhere` | a | | room `anywhere` | a | | room As can be seen, these eight composite nouns really only have three different meanings between them. So for instance `anybody male` or `somewhere dark` are valid descriptions. These eight nouns are unusual in being allowed to come at the front of a description: nouns are usually expected to be at the end. Inform also understands `nothing`, `nowhere`, `nobody`, `no-one` and even `no one`, which in a sense are opposites of `something` and the like, but for now we'll look at descriptions of things which do exist rather than don't. ## Defining new adjectives {PM_DefinitionBadCondition} {PM_DefinitionWithoutCondition} {PM_AdjDomainSlippery} {PM_AdjDomainSurreal} {PM_AdjDomainUnknown} {PM_ArticleAsAdjective} ^^{adjectives} ^^{properties: value properties: used as adjectives} ^^{value properties: used as adjectives} ^^{properties: either/or properties: used as adjectives} ^^{either/or properties: used as adjectives} ^^{adjectives: defining} ^^{defining: adjectives} ^^{definition+assert+} ^^{(rather than), in defining adjectives+sourcepart+} ^^{|called: in defining adjectives} ^^{descriptions (references to things): defining adjectives for descriptions} ^^{punctuation: colon} ^^{|:} We have already seen one way to make new adjectives: they automatically come into being when new properties are created. For example: A door can be creaky or quiet. This creates adjectives `creaky` and `quiet`. Or alternatively: Texture is a kind of value. The textures are rough, stubbly and smooth. Everything has a texture. makes `rough`, `stubbly` and `smooth` adjectives. That last sentence `Everything has a texture` was essential, because without it Inform would not know that these words could meaningfully be applied to things. Then they would only be nouns, not adjectives. But not all adjectives refer to property values. For example, the built-in adjective `even` as applied to a `number` value is not a property: when Inform wants to know whether a number is even, it applies a _definition_. And we can create that sort of adjective, too. Suppose we want to coin a word for supporters currently supporting something. We can do so with the following sentence: Definition: A supporter is occupied if something is on it. Note the colon, which is essential, and the usage of `it` in the definition part to refer to the object in question. (For this purpose we would write `it` even if we were defining a term about, say, a woman instead of a supporter, so that `she` or `her` might seem more appropriate – but see below.) This creates the adjective `occupied`, and gives it a definition valid for supporters. That restriction on validity means that non-supporters would always fail the description `something occupied`; which might be unfortunate if we wanted to talk about rooms being occupied. We could give a second definition thus: Definition: A room is occupied if a person is in it. These are entirely different senses of the word `occupied` – a mantelpiece is occupied if an invitation is on it, but for a drawing room to be occupied there must be human presence – and Inform applies whichever sense is relevant when deciding whether or not a given object is `occupied`. Often, though not always, we also want to give a name to the opposite possibility. We can do that as follows: Definition: A room is occupied rather than unoccupied if a person is in it. The `rather than...` part of the definition is optional, but it saves having to write a boringly similar definition of `unoccupied` out in longhand. (Note that Inform does not guess the meaning of `unoccupied` unless it has been explicitly told it. Such guesses are too risky, when so many "un-" words fail to conform to this pattern: "unified", "uncle", "ungulate" and so on.) Newly defined adjectives cannot be used when creating things, because they are not explicit enough. Inform could not satisfy: The Ballroom is occupied. The bucket is a large container. because there is not enough information: by whom is the Ballroom occupied? How large, exactly? On the other hand, newly defined adjectives are very helpful in conditions and for rules, as we shall see later on. It is occasionally clumsy having to refer to the subject of a definition using `it`. We can avoid this and give the definition better legibility by supplying a name instead. For instance: Definition: a direction (called thataway) is viable if the room thataway from the location is a room. which is a good deal easier to read than Definition: a direction is viable if the room it from the location is a room. ### See Also - [New conditions, new adjectives] for giving more extensive definitions of new adjectives, using phrases. ## Defining adjectives for values ^^{adjectives: for values} ^^{defining: adjectives: for values} ^^{definition+assert+: for values} ^^{empty / non-empty+adj+: for texts} ^^{non-empty / empty+adj+: for texts} ^^{text: empty / non-empty+adj+} ^^{even / odd (number)+adj+} ^^{odd / even (number)+adj+} ^^{positive / negative (number)+adj+} ^^{negative / positive (number)+adj+} ^^{descriptions (references to things): adjectives for values} In general, any noun can have adjectives applied to it, and this means that values can have adjectives just as objects can. We have already seen that they can (in some cases, at least) have either/or properties, and this gives them adjectives just as for objects. But we can also write out definitions which apply to values: Definition: A number is round if the remainder after dividing it by 10 is 0. Definition: A time is late rather than early if it is at least 8 PM. That makes the numbers 20 and 170 but not 37 meet the description `a round number`, and the times 8 PM and 11:23 PM but not 9 AM meet the description `a late time`. Because they come up fairly often, Inform contains several adjectives for numbers built in: - `positive` - greater than zero (but not 0 itself) - `negative` - less than zero (but not 0 itself) - `even` - divisible exactly by 2, like ..., -4, -2, 0, 2, 4, ... - `odd` - not divisible exactly by 2, like ..., -5, -3, -1, 1, 3, 5, ... Similarly, two useful adjectives are built in to talk about text: - `empty` - the text `""`, with no characters in it, not even spaces - `non-empty` - any text which does have at least one character in Note that `T is empty` is not quite same test as `T is ""`. If the value being looked at is a text substitution like `"[ingredient]"` in its unsubstituted form, and it just so happens that at the moment the `ingredient` substitution would produce no characters of text, then `"[ingredient]" is empty` would be false, even though `"[ingredient]" is ""` would be true: the difference is that the comparison made by `is` substitutes in before it makes the test, whereas `empty` tests without making substitutions, so it reads `"[ingredient]"` as potentially having content and therefore not being empty. See [Making new text with text substitutions] for more on the subtle difference between the substituted and unsubsituted form of a text substitution. Adjectives can have multiple definitions and, as long as each applies to a different sort of noun, there will be no problem. We could write: A thing can be round, square or funny-shaped. A container can be odd or ordinary. And these definitions of `round` and `odd` will not interfere with the ones applying to numbers, because Inform can always look at the noun to see which definition is meant in any given case. For instance, if the score is round, ... must mean `round` in the sense of numbers, because the score is a number. Inform itself makes good use of this; `empty` also has meanings applying to rulebooks, lists and activities, for instance, as will be seen later. Although it's more usual to give a definition to apply to a whole kind, we can actually give a specific definition to apply to just a single object or named value. For example: A colour is a kind of value. The colours are red, green and blue. Definition: red is subtle if the player is female. Definition: a colour is subtle if it is blue. The first definition of `subtle` takes precedence, of course, since it has the more specific domain – it applies only to red. The effect of this is that, if the player's female, the subtle colours are red and blue; if not, just blue. ## Whereabouts on a scale? ^^{numbers: adjectives describing magnitude} ^^{adjectives: for numeric quantities} ^^{defining: adjectives: for numeric quantities} ^^{definition+assert+: for numeric quantities} ^^{descriptions (references to things): adjectives for magnitude} ^^{properties: numeric magnitudes, adjectives for} ^^{value properties: numeric magnitudes, adjectives for} ^^{|or more / less} Adjectives are often used in English to give a sense of where something is on a sliding scale. We talk about "a tall man" and "a short man", but without meaning that all men are either tall or short. If pushed, we might say that tall means about 6 feet and up, short means about 5 feet 6 and down, but we more often compare one person's height against another's. Inform allows us to use adjectives in the same way. For example, every container has a number called its `carrying capacity`. We can define: Definition: A container is huge if its carrying capacity is 20 or more. Definition: A container is large if its carrying capacity is 10 or more. Definition: A container is standard if its carrying capacity is 7. Definition: A container is small if its carrying capacity is 5 or less. These definitions are similar to those in the previous section, but have a very specific (and strictly enforced) shape to them. The adjective must be a single word. We have to say `its` (i.e., of it), not the ungrammatical `it's`; we have to specify a property, and a literal value of it, and we must either give an exact value or else conclude with `or more` or `or less`. If we create something with one of these properties: The basket is a large container in the Shop. The thimble is a small container in the Shop. The matchbox is a standard container in the Shop. then they will have the most moderate values they can have, that is, the basket will have carrying capacity 10 and the thimble 5 (and of course the matchbox 7). Both of the following tests will then fail: if the basket is huge ... if the basket is a small container ... because the basket is neither huge nor small, but somewhere in between. Sometimes the meaning of adjectives must depend on their context, as we see from the following example, where we assess heights in inches: A person has a number called height. Definition: A man is tall if his height is 72 or more. Definition: A woman is tall if her height is 68 or more. Inform then judges whether someone is or is not `tall` using different standards for men and for women, and In the Shop are a tall man and a tall woman. creates a man 72 inches tall and a woman 68 inches tall. ## Comparatives {PM_ComparativeMisapplied} {PM_GradingCalled} {PM_GradingMisphrased} {PM_GradingNonLiteral} {PM_GradingUnknownProperty} {PM_GradingUnless} {PM_GradingWrongKOV} {PM_MultiwordGrading} ^^{numbers: adjectives comparing magnitude} ^^{adjectives: for numeric quantities} ^^{defining: adjectives: for numeric quantities} ^^{comparisons: of numbers using adjectives} ^^{same (property) as+sourcearg+} ^^{definition+assert+: for numeric quantities} ^^{descriptions (references to things): comparative adjectives} ^^{properties: numeric comparatives, adjectives for} ^^{value properties: numeric comparatives, adjectives for} ^^{|or more / less} The special definitions in the previous section have a further effect. When we define: Definition: A container is large if its carrying capacity is 10 or more. we not only say how to test if something is large (see if its capacity is at least 10) and how to create something large (give it a capacity of exactly 10), we also create a new form of comparison. Thus, if the basket is larger than the thimble ... if the thimble is not larger than the basket ... are both true. If we also define `huge` and `small`, as in the previous section, we also get comparisons `huger than` and `smaller than`. Note that `huger than` has exactly the same meaning as `larger than`: we can use whichever wording seems more natural. (For bacilli, for instance, we would probably not say `huger than`, even though the meaning would be unambiguous.) We can also compare two things to see if they share the same value of a property. For instance, to go back to the heights example, once we define `tall` and `short`, we get that exactly one of the following will be true: if Adam is taller than Eve ... if Adam is the same height as Eve ... if Adam is shorter than Eve ... Though it will not always seem natural wording, we can use the comparison `the same P as` for any property P which has a value. Do we think "if the basket is the same carrying capacity as the thimble" is good English? Maybe, maybe not. But we are always at liberty to spell things out in full: if the carrying capacity of the basket is the carrying capacity of the thimble ... ## Superlatives ^^{numbers: adjectives comparing magnitude} ^^{adjectives: for numeric quantities} ^^{defining: adjectives: for numeric quantities} ^^{superlatives: of numbers using adjectives} ^^{English: simple superlative forms} ^^{definition+assert+: for numeric quantities} ^^{descriptions (references to things): superlative adjectives} ^^{properties: numeric superlatives, adjectives for} ^^{value properties: numeric superlatives, adjectives for} ^^{|or more / less} Lastly, if we define an adjective in this calibrating way, we also automatically benefit from the use of the superlative form. That is, if we define Definition: A container is large if its carrying capacity is 10 or more. Definition: A container is small if its carrying capacity is 5 or less. then we can talk about things like this: - `the largest container` - `the smallest open container` Though we should be careful, in the second case, because we might get nothing: maybe all the containers are closed at the moment this is used. And in general there might be several equally large largest containers, in which case we should not rely on getting any particular one of those rather than another. Note that Inform constructs comparatives and superlatives by a pretty simplistic system. If we want to use these forms for an adjective expressing the relatively large size of a room, we had better go with "roomy" (roomier, roomiest) – not "spacious" (spaciouser, spaciousest). ## Which and who ^^{descriptions (references to things): complex phrases} ^^{(which), in description clauses+sourcepart+} ^^{(who), in description clauses+sourcepart+} ^^{(that), in description clauses+sourcepart+} ^^{descriptions (references to things): relative} A description can not only talk about things in terms of themselves, but also in terms of their relationships to the rest of the world. For instance, - `an open container on the table` - `a woman inside a lighted room` - `an animal carried by a man` - `a woman taller than Mark` - `something worn by somebody` are all valid descriptions. These are really abbreviations, having missed out the words `which is` or `who is`, as appropriate: - `an open container which is on the table` - `a woman who is inside a lighted room` - `an animal which is carried by a man` - `a woman who is taller than Mark` - `something which is worn by somebody` and indeed those are also valid descriptions. The other sentence verbs can all be used here, too. So for instance: - `a man who does not wear anything` - `something which supports something` And sometimes we should spell out `who is` regardless: - `a man who is not Sherlock Holmes` Since these clauses can be attached to the end of any valid description, descriptions can grow longer still: - `something worn by a woman who is in a dark room` Pedants who flinch when `which` is used to introduce a restrictive clause are welcome to use `that` instead. ## Existence and there {PM_OutOfPlay} ^^{(there is), declaring existence+sourcepart+} ^^{(nobody), testing that no such person exists+sourcepart+} ^^{|nothing: testing that no such thing exists} ^^{descriptions (references to things): existence} ^^{descriptions (references to things): non-existence} ^^{existence: testing that such a thing exists} ^^{non-existence: testing that no such thing exists} ^^{non-existence: starting things out of play} ^^{things+kind+: starting out of play} ^^{out of play} "There" is a curious word in English, which mostly refers to some place which is being talked about – but which can sometimes mean the whole world. In ^{@Ian Fleming}'s novel _From Russia With Love_ (1957), a chapter narrating a committee meeting of SMERSH officers in Istanbul ends with one of the Russians saying: > There is a man called Bond. What does this "there" mean? It really just means that Bond exists. In fact, he's watching the meeting through a concealed periscope, but the SMERSH general doesn't know that. All he is saying is that Bond is out there somewhere, and is not imaginary, or dead. Inform also allows `there is` (or `there are`) to talk about what exists, or does not. This is especially useful if, for some reason, we don't want to give a name to something. For example: There is a door in the Summerhouse. Another reason might be that we want to create something but not put it anywhere. If Inform reads the sentence: There is a man called Bond. then it creates a man, gives him the name Bond, but places him initially off-stage – not in any room, that is, but available to be brought into play later on, like an actor who is not needed until Act II. `There` also provides a useful way to test what exists: if there is a woman in the Summerhouse, ... Or even: if there is a woman, ... which will be true if the model world contains even a single woman, on-stage or off. The alternative `there are` can also be used: if there are women in the Summerhouse, ... but note that this does not necessarily imply more than one woman is present, despite the plural. If we want that, we have to be more explicit: if there is more than one woman in the Summerhouse, ... or, of course, we needn't use `there is` at all: if more than one woman is in the Summerhouse, ... And we can also test non-existence: if there is nobody in the Summerhouse, ... if there is nothing on the mantelpiece, ... ## A word about in ^^{containment+rel+} ^^{containment+relcat+} ^^{regional-containment+rel+} ^^{regional-containment+relcat+} ^^{indirect containment} ^^{containment+rel+: indirect} ^^{regions+kind+: things in regions} ^^{regions+kind+: regional containment} ^^{rooms+kind+: grouping into regions} ^^{map region of (room)+prop+} What does "in" mean? The literal answer is that it means containment, that is, `X is in Y` means that Y contains X. Containment is an idea which is itself a little complicated to unravel, though. **Meaning 1.** Usually, if X is "in" Y then this is because Y is either a room or a container, and X is immediately inside it. A croquet ball is "in" a croquet box, which is "in" the Summerhouse. This is the standard meaning, and is the one which happens if we write something like: The croquet ball is in the box. or if we ask a question like: if the croquet box is in the Summerhouse, ... This kind of "in" talks only about direct containment. If we ask if the croquet ball is in the Summerhouse, ... then the answer is that it isn't – it is in the box which is itself in the Summerhouse, but that's not the same thing. This is almost always the meaning of "in" that we intend. This is only one of a number of relationships between objects – there are also `part of`, `on`, `worn by` and `carried by`, for example. If we have The bird feed is on the sundial. ...then `if the bird feed is in the sundial` won't be true: the relationship here is one called support (being on top of, in effect), not containment. But there's no confusion because `on` and `in` are different words, so it's no problem that they have different meanings. **Meaning 2.** Much less common. If X is `in` Y and Y is a region, then the meaning is slightly different. Suppose the Garden Area is a region, and contains several rooms – the Croquet Lawn, the Terrace and so on. Then if the croquet box is in the Garden Area, ... if the bird feed is in the Garden Area, ... if the Terrace is in the Garden Area, ... are all true. This seems very natural, but in fact is quite different from the behaviour of "in" for non-regions. It allows rooms (and even other regions) to be "in" a region, and it allows indirect containment. Note also that `if the Terrace is in R`, where `R` is a region, this is not the same thing as asking `if the map region of the Terrace is R`. The `map region` of a room is the region it is immediately in (if any). If the Terrace is in a region called Garden Area which in turn is in the region Middlesex, then `if the Terrace is in Middlesex` is true, but `if the map region of the Terrace is Middlesex` is false. **How Inform decides.** So which meaning does Inform use, and when? Since these two meanings are so different, it clearly matters. The answer is that meaning 1 is always the meaning of `X is in Y` unless Y is explicitly the name of a region. Thus: if the croquet box is in the Garden Area, ... is meaning 2, because `Garden Area` is the name of a region. That seems fair enough, but values are indeed sometimes given names (becoming "variables", or values "that vary"). Suppose `mystery value` is a name for a value which is an object, but which has different identities at different times. Then Inform reads if the croquet box is in the mystery value, ... as meaning 1, because whatever `mystery value` is, it isn't explicitly a region name, even if from time to time it might happen to be equal to a region. That sometimes makes meaning 2 difficult to express. If we ever need it, and this is fairly rare, we can write it like so: if the croquet box is regionally in the mystery value, ... because `regionally in` is always meaning 2 of "in". For much more of this sort of definitional angst, see [The built-in verbs and their meanings]. ## A word about nothing ^^{|nothing: as a value} ^^{|nothing: testing that no such thing exists} ^^{descriptions (references to things): non-existence} ^^{non-existence: testing that no such thing exists} Like "in", "nothing" has two slightly different meanings, though here there's much less potential for confusion. **Meaning 1.** "Nothing" as "no thing". This is the meaning in sentences like: Definition: a container is bare if nothing is in it. And similar for conditions like `if the box contains nothing`. It's a word which describes the absence of things: it says that, though there might have been many possible items here, it turned out that there were none. **Meaning 2.** "Nothing" as a value. This is much less commonly seen, but sometimes Inform stores a value such as a property (or a variable) which always has to be an object. In some circumstances, `nothing` is then a special value meaning that this is not set at present. For instance, Definition: a container is impossible if its matching key is nothing. The `matching key` property of a container is always an object, but is allowed to be `nothing` when there isn't a matching key anywhere. (If such a container is locked, nobody will ever be able to unlock it.) **How Inform decides.** So which meaning does Inform use, and when? The answer is that it depends on the relationship being talked about. When this is "is", values are being compared and we are using meaning 2. But when it is any other relationship, like "is in" – which talks about containment – then we are using meaning 1. ## To be able to see and touch ^^{visibility+rel+ <-- visibility+relcat+} ^^{visibility+relcat+} ^^{touchability+rel+ <-- touchability+relcat+} ^^{touchability+relcat+}^^^{visibility+rel+ <-- able to see+relverb+ <-- see+relverb+}^^^{touchability+rel+ <-- able to touch+relverb+} ^^{visible / invisible (thing)+adj+} ^^{invisible / visible (thing)+adj+} ^^{touchable / untouchable (thing)+adj+} ^^{untouchable / touchable (thing)+adj+} ^^{light} ^^{darkness} ^^{yourself (- person)+const+} Two of the adjectives built into Inform are: - `visible` - the player can see this - `touchable` - the player can touch this So we can write descriptions such as `someone visible` or `a touchable container`. We also have adjectives `invisible` and `untouchable`, as might be expected. The visibility adjectives are particularly useful because the following is likely to go wrong: if Helen is in a dark room, ... This tests whether the room is dark, of itself; Helen may in fact be able to see by means of a torch, but the room is still `dark`. We can also talk about what other people can see and touch: something which can be seen by Helen are synonymous. Similarly for touch; and we can write such conditions as if Helen cannot see Agamemnon, ... if Cressida can see Troilus, ... Note that it is essential to establish who does the seeing and touching: so `something which can be seen` will not be allowed, whereas `something which can be seen by Helen` will. In fact, inside Inform the adjective `invisible` (for instance) has the following straightforward definition: Definition: Something is invisible if the player cannot see it. The exact definitions of visibility and touchability are complicated, because there are so many ways in which vision and touch can be obstructed, but the gist is that they behave as one would expect. Note that in darkness, nothing is visible, and that nobody can see from one room to another. In general anything invisible is also untouchable, but there are a few exceptions to do with being in the dark. Lastly, the player's own body (usually called `yourself` during play) is both visible (in light) and touchable. ## Adjacent rooms and routes through the map ^^{rooms+kind+: adjacent} ^^{adjacency+rel+} ^^{adjacency+relcat+} ^^{mapping (direction)+rel+} ^^{mapping (direction)+relcat+} ^^{adjacent (room)+adj+} ^^{use options: catalogue: |fast route-finding} ^^{fast route-finding+useopt+} ^^{use options: catalogue: |slow route-finding} ^^{slow route-finding+useopt+} ^^{pathfinding} ^^{route-finding, fast/slow} ^^{distance: measuring with (number of moves)+sourcepart+} ^^{(using doors), in route-finding+sourcepart+} ^^{directions+kind+: finding adjacent rooms} ^^{counting: moves along a route} Another useful adjective built into Inform is `adjacent`. Two rooms are said to be adjacent if there is a map connection between them which does not pass through some barrier such as a door. This is easily tested: if the Hallway is adjacent to the Study ... We usually want to know about the places adjacent to the current scene of the action, so that is what the adjective `adjacent` means when applied to rooms. For instance: if somebody is in an adjacent room, ... As with the case of `visible`, the adjective is a cut-down version of the more general relationship. This often happens: `worn` and `carried`, for instance, imply `by the player` unless something else is specified. If we want to ask a more direct question, we can obtain specific map connections as follows. (Recall that every map connection leads either to a door, to a room, or to nothing.) If we know which direction we want to look in, then the easiest thing is to use its relation – every direction in the map, say `north`, has its own relation, say `mapped north of`. So: if the Ballroom is mapped north of the Hallway, ... Alternatively, and particularly if the direction is not a constant, > phrase: {ph_roomdirof} room (direction) from/of (room) ... room > > This phrase produces the room which the given map direction leads to, or the special value `nothing` if it leads nowhere. If it leads to a door, the result is the room through that door. Examples: > > say "You look north into [the room north from the Garden]." > if the room north from the Garden is nothing, say "The grass leads nowhere." > phrase: {ph_doordirof} door (direction) from/of (room) ... door > > This phrase produces the door which the given map direction leads to, or the special value `nothing` if it leads nowhere or to a room. Examples: > > let the barrier be the door north from the Garden; > if the barrier is a door, say "Well, [the barrier] is in the way."; > phrase: {ph_roomordoor} room-or-door (direction) from/of (room) ... object > > This phrase produces the object which the given map direction leads to, which will always be either a room, a door or the special value `nothing`. The phrase is used mainly by the Standard Rules, for technical reasons, and usually it's better to use `room ... from ...` or `door ... from ...` instead. The map can be a great sprawling mass of rooms and doors connected together, and it can be quite hard to find a way through it one step at a time. > phrase: {ph_bestroute} best route from (object) to (object) ... object > > This phrase produces a direction to take in order to get from A to B by the shortest number of movements between rooms, or produces `nothing` if there is no way through at all. Example: > > The description of the brass compass is "The dial points quiveringly to [best route from the location to the Lodestone Room]." > > Best routes are ordinarily forbidden to go through doors, but if the suffix `using doors` is added as an option then any open or openable and unlocked door may be used on the way; and if `using even locked doors` is given, then any door at all will do. Since magnetism is no respecter of property, that seems right here: > > The description of the brass compass is "The dial points quiveringly to [best route from the location to the Lodestone Room, using even locked doors]." In practice this simple approach sometimes produces impossible journeys, rather the way Google Maps directions from New York to London would recommend driving down to the docks and then swimming. A more careful approach is to use: > phrase: {ph_bestroutethrough} best route from (object) to (object) through (description of objects) ... object > > This phrase produces a direction to take in order to get from A to B by the shortest number of movements between rooms which match the given description, or produces `nothing` if there is no way through at all. Example: > > best route from the Drawbridge to the Keep through visited rooms > > The condition – in this case, that `visited rooms` must be used – also applies to both ends of the journey, so if either Drawbridge or Keep are unvisited then this is `nothing`. (Similarly, saying something like `...through containers` would mean there is never a route.) Lastly, the following phrases can find out how long the journey would be. (They are quite a bit faster than using the `best route...` phrases repeatedly and counting.) > phrase: {ph_bestroutelength} number of moves from (object) to (object) ... number > > This phrase produces the number of map connections which must be followed in order to get from A to B by the shortest number of movements between rooms. If A and B are the same, the answer is 0; if there is no route at all, the answer is -1. Example: > > The description of the proximity gadget is "You are now [number of moves from the location to the Sundial] moves from the Sundial."; > phrase: {ph_bestroutethroughlength} number of moves from (object) to (object) through (description of objects) ... number > > This phrase produces the number of map connections which must be followed in order to get from A to B by the shortest number of movements between rooms matching the given description. If A and B are the same, the answer is 0; if there is no route at all, or if either A or B fail to match the description themselves, the answer is -1. Route-finding makes it possible to write quite sophisticated conditions concisely. But these sometimes run slowly, because they call for large amounts of computation. How rapidly Inform can find routes depends on which of two methods it uses. Both have advantages – one is fast but needs large amounts of memory, the other is slow but economical. We can choose between them with one of these two use options: Use fast route-finding. Use slow route-finding. If neither is specified, `fast` is used where the project uses the Glulx virtual machine (see the Settings panel), and `slow` on the Z-machine, where memory is tighter. Fast route-finding is ideally suited to situations where dozens of characters are constantly route-finding through the map as they meander around in a landscape. ### See Also - [Indirect relations] for route-finding through a relation rather than the map. ## All, each and every {PM_ComplexDeterminer} ^^{(all), in descriptions+sourcepart+} ^^{(each), in descriptions+sourcepart+} ^^{|every: in descriptions} ^^{(none), in descriptions+sourcepart+} ^^{(no), in descriptions+sourcepart+} ^^{|some: in descriptions} ^^{(most), in descriptions+sourcepart+} ^^{(almost all), in descriptions+sourcepart+} ^^{determiners (all / none)} ^^{quantifiers: universal} ^^{descriptions (references to things): determiners (all / none)} When testing conditions, we normally talk only about specific things, or else ask if a particular circumstance happens: if the oaken door is open if a woman is carrying an animal But we can also use `all`, `each` or `every` to check the whole range: if each door is open if anyone is carrying all of the animals if everybody is in the Dining Room Inform allows other English "determiners" (as they are sometimes called), as well: if some of the doors are open if most of the doors are open if almost all of the doors are open are true if at least one case is true, if a majority (any number greater than one half) or at least 80 per cent of the possible cases are true, respectively. And we can also use `none` and `no`. These three are all ways to say the same thing: if no door is open if all of the doors are not open if none of the doors is open though it may be clearer style to find a positive way of putting things: if all of the doors are closed All, each and every can be applied to values, too – but only in some cases. For example, suppose we write: Colour is a kind of value. The colours are red, orange, yellow, green, blue, indigo and violet. A colour can be found or unfound. And suppose that, during play, we assign the `found` property to any colour which the player notices on a wall. We might then want to write conditions like so: if every colour is found if most of the colours are found if any colour is found But we always have to bear in mind that Inform might have no reasonable way to decide these questions. It will refuse to allow these, for example: if every number is positive if any text is palindromic (even supposing the adjective `palindromic` has been defined) – there are practically infinitely many possible numbers and texts, so the search cannot sensibly be done. ## Counting while comparing ^^{comparisons: counting} ^^{counting} ^^{(less than), in descriptions+sourcepart+} ^^{(more than), in descriptions+sourcepart+} ^^{(at least), in descriptions+sourcepart+} ^^{(at most), in descriptions+sourcepart+} ^^{(all except), in descriptions+sourcepart+} ^^{|except: in descriptions} ^^{|exactly: in descriptions} ^^{descriptions (references to things): counting} ^^{numbers: of things in descriptions} Lastly we can also ask for a more specific number of possibilities, like so: if two women are carrying animals if at most three doors are open if fewer than 10 portable containers are closed if all but two of the devices are switched on if there are more than six locked doors Likewise for `less than`, `at least`, `all except`. Something to watch out for is that if two doors are open will be found true if there are (say) three open doors: after all, if three doors are open, then certainly two doors are. So this is not quite counting. We can be more precise by writing if exactly two doors are open The `all but` counts – say, `if all but two doors are open` – are exact: if, in fact, all of the doors are open then this will be found false. We can often use these counting forms with values, too. As with the use of `all`, this is allowed only if the kind of value is one which can reasonably be searched through. For example: if more than three scenes are happening if there are more than two non-recurring scenes are allowed because the built-in kind of value `scene` (of which much more later on) has only a small number of possible values. Lastly, note that the `the` in text like `two of the doors` matters: without it, the phrase will not be recognised as a requirement on the number. (This is to make sure that names of things like `two of hearts` are not misinterpreted.) # Basic Actions ## Actions {ACTIONS} {kind_actionname} {PM_APWithNoParticiple} {PM_APUnknown} {PM_NonActionIn} ^^{actions} ^^{success: for actions} ^^{failure: for actions} ^^{taking+action+ <-- >GET} ^^{ACTIONS+testcmd+} ^^{testing commands: >ACTIONS} _Actions_ are what we get if we try to break down a narrative into its smallest moments. We might casually say that we are "going shopping", but this involves many smaller steps: going north, going east, entering the shop, examining a loaf of bread, taking it, giving money to the baker, and so on. An action is an impulse to do something. This may or may not be a reasonable aspiration, and may or may not be achieved. The player explores the story by generating a sequence of actions, so writing the story is all about anticipating and responding to these actions. Actions are written with present participles. For instance, if the player types ``TAKE NAPKIN`` or ``GET THE NAPKIN`` or something similar then the resulting action is `taking the napkin`. Once the command has been understood, the exact wording doesn't matter any more: the action is what matters. Every action ends in success or failure. In this context, success means only that the player's intention has been fulfilled. If the player sets out to take the napkin, but finds a million-pound banknote in its folds instead, the action will be deemed to be a failure. The testing command ``ACTIONS`` causes Inform to log every action as it happens, and what its outcome is. (``ACTIONS OFF`` turns this off again.) For instance: > SOUTH [going south] Security Vault You can see a metal door here. [going south - succeeded] > CLOSE DOOR [closing metal door] You close the metal door. [closing metal door - succeeded] > TAKE DOOR [taking metal door] That's fixed in place. [taking metal door - failed the can't take what's fixed in place rule] A good way to get a sense of the constant flow of actions is to use this command and then wander around an existing work, trying things out. ``ACTIONS`` can also give an insight into the web of rules governing play: there are more than ten different ways an attempt to take something can fail, for instance. ## Actions versus commands ^^{>OOPS} ^^{>AGAIN} Actions and commands are not quite the same thing. Commands are the words typed in players: ``EXAMINE BLUEPRINT`` is an example of a command. When the player types this (and assuming there is a blueprint available), the action `examining the blueprint` is what then happens. At first sight, there's not much difference between ``EXAMINE BLUEPRINT`` and `examining the blueprint`. But not all typed commands correspond so exactly to actions: - If the player next types ``DROP IT``, the action generated is `dropping the blueprint`, because the command parser inside the story recognises ``IT`` as meaning the blueprint. The same command typed at a different time might produce a different action. - Two quite different-looking commands, such as ``DROP BLUEPRINT`` and ``PUT BLUEPRINT DOWN``, can produce the same action — again, `dropping the blueprint`. - If the player types ``DROP ALL``, that might generate multiple actions, not just one: for example, `dropping the bell`, `dropping the book` and `dropping the candle` might all happen in succession. - If the player types ``OOPS ...`` or ``O ...``, that tells the command parser to correct the previous mistyped command. For example, if a player typed ``PUT THE BLUEPRINT IN THE CUBOARD``, and the parser complained that ``CUBOARD`` did not make sense, the player could reply ``OOPS CUPBOARD``. The end result is the action `putting the blueprint in the cupboard`, but only because that was the original intention. There's no such thing as an `oopsing` action. - And similarly for the special command ``AGAIN`` or its abbreviated form ``G``. This tells the command parser to behave as if the previous command had been typed again. So ``GO NORTH`` and then ``AGAIN`` will generate the actions `going north` and then `going north`, but there's no `againing` action. - And besides all of that, of course, many commands make no sense to the parser, and instead produce replies like ``That's not a verb I recognise.`` No time elapses in the story, and no action is generated. Actions can also happen without involving the command parser at all: - When the story begins, a `looking` action causes the player character's initial surroundings to be described — even though nobody typed ``LOOK``. - Inform generates a few so-called _implicit_ actions automatically as a courtesy to players. If a player types ``WEAR HAT``, but does not have the hat, `taking the hat` is tried first, and only then `wearing the hat`. - As we shall see, rules written by the author of the story can cause any action to be tried by any character. It's a good idea for the author of a story to have a rough idea of the range of actions built in to Inform, and the commands which might generate those actions. Inform provides complete documentation on both of those things, but not in this manual. Instead, it's all given in the Index of a project. Before going on with this chapter, then, readers might want to try one of the tiny stories so far, and then look at the Actions page of the project's Index in the Inform application. In particular: - The "Grouped" and "Alphabetic" tabs show all of the built-in actions. Clicking on the magnifying glass icon next to any action shows a detailed description of what it does, and how it can be generated by commands. - The "Commands" tab gives an alphabetical listing of build-in commands, from ``ADJUST`` to ``Z`` (which is an abbreviation for ``WAIT``). ## Instead rules {rules_instead} ^^{rules} ^^{instead of (action)+rb+} ^^{rules: instead rules} ^^{actions: using instead rules to change outcome} ^^{punctuation: comma: comma replacing colon} ^^{|,: comma replacing colon} An action is ordinarily handled by running it through Inform's extensive rulebooks of what might be called normal behaviour. An action such as `taking the napkin`, for instance, will be run through numerous checks to see if it is physically reasonable, and then provided all is well, the napkin will be moved into the possession of the player. Instead, though, we can bypass the rules to do with an action and do something else: Instead of eating the napkin: say "Why not wait for the actual dinner to arrive?" This is an example of a _rule_: a set of circumstances followed by a list of instructions. When those circumstances apply, the instructions are carried out. In the case of an `instead` rule, after this is done the action is immediately ended (and counts as a failure, since the original intention has been thwarted). A friendly alternative can be used when there is only a single instruction, as here: in such rules the colon can be replaced with a comma. Thus: Instead of eating the napkin, say "Why not wait for the actual dinner to arrive?" ## Before rules {rules_before} ^^{before (action)+rb+} ^^{rules: before rules} ^^{instead of (action)+rb+} ^^{rules: instead rules} ^^{(instead), to stop the action+sourcepart+ <-- +to+stop the action: using (instead)+sourcepart+} ^^{actions: using before rules to test or change outcomes first} ^^{actions: +to+stop the action} ^^{actions: +to+continue the action} Despite what was said in the previous section, instead rules do not quite bypass all of the usual rules. Inform knows that certain actions require light: for instance, examining the napkin; looking; looking under the dining table and if it is dark then none of these actions will be allowed, and any instead rules about them will not even be reached. Similarly, Inform knows that most actions require physical access to their objects: so `taking the napkin` would be blocked if the napkin were, say, inside a closed glass bottle, whereas `examining the napkin` would not. So an instead rule can only take effect if the action has already passed these basic reasonability tests. `Before` rules genuinely precede checking of any kind. They also differ from instead rules in that they do not automatically stop the action in its tracks. Rather, they are provided as an opportunity to ensure that something else is done first. For example: Before taking the napkin, say "(first unfolding its delicate origami swan)". whence > GET NAPKIN (first unfolding its delicate origami swan) Taken. We have seen that instead rules automatically stop actions, whereas before rules automatically allow them to continue. We sometimes want to change this. The magic word `instead` can therefore be tacked on to any instruction in a before rule, and will have the effect of immediately stopping the action at that instruction. Thus the following two rules are (almost) equivalent: Before taking the key, instead say "It seems to be soldered to the keyhole." Instead of taking the key, say "It seems to be soldered to the keyhole." It is also possible to be explicit about stopping the action: > phrase: {ph_stopaction} stop the/-- action > > This phrase stops the current rule, stops the rulebook being worked through, and finally stops the action being processed. Example: > > Before taking the key: > say "It seems to be soldered to the keyhole."; > stop the action. Finally, we can prevent Inform from stopping the action when it otherwise might: > phrase: {ph_continueaction} continue the/-- action > > This phrase ends the current rule, but in a way which keeps its rulebook going, so that the action being processed will carry on rather than being stopped. Example: > > Instead of taking the napkin: > say "(first unfolding its delicate origami swan)[command clarification break]"; > continue the action. > > An `instead` rule ordinarily stops the action when it finishes, so the `continue the action` is needed to make things carry on. (This rule would have been better written as a `before` rule, in fact, but it shows the idea.) As a general principle, it is good style to use instead rules whenever blocking actions, and before rules only when it is genuinely necessary to do something first but then to continue: in fact, it is good style to use `stop the action` or `continue the action` as little as possible. ## Try and try silently {PM_UnknownTryAction1} {PM_UnknownTryAction2} {PM_ActionNotSpecific} {PM_ActionTooSpecific} ^^{actions: performing with (try)+sourcepart+} ^^{actions: suppressing success messages with (try silently)+sourcepart+} the [Source Text] chapter noted that surveys of Inform source text showed that the three most popular phrases used by authors are `say`, `if` and `now`. The fourth most popular is `try`, which allows us to trigger off actions ourselves, rather than waiting for the player to type something which generates them. Thus: > phrase: {ph_try} try (action) > > This phrase makes the action, which has to be named literally, take effect now. Example: > > Instead of entering the trapdoor, try going up. > > It's as if the player had typed ``GO UP`` as a command. Note that the action has to be specific: > > try eating something; > > is not allowed, since it doesn't say exactly what is to be eaten. The word `try` is intended to make clear that there is no guarantee of success. For example: Before locking the front door, try closing the front door. could go wrong in any number of ways – perhaps the door is closed already, perhaps it is not openable, perhaps somebody has wedged it open. It would be safer to write: Before locking the front door: try closing the front door; if the front door is open, stop the action. There's no need to say anything if closing didn't work, because the closing action will have done that already. A neater approach still is to use: > phrase: {ph_trysilently} silently try (action) & try silently (action) > > This phrase makes the action, which has to be named literally, take effect now, under the "silent" convention which means that routine messages aren't printed. Example: > > try silently taking the napkin; > > Silence is maintained only if this new action, the taking of the napkin, is successful (so if the napkin is successfully taken, the text "Taken." will not appear): if the action should fail, a suitable objection will be voiced as usual. So now we have: Before locking the front door: try silently closing the front door; if the front door is open, stop the action. And this is neater because it won't produce a pointless "You close the front door." message. ### See Also - [Stored actions] for how to store up actions as values and try those, too, so that isn't necessary to name the action as literally as in the examples above. ## After rules {rules_after} ^^{after (action)+rb+} ^^{rules: after rules} ^^{actions: using after rules to change output} ^^{+to+continue the action} ^^{actions: +to+continue the action} There is pleasantly little to be said about `after` rules. If an action has survived all the rules in its way, and has actually succeeded, then we need to give the player a response which acknowledges this. Inform's normal rules will be sufficient to say something undramatic: for instance, if `taking the napkin` has succeeded then it will reply "Taken." to the player. An after rule is an opportunity to say something more interesting: After taking the diamonds, say "Taken!" (Well, slightly more interesting.) After rules automatically end the action (as a success), which is what we would want in the above case. Allowing it to continue would simply result in "Taken." being printed as well. However, should we really need to do something and then carry on: After taking the diamonds: say "(Mr Beebe looks up sharply.) "; continue the action. ## Reading and talking ^^{actions: involving speech} ^^{rules: for speech} ^^{understanding: arbitrary text: for conversations and consulting} ^^{books (implementing): consulting} ^^{consulting (thing) about+action+} ^^{asking (actor) about+action+} ^^{telling (actor) about+action+} ^^{answering (actor)+action+} ^^{dialogue: >ASK / TELL} A few actions apply not to items alone, but also involve what might be called conversation. The first is the one used for looking things up in books (which is conversation of a kind, even if the author is not present): `consulting ... about ...`. For example, {*}In the Grove is a book of sybilline verses. After consulting the book about "grove", say "The Grove is a sacred yadda, yadda. There's a tree, that sort of thing. Wisdom." After consulting the book about "future events", say "It's a bit, what's the word? Delphic." Note that what follows `about` here is a piece of text in double-quotes, and not the name of something. It can be almost any text at all, and in fact we shall later see (in the chapter on [Understanding]) that we can match complicated patterns of words, too. Similar actions are used for conversing with people: After asking the Sybil about "verses", say "She blushes." After telling the Sybil about "persians", say "She nods gravely." After answering the Sybil that "I am mad", say "She sighs." These would be produced by commands like "ask sybil about verses", "tell sybil about persians" and "answer i am mad". Answering is little-used except that it also catches commands like "sybil, something unrecognised", which inexperienced players sometimes type. Asking and telling, however, are important actions and the difference between them is often worth preserving. If you would prefer to make "tell sybil about X" do the same as "ask sybil about X", the following rule would serve: Instead of telling the Sybil about something, try asking the Sybil about it. Games with a lot of conversation often involve great heaps of rules like the ones above, which can be repetitious to type out. We shall also later see (in the chapter on [Tables]) that we can tabulate questions and answers in a much more concise way, if we prefer. ### See Also - [Topic columns] for table-based ways to store and retrieve conversation. ## The other four senses ^^{senses} ^^{actions: involving senses} ^^{rules: for senses} ^^{rooms+kind+: listening to (with no object)} ^^{rooms+kind+: smelling (with no object)} ^^{listening to+action+} ^^{smelling+action+} ^^{touching+action+} ^^{tasting+action+} ^^{looking under+action+} The five senses are all simulated with actions. Sight is so informative that it is handled by a whole range of actions: `looking`, which describes the general scene; `examining something`, which takes a closer look at a specific thing; `looking under something`, and so on. The other senses have one action each: `listening to something`, `touching something`, `tasting something` and `smelling something`. It makes no sense to touch or taste the general scene, but listening and smelling are a different matter: we often just listen, without listening to anything specific. If the player types the command "listen", Inform understands that as listening to the current location: similarly for the bare command "smell". Thus: Instead of listening to the Seashore, say "The song of gulls." Instead of smelling the Cave, say "Salt and old seaweed." ## Rules applying to more than one action {PM_APWithDisjunction} {PM_APWithImmiscible} ^^{rules: applying to multiple actions} ^^{actions: rules for multiple actions} A description can include more than one choice of action. For instance: examining or searching the desk matches either of `examining the desk` or `searching the desk`. We can have more than two actions, of course: examining, looking under or searching the desk The actions combined like this need to be compatible with each other, at least a little. For instance, this will generate a problem message: waiting or searching the desk because it makes no sense to "wait the desk". On the other hand, this is fine: waiting or searching The general rule is that if we specify one or more objects (`the desk` in the above example), then each of the actions we quote must take at least that many objects. For example, the following saves us writing the same basic rule three times over: Instead of examining, looking under or searching the desk: say "There's no use poking around in that old desk." ## All actions and exceptional actions ^^{rules: applying to all but some actions} ^^{actions: rules for all but some actions} ^^{(doing something / anything), describing actions+sourcepart+} ^^{|except: describing actions} The special description `doing something` (or `doing anything`) matches any action, and `doing something to ...` also allows the noun to be specified. For instance, the following puts its object out of bounds: Instead of doing something to the cucumber sandwich, say "Lady Bracknell stares disapprovingly down her pince-nez at you, in a way which no amount of hunger or curiosity could overcome." We sometimes need to be a little careful here: `waiting` qualifies as `doing something`, but not as `doing something to something`, because there is no object. `Putting the handbag on the cucumber sandwich` would also not qualify as `doing something to the cucumber sandwich` – only to the handbag. More often, we would like to restrict the range of allowable actions to a select few. For instance: Instead of doing something other than looking, examining or waiting: say "You must learn patience." (Or we can write `except` instead of `other than`.) Or we might have an object, too: Instead of doing something other than examining, taking or dropping with the dagger: say "Don't fool around with that dagger. It's exceedingly sharp." Note the `with`, which is crucial here. Without it, the rule is subtly different: Instead of doing something other than examining, taking or dropping the dagger: say "Don't fool around with that dagger. It's exceedingly sharp." This second version matches if the action is, say, taking a shield, or even just looking, because that would be an action other than examining the dagger, taking the dagger or dropping the dagger. ## The noun and the second noun {var_noun} ^^{noun (- object)+glob+} ^^{second noun (- object)+glob+} ^^{rules: applying to arbitrary things} ^^{things+kind+: referring to arbitrary things in rules} ^^{articles: displaying and capitalising} ^^{case sensitivity: in text substitutions with objects} Once we begin applying rules to actions which are not entirely known in advance, we have a problem: there's no way to find out what specifically is happening. Consider the following: Instead of examining something, say "It is none of your concern!" This is fine as far as it goes, but clumsy. What if the player had examined a human being? Then "it" would be inappropriate. A better approach would be this: Instead of examining something, say "[The noun] is none of your concern!" The `noun` and, when necessary, the `second noun` are values which can be used in any rule about actions, and it follows that they can also be substituted into text, as this example demonstrates. Results might include: Lady Bracknell is none of your concern! The silver cigarette case is none of your concern! This seems a good moment to mention that if you use `The` in a substitution, then a capitalised `The` will be used so long as this is grammatically correct (Lady Bracknell, as a proper noun, takes no article); `the` becomes a lower-case `the` along the same lines; and `a` a lower-case indefinite article. Instead of examining something in the Drawing Room, say "Under Lady Bracknell's eye, you feel constrained. Besides, it is only [a noun]." ## In rooms and regions ^^{actions: rules applying to rooms and regions} ^^{rules: applying to rooms and regions} ^^{rooms+kind+: rules applying to rooms} ^^{regions+kind+: rules applying to regions} ^^{(in), location conditions for rules+sourcepart+} Three elaborations of action descriptions increase the range of possibilities further. Instead of taking something in the Supernatural Void, say "In this peculiar mist you feel unable to grasp anything." Like the objects to which the action applies, this location – the `in` clause – can take any description, not just an explicit place like "Supernatural Void": Instead of listening in a dead end, say "You strain to hear further clues as to the course of the underground river, but to no avail." But we often want a rule to apply in any of a set of rooms: and where, unlike the `dead end` example above, the rooms have nothing much in common except where they happen to lie on a map. For instance, we might want a rule to apply only inside a given building, or a garden consisting of five miscellaneous rooms. If so, we can create a `region` as a convenient way to refer to that group of rooms: The Arboretum is east of the Botanical Gardens. Northwest of the Gardens is the Tropical Greenhouse. The Public Area is a region. The Arboretum and Gardens are in the Public Area. Instead of eating in the Public Area, say "The curators of the Gardens are ever among you, eagle-eyed and generally cussed." ## In the presence of, and when {PM_NonActionInPresenceOf} {PM_APWithBadWhen} ^^{|in the presence of} ^^{|presence of} ^^{actions: rules applying only when characters are present} ^^{rules: applying only when characters are present} ^^{characters (people): rules applying only when characters are present} ^^{actions: rules applying under arbitrary conditions, using (when)+sourcepart+} ^^{rules: arbitrary conditions for rules, using (when)+sourcepart+} ^^{when (condition)+sourcearg+: arbitrary conditions for rules} ^^{conditions: for rules} Relative location can also be important: relative to other people, that is – Instead of eating something in the presence of Lady Bracknell, say "Lady Bracknell disapproves thoroughly of gentlemen who snack between meals, and there are few disapprovals in this world quite so thorough as Lady Bracknell's." `In the presence of` means that this action takes place when Lady Bracknell is close at hand to the player. Most of the time that means that the player and Lady B. are in the same location, but the full answer is that Lady B. has to be what is called "in scope". This is the same concept used to work out what the player can refer to in most commands: for example, the command ``GIVE MUFFIN TO LADY BRACKNELL`` will be understood only if she is "in scope". Since it is possible to change scoping rules, the meaning of `in the presence of` may change accordingly. See [Scope] for more. `In the presence of` need not be applied to specific people. It can be somebody described more vaguely (`... in the presence of a woman`, say), or can just as easily be an inanimate thing (`... in the presence of the radio set`). The last of the optional clauses we can tack on to the description of an action is the most general of all. We can add `when` and then any condition at all, as in: Instead of eating something when the radio set is switched on, say "Something about the howling short-wave static puts you right off luncheon." This supposes that the radio is so loud that it can be heard from any room: we could muffle it so that it's only audible from the room it is in like so: Instead of eating something in the presence of the radio set when the radio set is switched on, say "Something about the howling short-wave static puts you right off luncheon." ## Going from, going to ^^{going+action+ <-- movement (player)} ^^{going+action+: going nowhere+action+} ^^{going+action+: going from+action+} ^^{going+action+: going to+action+} ^^{going+action+: default failure response} ^^{going+action+: rules for going to and from places} ^^{|nowhere: rules for going nowhere} ^^{actions: (going), special cases+sourcepart+} ^^{rules: for (going), special cases+sourcepart+} ^^{actions: rules applying to rooms and regions} ^^{rules: applying to rooms and regions} ^^{rooms+kind+: rules applying to rooms} ^^{(in), location conditions for rules+sourcepart+} ^^{connections between rooms: rules applying to map connections} Going is an action defined like any other: it is the one which happens when the player tries to go from one location to another. But it is unlike other actions because it happens in two locations, not just one, and has other complications such as vehicles and doors to contend with. To make it easier to write legible and flexible rules, `going` is allowed to be described in a number of special ways not open to other actions, as demonstrated by the following example story: {*}"Going Going" The Catalogue Room is east of the Front Stacks. South of the Catalogue Room is the Musicology Section. Instead of going nowhere from the Front Stacks, say "Bookcases obstruct almost all passages out of here." Instead of going nowhere, say "You really can't wander around at random in the Library." Before going to the Catalogue Room, say "You emerge back into the Catalogue Room." Note that `going nowhere` means trying a map connection which is blank, and if no rules intervene then "You can't go that way" is normally printed. Unless `nowhere` is specified, descriptions of going apply only when there is a map connection. So `going from the Musicology Section` would not match if the player were trying to go east from there, since there is no map connection to the east. Similarly, `going somewhere` excludes blank connections. The places gone `from` or `to` can be specific named regions instead of rooms. This is convenient when there are several different ways into or out of an area of map but a common rule needs to apply to all: so, for example, Before going from the Cultivated Land to the Wilderness, ... Before going nowhere from the Wilderness, say "Tangled brush forces you back." Note that it must be `going nowhere from the Wilderness`, not `...in the Wilderness`. (Note also the caveat that the regions must be named: `going from a region`, or something similarly nonspecific, will not work.) An important point about `going... from` is that, as mentioned in general terms above, it requires that there is actually a map connection that way: whereas `going... in` does not. Suppose there is no map connection north from the Wilderness. Then: Instead of going north from the Wilderness, say "You'll never read this." Instead of going north in the Wilderness, say "Oh, it's too cold." The first of these never happens, because it is logically impossible to go north from the Wilderness: but the second does happen. (Technically, this is because `going north` is the action, and `in the Wilderness` a separate condition tacked onto the rule.) This distinction is often useful – it allows us to write rules which apply only to feasible movements. This may be a good place to mention a small restriction on the ways we can specify an action for a rule to apply to, and how it can be overcome. The restriction is that the action should only involve constant quantities, so that the following does not work: The Dome is a room. The Hutch is north of the Dome. The rabbit is in the Hutch. Before going to the location of the rabbit, say "You pick up a scent!" because `the location of the rabbit` is a quantity which changes in play (the player can pick up the rabbit and take it to the Dome, for instance). However, we can get around this restriction by defining a suitable adjective, like so: The Dome is a room. The Hutch is north of the Dome. The rabbit is in the Hutch. Definition: a room is rabbit-infested if it is the location of the rabbit. Before going to a rabbit-infested room, say "You pick up a scent!" ## Going by, going through, going with {PM_GoingWrongKind} {PM_GoingWithoutObject} ^^{going+action+: going by+action+} ^^{going+action+: going through+action+} ^^{going+action+: going with+action+} ^^{going+action+: rules for going through doors} ^^{going+action+: rules for going by vehicles} ^^{going+action+: rules for going with pushed things} ^^{doors+kind+: rules for going through doors} ^^{vehicles+kind+: rules for going by vehicles} ^^{actions: (going), special cases+sourcepart+} ^^{rules: for (going), special cases+sourcepart+} ^^{actions: (pushing) objects to other rooms+sourcepart+} ^^{rules: for (pushing) objects to other rooms+sourcepart+} ^^{pushing things: rules for pushing things} ^^{things+kind+: pushable between rooms} ^^{exiting+action+} ^^{rules: for (exiting)+sourcepart+} ^^{actions: (exiting)+sourcepart+} Adding to the previous example story, we apply rules which depend on travelling by a particular vehicle: The book trolley is in the Musicology Section. "The book trolley, a sort of motorised tractor for trundling around through the stacks, is parked here." The trolley is a vehicle. Instead of going nowhere by the trolley, say "Don't go crashing the trolley into walls." Instead of going to the Front Stacks by the trolley, say "The Front Stacks are far too confined for the trolley to manoeuvre into them." And, lastly, rules which apply to movements through particular doors: The green baize door is east of the Catalogue Room and west of the Clerk's Office. The green baize door is an open door. Before going through the green baize door, say "Through you go..." After going through the green baize door: try looking; say "...and here you are." (Note that these apply whether the action is `going east` or `entering the green baize door`, each having the same effect.) The last rule is worth a second look: the normal way that a `going` action is reported is to produce the room description of the new location. So if an `after` rule stops the action before we get to reporting, we have to produce any room description by hand (hence the `try looking` to cause the looking action). Alternatively, we could simply say something and let the normal course of events take place: After going through the green baize door: say "...and here you are:"; continue the action. Finally, going is an action which can also happen while the player is pushing something from one room to another, and we can describe this like so: Instead of going from the Office with the trolley, say "But it looks perfectly placed here. Why push any further?" `Going` is not the only action which moves the player. Another is `exiting`, an action which moves the player out of whatever they are currently in or on. This action is often caused by the player typing just ``OUT`` or ``GET DOWN``, and there's no noun as such. But Inform allows the syntax `exiting from` to make it easier to write rules about the exiting of particular containers or supporters: After exiting from the Mini Cooper: say "You painstakingly unpack your limbs from the tiny car." ## Named action patterns {PM_NamedAPWithActor} {NAPS} ^^{kinds: of action} ^^{actions: new named action patterns} ^^{rules: creating named action patterns to reduce redundancy} ^^{propriety} Especially when people need to react to events going on around them, it is helpful to be able to categorise actions into whole areas of behaviour. For instance: Mr Carr is in the Inn. Mr Carr is a person. Kissing Mr Carr is unmaidenly behaviour. Doing something to the painting is unmaidenly behaviour. Instead of unmaidenly behaviour in the Inn, say "How unmaidenly!" Here, `unmaidenly behaviour` is an example of a _named action pattern_. (In the past, this was sometimes called a "kind of action", but not any more.) The term _action pattern_ is Inform slang for a possibly vague description of an action: for example, `Kissing Mr Carr` and `Doing something to the painting` are both action patterns, even though one is more specific than the other. The effect of the two sentences Kissing Mr Carr is unmaidenly behaviour. Doing something to the painting is unmaidenly behaviour. is that `unmaidenly behaviour` is now also valid as an action pattern, so it can be used in `Instead of` and other such rules. This is convenient both as a shorthand and because, when further actions suddenly occur to us as also being unmaidenly, we only need to add a single line: Attacking Mr Carr is unmaidenly behaviour. And this will automatically be reflected in any rules which concern the consequences of failing to be ladylike, that is, which depend on the current action being `unmaidenly behaviour`. Note that an action _pattern_ is not the same thing as an action _name_. So this works: Throwing something at something is unmaidenly behaviour. But this does not: Throwing it at is unmaidenly behaviour. While it's true that the text `throwing it at action` means something to Inform (it's an _action name_), `throwing it at` does not, and isn't valid as an action pattern because it doesn't say what the two objects involved are. So: throwing something at something throwing something at Mr Carr throwing the ring at somebody are all valid action patterns (assuming Mr Carr and the ring exist), but `throwing it at` is not. See [New actions] for more on this distinction. ## Repeated actions ^^{rules: applying to repeated actions} ^^{actions: rules for repetitions} ^^{time: counting actions with (for the Nth time)+sourcepart+} ^^{counting: actions with (for the Nth time)+sourcepart+} ^^{(first time), counting actions+sourcepart+} We come at last to the final thing which can be specified about an action, and appropriately enough it must be specified with the final words of the description. This is the way to talk about repeated activity: Instead of examining the tapestry for the third time, say "All right, so it's a masterpiece, but is this really the time to make a detailed study?" Instead of examining the urn at least twice, say "It's an urn. What do you want from me?" Instead of going nowhere for the 20th time, say "Do stop walking into walls, there's a good fellow." Note that we are allowed to spell out numbers up to twelve in English words, but beyond that must use digits (thus `twelfth` is allowed but not `thirteenth`: `13th` should be used instead). The following example is instructive: Instead of taking something for the fourth time, say "No. I'm capricious." This means that it is the fourth time a `taking...` action has been tried, and does not mean that the same item was taken each time. Also, note that we are counting the number of times the action has been tried, not the number of times it succeeded. ## Actions on consecutive turns ^^{rules: applying to consecutively repeated actions} ^^{actions: rules for consecutive repetitions} ^^{turns: counting actions with (for the Nth turn)+sourcepart+} ^^{counting: actions with (for the Nth turn)+sourcepart+} ^^{(doing it), a repeated action+sourcepart+} ^^{rules: abbreviating actions with (doing it)+sourcepart+} ^^{abbreviations: rule actions with (doing it)+sourcepart+} We can also reckon the number of consecutive turns on which an action has been repeated, by talking about `turns` instead of `times`, as demonstrated in the following example story. Note also that we are allowed to use the phrase `doing it` to mean "the same description as the previous one except for the part about turns or times", like so: {*}"Waiting Room" The Antechamber is a room. The tattered copy of Women's Wear Daily is in the Antechamber. Instead of taking the Daily, say "It is stamped NOT TO BE TAKEN AWAY." Instead of examining the Daily for the first time, say "The best article seems to be about how your star sign affects your best swimsuit colour. Really: that's the best article." Instead of doing it for the second time, say "You now know a generous amount about a typical week in the life of a weather forecaster." Instead of doing it for the third time, say "You would now know how to cook herb bread, except that you have already forgotten the names of both of the herbs." Instead of doing it more than three times, say "Nope, you've drained it of all conceivable sustenance, even the small ads about French farmhouses to let (sleeps 7) and breast reduction surgery (with alarming photographs in sallow light)." After waiting for four to six turns, say "This is getting mighty dull." After waiting for seven to eight turns, say "Really, exceptionally dull." After waiting for nine turns, end the story saying "You have died of boredom, something previously thought medically impossible". Note once again that numbers above twelve must not be written out, so `more than twelve times` would be acceptable, but we would write `more than 13 times`. ## Postscript on actions In this chapter, all actions have been carried out by the player, all have been drawn from the standard stock of built-in actions (`unlocking`, `taking`, `going` and so forth), and all of those built-in actions have been allowed to work in the standard way – we have seen how to prevent the taking of something, and how to give this unexpected consequences, but not how to make taking work in an entirely different way. All three of those restrictions will later be lifted in the chapter on [Advanced Actions], but otherwise we have covered the ground thoroughly, and it is time to move on to the techniques enabling us to do more than make tart replies to the player: it is time to change the world. # Change ## Change of values that vary ^^{+to+now (a condition) <-- change} ^^{+to+now (a condition): changing global variables} ^^{variables: changing global variables} ^^{type-checking} So far, what we have done in response to the player's commands amounts to little more than a few ripostes. The simulated world does change during play, as the player moves from room to room or picks up things, but all of this is happening automatically, not at our direct instruction. How then can we make the world change? Recall that the world consists of rooms, in which are things, and that all of these have properties appropriate to their kinds. Some properties are either/or (`open` or `closed` but not both and not neither), while others have values (the `matching key` of a lockable door, for instance). Finally, we may also have created some free-standing values or "variables". We take the last example first, as it is the simplest. Suppose we have: {*}"Winds of Change" The prevailing wind is a direction that varies. The prevailing wind is northwest. The Blasted Heath is a room. "Merely an arena for the play of witches and kings, my dear, where the [prevailing wind] wind blows." Instead of waiting when the prevailing wind is northwest: say "A fresh gust of wind bowls you over."; now the prevailing wind is east. The new phrase here is `now`. This automatically checks that the new value is one which makes sense in the given context, so for instance it would not allow either of these: now the prevailing wind is 25; now the prevailing wind is the Heath; the former being a number, and the latter a room, so that neither is a direction. Similarly, `now` will not allow constant values to be changed. So Colour is a kind of value. The colours are blue, red and mauve. After pulling the psychedelic lever: now blue is mauve. ...will result in a problem message; it's like writing `now 1 is 2`. The difference between `the prevailing wind` and `blue` is that the wind was declared to be a `direction that varies`, whereas blue wasn't. ## Changing the command prompt {var_prompt} ^^{prompt, changing the prompt} ^^{command prompt (- text)+glob+} ^^{when play begins+rb+} ^^{time of day (- time)+glob+} The command prompt is the text printed by Inform to ask the player for another command. Ordinarily this is simply a greater-than-sign, ">", so we tend not to notice it as text at all. Internally, though, it is a variable value called `command prompt`, which means we can change it. For example, this will be a more conversational sort of prompt: When play begins: now the command prompt is "What now? ". Whereas this will be more up-to-the-minute and demanding: When play begins: now the command prompt is "[time of day] >". (`Time of day` is another variable value, which is fairly self-explanatory, but will be covered in detail later on.) The prompt can be changed at any point, so can be used to indicate the current situation, or even as a sly way to introduce a sort of conversation between computer and player. ## Changing the status line {var_sl} ^^{status line} ^^{screen top} ^^{scoring: in status line} ^^{score (- number)+glob+} ^^{turn count (- number)+glob+} ^^{left hand status line (- text)+glob+} ^^{right hand status line (- text)+glob+} ^^{time of day (- time)+glob+} The status line is the black bar along the top of a story being played, which ordinarily displays the current position; in a story with scoring, it also usually shows the score and number of moves taken. Like the command prompt, it is not fixed but results from values which can be changed: the `left hand status line` and `right hand status line`. The default values are `"[the player's surroundings]"` for the left hand status line and `"[score]/[turn count]"` for the right hand status line (if there's scoring; it's blank otherwise). Score and turn count are numbers which vary in play (more about scoring later); `"[the player's surroundings]"` is a text substitution really intended for just this purpose: > phrase: {phs_surroundings} say "[the/-- player's surroundings]" > > This text substitution produces a succinct description of where the player is, be this in darkness, in a lighted room or inside an opaque container such as a large packing case. Example: > > now the left hand status line is "You: [the player's surroundings]"; These make useful elements to juggle in redesigning the status line, as in the following example: {*}When play begins: now the left hand status line is "[the player's surroundings] / [turn count] / [score]"; now the right hand status line is "Time: [time of day]". The text in the right hand status line should be kept no more than 14 letters long, including any spaces. The left hand status line has more leeway, but should still be kept brief. ### See Also - [Awarding points] for scoring. - [Constructing the status line] for an activity which allows much greater flexibility, and can make a status window larger than a single line. ## Change of either/or properties ^^{+to+now (a condition): changing either/or properties} ^^{properties: either/or properties: changing} ^^{either/or properties: changing} ^^{type-checking} When we have an either/or property, we can set it like so: Instead of waiting when the oaken door is closed: say "There is a slow, creaky click! sort of noise as the door swings open, apparently all by itself."; now the oaken door is open. If it is open already, nothing changes: in any case nothing is said to the player unless we give explicit instructions to that effect, as we've done here. Inform protects its model world from accidental damage in several ways, one of which is to ensure that things are not given properties which they are not allowed to have. So this, for instance, will not be accepted: now the oaken door is unvisited More subtle problems arise if it is not possible to tell, when the story is being constructed, what the object in question will be: for instance, if we try to change a randomly chosen object to be `unvisited`. Inform therefore makes additional checks during play, printing up a suitable message only if the rules are violated. The net effect is that it is impossible for the oaken door ever to have the `unvisited` property. ## Change of properties with values ^^{+to+now (a condition): changing value properties} ^^{properties: value properties: changing} ^^{value properties: changing} ^^{initial appearance of (thing)+prop+} ^^{initial appearance of (thing)+propcat+} ^^{descriptions (displayed): initial appearance of thing} ^^{printed name of (object)+prop+} ^^{printed name of (object)+propcat+} ^^{names: printed name of (object)+prop+} ^^{connections between rooms: changing} ^^{rooms+kind+: changing connections between rooms} ^^{|nowhere: in removing room connections} ^^{|nothing: in removing room connections} Changing properties with values is very similar: now the printed name of the Closet is "Suddenly Spooky Closet" Inform checks three different things to ensure that this change is safe to perform. Firstly, the value must be the right kind for the property in question, so this for instance would be rejected: now the printed name of the Closet is 7 Secondly, the object in question has to be allowed to have the given property. This, for instance, would be disallowed: now the initial appearance of the Closet is "Dusty" (since `initial appearance` is a property which only things can have, not rooms). Finally, the object has to actually have the property, not just have the right to have that property. Thus: now the printed name of the Closet is "Suddenly Spooky Closet" ...is only permitted if the Closet is designed with a `printed name`. In fact this is certain to be true: all rooms and things automatically have a printed name, which is the short boldface description in the case of rooms, and the usual text briefly describing something in the case of things. `Now` is a simple way to change many things in Inform, but it's cumbersome to change the map of the model world using `now`, because the map is such a complicated arrangement. (It's not a property: it's a sort of mesh of relations.) So a special phrase exists to change map connections: > phrase: {ph_changeexit} change (direction) exit of (room) to (room) > > This phrase alters the map so that the given map connection is made. Note that connections can be made to rooms, but not doors: the positions of doors are fixed. Example: > > change the east exit of the Closet to the Tsar's Imperial Dining Salon > > Since `nothing` is not a room, this doesn't allow us to change the exit to nothing, so there is a separate definition of: > > change the west exit of the Closet to nothing > phrase: {ph_changenoexit} change (direction) exit of (room) to nothing/nowhere > > This phrase alters the map so that the given map connection is unmade. Example: > > change the west exit of the Closet to nowhere Altering the map itself is not a very subtle way to adjust when and where the player can move – writing suitable rules is usually a cleaner solution – so this phrase is best avoided unless really needed. ## Whose property? ^^{properties: shorthand name, omitting (of the)+sourcepart+} ^^{abbreviations: property names, omitting (of the)+sourcepart+}^^^{abbreviations <-- shorthand} ^^{printed name of (object)+prop+} ^^{printed name of (object)+propcat+} This seems a useful point to clarify something already seen. We normally call a property with a value something like: the printed name of the West Ballroom We are sometimes allowed to omit the `of the ...` part, and simply call it `the printed name`, for the sake of brevity. For instance, the following room description: The West Ballroom is a room. "A handsome sweep of chequered floor beckons the eye into the [printed name]." will result in "West Ballroom" being substituted for `"[printed name]"`. Since the text belongs to the West Ballroom, that is assumed to be the owner of any properties named in its description. Similarly: Instead of examining something, say "Hmm, let me see: [printed name]..." Here the owner of the `printed name` is assumed to be the noun referred to in the action – in other words, the `something` alluded to in the rule. ## Moving things ^^{things+kind+: changing location of} ^^{player: moving the player} ^^{|without printing a room description} ^^{|printing an abbreviated room description} ^^{rooms+kind+: descriptions: moving without printing one} ^^{+to+now (a condition): changing the locations of things} ^^{immobile things: |fixed in place} ^^{things+kind+: immobile: |fixed in place} ^^{immobile things: moving anyway} ^^{things+kind+: immobile: moving anyway} ^^{fixed in place / portable (thing)+prop+} ^^{portable / fixed in place (thing)+prop+} ^^{fixed in place (thing)+propcat+} ^^{portable (thing)+propcat+} ^^{carrying+rel+} ^^{carrying+relcat+} ^^{wearing+rel+} ^^{wearing+relcat+} We have now seen how to change the properties of rooms and things, and also any freestanding values which may have a bearing on the model world. We are not allowed to change the kind of anything during play. Our remaining freedom is to move things around. It would make no sense to move rooms around, because rooms are the fixed reference points in our geography, but anything else is mobile. This even includes things which are supposedly `fixed in place`, for unlike the player, we have god-like powers. (There are minor restrictions: backdrops are trickier to move, since they are present in several rooms at once – see the next section. And doors, at the junction between two rooms, cannot be moved.) Here is how to move something: > phrase: {ph_move} move (object) to (object) > > This phrase moves the first-named object to the second. Example: > > move the genie's lamp to Aladdin's Cave; > > The first object named has to be a thing; the destination must be a room, as here, a container, a supporter, or a person. When something is moved, all its parts and contents (and all their contents, and so on) move with it. If the thing being moved is a person, then the destination is required to be a room or an enterable container. (In particular, a person cannot be carried by another person.) > > Two options can be used if the object being moved is the player. > > move the player to Aladdin's Cave, without printing a room description > > omits the description which would otherwise be produced. A compromise is to use: > > move the player to Aladdin's Cave, printing an abbreviated room description > > which gives a full description if the player has never been here before, but only a brief one if it is a familiar scene. These options have no effect for any other objects being moved. If the destination is a person, like so: move the genie's turban to Aladdin; then it will be carried rather than worn. We could arrange for it to be worn instead by writing now the genie's turban is worn by Aladdin; `Now...` is a much more flexible phrase than `move`: more on this shortly. ## Moving backdrops ^^{+to+now (a condition): changing the locations of backdrops} ^^{backdrops+kind+: changing the location of backdrops} ^^{+to+move (backdrop) to (region)} ^^{regions+kind+: moving a backdrop to a new region} ^^{things+kind+: changing location of} ^^{(everywhere), placing backdrops+sourcepart+} ^^{|nowhere: placing backdrops} A backdrop can be in several rooms at once. When created, its position can be given as any specific collection of rooms, or as a region, or even as `everywhere`. For instance: The Upper Cave is above the Rock Pool. The Ledge is east of the Pool. The stream is a backdrop. It is in the Upper Cave and the Ledge. Moving backdrops is not like moving other things, because there's no single destination. There are several possibilities: (a) A backdrop can be moved to a region. If we define: Lower Level is a region. The Rock Pool and the Ledge are in the Lower Level. then we can write either of move the stream to the Lower Level; now the stream is in the Lower Level; and either way, the stream is now found in the Rock Pool and the Ledge but nowhere else. (b) A backdrop can be moved to a category of rooms: > phrase: {ph_movebackdrop} move (object) backdrop to all (description of objects) > > This phrase moves the backdrop so that it is now present in every room matching the given description. Example: If we define > > A room can be wet or dry. A room is usually dry. The Rock Pool is wet. > > then we can write > > move the stream backdrop to all wet rooms; > > This phrasing, `move the ... backdrop to all ...` is deliberately meant to look unlike the simpler `move ... to ...`, to emphasise that this kind of movement is possible only for backdrops. What then happens is that the stream is present in whichever rooms are currently wet. But the stream's position is ordinarily checked only after movements, for efficiency's sake. So if the player is in a room which suddenly changes from being dry to being wet, the stream will not magically appear (though it will be there if the player goes out and comes in again). If this is not good enough, the phrase `update backdrop positions` can be used to ensure the accuracy of all backdrop locations after a dramatic change: > phrase: {ph_updatebackdrop} update backdrop positions > > This phrase runs through all backdrops in the model world and makes sure they are correctly in, or not in, the current location, so that everything appears right from the player's point of view. Example: > > The Upper Cave is above the Rock Pool. The Ledge is east of the Pool. The stream is a backdrop. > > When play begins: > move the stream backdrop to all wet rooms. > > A lever is in the Cave. The lever is fixed in place. > > Instead of pulling the lever when the Cave is dry: > now the Cave is wet; > now the lever is in the Rock Pool; > now the lever is portable; > update backdrop positions; > say "The old rusty lever pulls away, and the thin cave wall goes with it, so that a stream bursts into the cave, falling to the pool below." (c) A backdrop can be moved to be either everywhere or nowhere: After sleeping: say "It's a bright new day!"; now the stars are nowhere. After waiting: say "Darkness falls rapidly here."; now the stars are everywhere. ## Moving the player ^^{player: moving the player} ^^{things+kind+: changing location of} ^^{|without printing a room description} ^^{|printing an abbreviated room description} ^^{+to+now (a condition): changing the player's location} ^^{rooms+kind+: descriptions: moving without printing one} ^^{+to+now (a condition): changing the player's identity} ^^{player: changing the identity of the player} ^^{yourself (- person)+const+} The player is a thing, too, and can also be moved, which has the effect of instantaneous transportation, without the need for a suitable map connection to the new location. For instance, these are equivalent: move the player to the Bodleian Library; now the player is in the Bodleian Library; This will ordinarily result in a room description of the Bodleian Library being printed up, but that might not always be desirable. For instance: Instead of waiting in the Schola Maleficorum: say "A bored demon catches your eye (they really do have very inquisitive fingers) and throws you back out into the Antechamber."; move the player to the Antechamber, without printing a room description. Thus tacking on the option `without printing a room description`, remembering to add the comma, omits the description which would otherwise be produced. A compromise is to use the option `printing an abbreviated room description`: this gives a full description if the player has never been here before, but only a brief one if it is a familiar scene. The player's point of view can also be moved by shifting to another character. Suppose the story features two people, Alice and Bob, and the player at the keyboard is giving commands to Alice, and seeing everything from her point of view. The phrase: now the player is Bob switches the perspective so that now Bob is the one controlled by the human player, and it's Bob's point of view which counts. The human being at the keyboard may feel a sense of having jumped abruptly from place to place, but in fact neither Alice nor Bob has moved. A change of player can sometimes cause confusing things to happen, if it takes place as part of a successful action. Suppose there's an action called `possessing`, which enables the player to possess somebody else's body; and suppose the player types ``POSSESS ADELE``. The action succeeds, so that the player moves into the mind of Adele. But that means that at the end of the action, the player is no longer the actor – that is, no longer the person who began the action; and consequently, Inform won't use the report rulebook to say what has just happened. It's a strange business, moving into another body. ## Removing things from play ^^{things+kind+: removing from play} ^^{deleting things from the world <-- destroying things} ^^{non-existence: removing things from play} ^^{non-existence: starting things out of play} ^^{things+kind+: starting out of play} ^^{out of play} ^^{on-stage / off-stage (thing)+adj+} ^^{off-stage / on-stage (thing)+adj+} ^^{+to+now (a condition): changing the locations of things} ^^{|nowhere: placing things} Some things will occasionally be in a limbo state called being `off-stage`: like actors or props not needed in Act II, but perhaps to be brought back on-stage later, they wait on the sidelines. Anything created with no apparent location will start the story off-stage, as in the case of the lamp here: Aladdin's Cave is a room. The genie's lamp is a container. (Such things are easy to see in the World index because they are listed after all of the rooms and their contents, not belonging inside any room.) If we wanted to make this clearer to a human reader, we could add: The lamp is nowhere. to emphasise the point. In this context, `nowhere` means `in no room`. Moving the lamp onto the stage-set, so to speak, is easy: now the lamp is in the Cave; or perhaps: now the player is carrying the lamp; and we can whisk it away again like so: now the lamp is nowhere; (We can't say `now the lamp is somewhere` because that's too vague about exactly where it is.) In older builds of Inform, the usual thing was to write `remove the lamp from play`, but that's now a deprecated phrase: better to use `nowhere` instead. > phrase: {ph_remove} remove (object) from play > > Removes the given object from play, so that it is not present in any room. We are not permitted to remove rooms, or doors, or the player, from play; but we are permitted to remove backdrops, making them disappear from all rooms in which they are present. Example: > > remove the gold coin from play; We can test whether something is on-stage or off-stage with: if the gold coin is somewhere, ... if the gold coin is nowhere, ... Inform also understands two adjectives for this: if the gold coin is on-stage, ... if the gold coin is off-stage, ... Because these are adjectives, they can be used in a few ways which `nowhere` and `somewhere` can't, such as: say "Ah, so many absent friends. Who now remembers [list of off-stage people]?" Note that `on-stage` and `off-stage` apply only to things. Rooms, directions and regions are the stage itself: so it makes no sense to ask the question of whether they are `on-` or `off-`. Doors are always on-stage; a backdrop, say `the sky`, is always on-stage unless it has been taken off by writing something like `now the sky is nowhere`. ## Now... {PM_BadNow1} {PM_BadNow2} {PM_BadNow3} {PM_CantForceRelation} {PM_CantForceExistence} {PM_CantForceGeneralised} {PM_CantForceCalling} {PM_CantChangeKind} {PM_RedefinedNow} ^^{+to+now (a condition): for arbitrary conditions} ^^{things+kind+: changing multiples with (now)+sourcepart+} ^^{properties: changing multiple things with (now)+sourcepart+} ^^{+to+if (a condition)} `Now` has already appeared several times in this chapter, being used like a Swiss army knife to change values of all kinds: now the score is 100; In fact, `now` is by far the most flexible phrase known to Inform. > phrase: {ph_now} now (a condition) > > This phrase makes the condition become true. Examples: > > now the score is 100; > now the player is Kevin; > now the front door is open; > now Mr Darcy is wearing the top hat; > now all the doors are open; > now all of the things in the sack are in the box; > > Inform issues a problem message if the condition asks to do the impossible (`now 3 is an even number`) or is vague (`now the duck is not in the Lily Pond`) or not in the present tense (`now the front door had been open`). We've now seen all three things which can be done with a condition S which describes the world: - **S.** - The relation holds at the start of play. - ** if S, ...;** - Does the relation hold right now? - ** now S; ** - Make the relation hold from now on. For instance, The apple is in the basket. if the apple is in the basket, ...; now the apple is in the basket; ## Increasing and decreasing ^^{calculation: incrementing} ^^{calculation: decrementing}^^^{calculation <-- arithmetic <-- maths}^^^{calculation <-- numbers: calculation with} Once we begin to deal with named values (or table entries, list entries or other ways to describe places where values are kept), we find that we often want to change them. We could if we wanted always use `now` for this, but it can be a little clumsily worded if we want to increase or decrease something: now the score is the score plus six; Because of that, we have some convenient abbreviations which have the advantage that the value being changed only has to be named once: > phrase: {ph_increase} increase (a stored value) by (value) > > This phrase increases the variable, table entry, list entry, or property by the given amount, which must be of a compatible kind. Example: > > increase the score by 8; > increase the time of day by 5 minutes; > phrase: {ph_decrease} decrease (a stored value) by (value) > > This phrase decreases the variable, table entry, list entry, or property by the given amount, which must be of a compatible kind. Example: > > decrease the score by 6; > decrease the carrying capacity of the player by 10; An even greater abbreviation can be made when we are changing a number by 1 either way: > phrase: {ph_increment} increment (a stored value) > > This phrase increases the variable, table entry, list entry, or property by 1. Example: > > increment the score; > phrase: {ph_decrement} decrement (a stored value) > > This phrase decreases the variable, table entry, list entry, or property by 1. Example: > > decrement the score; `Increment` and `decrement` are traditional computing terms, though they have been used in engineering for at least a century and in finance for longer still. ## Checking on whereabouts ^^{+to+if (a condition)} ^^{containment+rel+} ^^{containment+relcat+} ^^{carrying+rel+} ^^{carrying+relcat+} ^^{possession+rel+} ^^{possession+relcat+} ^^{support+rel+} ^^{support+relcat+} ^^{incorporation+rel+} ^^{incorporation+relcat+} ^^{worn (thing)+adj+} ^^{carried (thing)+adj+} ^^{held (thing)+adj+} We have seen that while rooms are fixed, their contents move around, so we will need ways to examine the current whereabouts of things. The following examples show the kind of conditions allowed: condition | subject | relationship | object ------------------------------------------ | ------- | ------------- | ------ `if the lamp is in Aladdin's Cave` | lamp | in | Cave `if Aladdin is not in Aladdin's Cave` | Aladdin | not in | Cave `if Aladdin's Cave contains the lamp` | Cave | contains | lamp `if the lamp is carried by Aladdin` | lamp | carried by | Aladdin `if Aladdin is carrying the lamp` | Aladdin | carrying | lamp `if Aladdin does not have the lamp` | Aladdin | does not have | lamp `if the table supports the lamp` | table | supports | lamp `if the table is supporting the lamp` | table | supporting | lamp `if the lamp is supported by the table` | lamp | supported by | table `if the lamp is on the table` | lamp | on | table `if the lamp is on top of the table` | lamp | on top of | table `if the lamp is in the cupboard` | lamp | in | cupboard `if the lamp is contained in the cupboard` | lamp | contained in | cupboard `if the lamp is inside the cupboard` | lamp | inside | cupboard `if the lamp is within the cupboard` | lamp | within | cupboard `if the wick is part of the lamp` | wick | part of | lamp These are exactly like the assertions which we use to set up the world, except that we make them questions by placing `if` in front. But we shall later see that we can also use three other tenses, not to mention plural forms, so that new verbal forms like `had not been inside` and `were not supported by` are legal here (which they would not be in assertions). What we are not allowed is to contract these verbs with apostrophes: "isn't", "hasn't" and "hadn't" are forbidden. Overwhelmingly the condition we check most is whether the player is carrying something. The following are therefore equivalent: if the lamp is carried by the player ... if the lamp is carried ... And similarly for `not carried`, `worn` and `not worn`. To be precise, if a form of *to be carried* or *to be worn* is not followed by any other description, then `the player` is assumed to be doing the carrying or wearing. ## More flexible descriptions of whereabouts ^^{+to+if (a condition): with generic conditions} The examples just given were all basically of the form "X *relation* Y" where X and Y were specific names of things. For example, if the lamp is carried by Cinderella ... if the lamp is inside the cupboard ... Just as actions could be described with patterns to be matched (`taking an open container`, say), so can the positions of things. Giving subtler descriptions of our X and Y sometimes broadens the possibilities, sometimes narrows them: if the lamp is carried by a woman ... if the lamp is inside the closed cupboard ... In the first case, Y is allowed to be one of a whole range of things – any of the women existing in the world. This makes for a broader condition. In the second case, Y has not only to be the cupboard, but at a time when it is closed: which makes for a narrower condition. We can, of course, also vary X: if an animal is inside the cupboard ... if a container is carried ... And we can even vary both X and Y at once: if a woman is holding an animal ... a condition which will be true if, anywhere in the story's world, any woman is holding any animal. ## Calling names {PM_CalledThe} {PM_CalledWithDash} ^^{|called: in describing things} ^^{punctuation: brackets: for calling values} ^^{|( ): for calling values} ^^{names: for things named generally} ^^{|something: naming value of} Conditions like `if somebody is in an adjacent room` allow complicated tests to be performed with a minimum of fuss, but it's rare that we want to know only whether they are true: more likely we also want to know *which* person, and *which* room. For this purpose, we are allowed to supply a name for any such vaguely-described object which comes up, and then to use that name thereafter. if somebody is in an adjacent room (called the Hiding Place), say "You hear distant breathing from [the Hiding Place]." We can even name more than one of the things discovered: Instead of waiting when a woman (called the kidnapper) is holding an animal (called the pet), say "How can you think of rest when, somewhere out there, [pet] has been cruelly kidnapped by [the kidnapper]?" Note the brackets, which are essential. The result of typing ``WAIT`` is then How can you think of rest when, somewhere out there, a lapdog has been cruelly kidnapped by Baroness Orczy? Of course, that might be just one of many animals held by women in the story. We shall later see ways to go through all of the possibilities found, performing some action with each in turn. A calling, if we can use that word, should be made immediately after the noun it refers to, and not left to hang back after any relative clauses. For instance, if something (called the penitential object) held by the player is hot is allowed, but not if something held by the player (called the penitential object) is hot because there is too much potential ambiguity – are we trying to call the player something? ### See Also - [Repeat running through] for systematically working on everything matching a description. ## Counting the number of things ^^{counting: things} ^^{things+kind+: counting} ^^{+to+number of (description of values)} It is very often useful to know how many things are in a given situation, and for this purpose we have the `number of ...` construction. For instance: the number of edible things carried the number of things on the table the number of people in the Dining Room Whereas `a woman is holding an animal` makes the same test as `an animal is held by a woman`, getting the same result, counting is not so even-handed: the number of women holding animals the number of animals held by women are different questions and, unless the ration is strictly one lapdog per baroness, will have different answers. If Cruella de Vil has 101 dalmatians, they may be very different indeed. It can also be helpful to count things with no particular location, like so: the number of rooms the number of closed doors For instance: When play begins: now the right hand status line is "Explored: [number of visited rooms]/[number of rooms]". Provided that the possible range is finite, we can also use `number of` to count values which match a description. For instance: the number of non-recurring scenes or if we were to define Colour is a kind of value. The colours are red, orange, yellow, green, blue, indigo and violet. then `the number of colours` would evaluate to 7. As with other ways of talking about whole ranges of values, this only works if the range is manageable. `The number of numbers` cannot sensibly be worked out: there are infinitely many, for all practical purposes, and similarly for `the number of texts`. ## Looking at containment by hand ^^{siblings, in containment hierarchy} ^^{containment+rel+: hierarchy, low-level interface} ^^{Inform 6 equivalent: |child} ^^{Inform 6 equivalent: |parent} ^^{Inform 6 equivalent: |sibling} ^^{held by: first thing held by (object)+phr+} ^^{held by: next thing held after (object)+phr+} The descriptions outlined in the last few sections are intended to deal with almost all of the routine questions we might have about what currently resides where. It should be a last resort to use the following more primitive way to inspect the world. > phrase: {ph_holder} holder of (object) ... object > > This phrase produces the container, supporter, carrier, wearer or room in which the object resides, or the thing which incorporates it, if it is a part of another object. It's sometimes useful to go the other way. When something has possessions, we can find them out one at a time by running through a list. > phrase: {ph_firstheld} first thing held by (object) ... object > > This phrase produces the first of the list of things contained in, supported by, carried by or worn by (but _not_ incorporated by) the object. Example: > > first thing held by Baroness Orczy > phrase: {ph_nextheld} next thing held after (object) ... object > > This phrase produces the next item of the list of things contained in, supported by, carried by or worn by (but _not_ incorporated by) whatever contains, supports or wears the object. Example: suppose Baroness Orczy is carrying a lapdog and a string of pearls. > > next thing held after the lapdog > > is then the string of pearls. ## Randomness ^^{randomness: seeding the generator} ^^{randomness: random numbers} ^^{randomness: value kinds} ^^{randomness: enumerated values}^^^{randomness <-- chance <-- numbers: random numbers} Sometimes we want to introduce random behaviour into play. We usually do this by generating random values, and then acting differently depending on what they are. The following: a random number from 2 to 5 produces, as it suggests, a random number drawn from the choices 2, 3, 4 or 5, each of which is equally likely to come up. In fact, this isn't limited to numbers: > phrase: {ph_randombetween} a random (name of kind) between (arithmetic value) and (arithmetic value) ... value & a random (name of kind) from (arithmetic value) to (arithmetic value) ... value & a random (name of kind) between (enumerated value) and (enumerated value) ... value & a random (name of kind) from (enumerated value) to (enumerated value) ... value > > This phrase produces a uniformly random value in the range given. Examples: > > a random number from 10 to 99 > a random time from 2:31 PM to 2:57 PM > a random time period from 6 minutes to 1 hour 25 minutes > > If we make a new kind of value: > > A cloud pattern is a kind of value. The cloud patterns are cumulus, altocumulus, cumulonimbus, stratus, cirrus, nimbus, nimbostratus. > > then we can also take random values from it: > > a random cloud pattern between stratus and nimbus > > which has three possible outcomes, all equally likely. We can also use random conditions: > phrase: {ph_randomchance} if a random chance of (number) in (number) succeeds: > > This condition is true X/Yths of the time, where X and Y are the numbers. Example: > > if a random chance of 2 in 3 succeeds, ... > > Here is a rule which applies only 15% of the time: > > Instead of waiting when a random chance of 15 in 100 succeeds: ... Testing IF which makes random choices can be rather frustrating, because a problem showing up on one attempt may not show up on another. We can get around this by making use of the fact that computers do not actually generate true randomness, but instead make a sequence of apparently random numbers by applying a complicated formula to each one in order to make the next. The starting point is a number called the "seed", because the next choice grows out of it. > phrase: {ph_seed} seed the random-number generator with (number) > > This phrase changes the seed number as specified. Any random numbers generated after that depend only on the seed. Example: the following sentence will "fix" the process of generating these random numbers so that they are not random at all – the same sequence of random numbers will be produced on each run. > > When play begins, seed the random-number generator with 1234. > > The seed value `1234` can be anything positive; a different sequence of random numbers will be produced for each different seed value. A seed value of 0 restores the RNG to properly random behaviour again. Alternatively, it's possible the "fix" the RNG by clicking the "Make random outcomes predictable when testing" option on the Settings panel. This makes the behaviour predictable whenever the story is played within Inform, but (unlike the rule above) has no effect on the story file once released. ## Random choices of things {PM_RandomImpossible} ^^{randomness: random things} ^^{descriptions (references to things): randomly described thing} Writing `a random number` is not allowed, because the possible range is too large, but that was the only reason why not. > phrase: {ph_randomdesc} a/-- random (description of values) ... value > > This phrase makes a uniformly random choice from values satisfying the description given. Example: > > a random visited room > a random scene > > A problem message is issued if the range is too large (for instance, `a random text`). Unexpected results may follow if no value fits the description, unless we are describing objects, in which case the result is the special value `nothing`. For instance: say "You can see [number of adjacent rooms] way[s] from here; how about [random adjacent room]?" But it's important to worry about the possibility that nothing qualifies – here, that no adjacent rooms exist. The above would then say: You can see 0 ways from here; how about nothing? # Time ## When play begins {ROOMPLAYBEGINS} {rules_wpb} ^^{when play begins+rb+} ^^{rules: run at beginning of story} ^^{initial state of the world: setting in (when play begins)+sourcepart+} ^^{starting conditions: setting in (when play begins)+sourcepart+} ^^{story structure: beginning} With the material from previous chapters, we are now able to set up a simulated world, to respond to the player's actions within it, and to make it change in perhaps unexpected ways. The resulting experience can be as lively as we want to make it, but so far we have no very good ways to give it any structure: a beginning and an end, for instance, or a sense of plot. This next chapter is all about the passage of time, and it begins at the beginning. We have already seen an example of how to write a rule which applies just once, at the start of the story: When play begins: say "Welcome to Old Marston Grange, a country house cut off by fog." The `when play begins` rules are checked only at the start of a story, not when a saved session is restored from disc. What happens is that these rules are followed, then the story's banner is printed, then the initial room description is printed up, and then the player is asked for a first command. ## Awarding points {var_score} ^^{use options: catalogue: |scoring} ^^{scoring+useopt+} ^^{scoring <-- points <-- rankings <-- full score} ^^{scoring: maximum score} ^^{scoring: enabling} ^^{scoring: reporting during story} ^^{score (- number)+glob+} ^^{maximum score (- number)+glob+} ^^{>NOTIFY ON/OFF} ^^{+to+increase (a stored value) by (value)} Traditionally-written stories award points throughout play, as an indication of progress. If we want to be traditional, we must first write: Use scoring. Without this, the ``SCORE``, ``NOTIFY ON`` and ``NOTIFY OFF`` commands do not work; the final score is not shown at the end of a story; and the status line above the player's text area shows only the turn count, not (as is more usual) both the score and the turn count. Changing the `score` (see below) has no visible effect, though it is not actually illegal. With `Use scoring` in place, we can award points as follows: increase the score by 5; substituting whatever number we feel is appropriate. We should be careful not to give out the same points over and over, that is, not to reward the same basic achievement many times over if the player simply repeats the same action. This, for instance, is open to abuse: After taking the trophy: increase the score by 5; say "Well done!" The player may simply take the trophy, drop it again, take it again, ... and win five points every time around. We can prevent this by phrasing the rule more carefully: After taking the trophy when the trophy was not handled: increase the score by 5; say "Well done!" (`Was handled`, not `is handled`, because this rule happens after the trophy has been taken – so by the time this rule has been considered, the trophy is always handled.) Rather than being an open-ended scoring system, IF normally has a maximum possible score, which can be specified with a sentence like so: The maximum score is 10. The score and maximum score are just numbers that vary, so we can freely change them: After eating the poisoned mushroom: now the score is -100. ## Introducing tables: rankings ^^{tables} ^^{tables: ranking score} ^^{tables: tabs in formatting tables} ^^{tabs vs spaces, in tables+ofsource+} ^^{spaces vs tabs (in tables)} ^^{scoring: ranking table} ^^{maximum score (- number)+glob+} Another tradition of interactive fiction is that the player has a current 'rank' according to how far their score has got. We can (but need not) choose to provide such rankings, and should do so by specifying a table like this: {*}Table 1 - Rankings Score Rank 0 "Beginner" 25 "Amateur Adventurer" 50 "Novice Adventurer" 100 "Junior Adventurer" 200 "Adventurer" 300 "Master" 330 "Wizard" 350 "Master Adventurer" Typographically, tables in Inform look as much as possible like those found in non-fiction books: they can have many columns, so this is only a simple example (drawn from the actual rankings used by ^{Infocom}'s *Zork I*, 1979). Each line in the source represents one row in the table, and the entries on a line must be separated by at least one tab character. (An entry might of course have several words with spaces in between, so a space is not enough to separate entries: this is the only context when Inform distinguishes between spaces and tabs.) The table must occupy a single whole paragraph, with no skipped lines or missing entries. We are free to use extra tabs to indent it if we like. Ordinarily we must explicitly ask to use the information presented in a table, but the table of rankings is a special case: Inform uses it automatically, if it is provided at all. To be recognised it must have the name `Rankings` and must have two columns named and arranged as shown. The scores should be given in ascending order. Customarily, the score in the final row should be the maximum possible achieved in the story – so that only a player with maximum possible score can be awarded the final ranking – and the value of `maximum score` is automatically set to this bottom-row value if it has not been explicitly set anywhere else in the source text. ## When play ends {rules_wpe} ^^{when play ends+rb+} ^^{rules: run at end of story} ^^{end of story <-- story structure: ending} ^^{victory} ^^{death} ^^{winning the story} ^^{losing the story} ^^{(finally), ending the story+sourcepart+} ^^{>AMUSING} ^^{story structure: ending} Short of something like a power cut, the story can only end when one of the two participants chooses to end it: either the player, by deciding that enough is enough, or us. In story-telling, there are many kinds of ending: happy, sad, decisive, bittersweet, surprise. Inform doesn't try to interfere in that kind of artistic choice, but it does need to know one thing about the ending: is it final, or not? Many authors like to make additional menu items available if the player has completed the story right through, but not if she has reached an early or wrong ending. (See the activity `amusing a victorious player`, for example.) > phrase: {ph_end} end the/-- story > > This phrase ends the story at the next opportunity (typically as soon as the current rule ends), with the closing message "The End." The end is not considered final. > phrase: {ph_endfinally} end the/-- story finally > > This phrase ends the story at the next opportunity (typically as soon as the current rule ends), with the closing message "The End." The end is considered final, and any hidden menu options will be revealed. > phrase: {ph_endsaying} end the/-- story saying (text) > > This phrase ends the story at the next opportunity (typically as soon as the current rule ends), with the closing message given in the text. The end is not considered final. Example: > > end the story saying "You have been stymied" > phrase: {ph_endfinallysaying} end the/-- story finally saying (text) > > This phrase ends the story at the next opportunity (typically as soon as the current rule ends), with the closing message given in the text. The end is considered final, and any hidden menu options will be revealed. Example: > > end the story finally saying "You have defeated Sauron" The closing message is traditionally set out in asterisks: ``` transcript *** The End *** ``` This style is traditional in IF, and goes back to 1980 if not earlier. We can test the current state like so: > phrase: {ph_ended} if story has ended: > > This condition is true if an end has been declared using one of the `end the story...` phrases. > phrase: {ph_notended} if story has not ended: > > This condition is true if no end has been declared using one of the `end the story...` phrases. > phrase: {ph_finallyended} if story has ended finally: > > This condition is true if an end has been declared using one of the `end the story finally...` phrases, so that an ending has been reached which the author feels is a completion of the player's experience. > phrase: {ph_notfinallyended} if story has not ended finally: > > This condition is true if an end has been declared using one of the `end the story...` phrases, but not `finally`, so the author feels that the player can get further experience by playing again and trying different approaches. The rulebook `when play ends` is the matching bookend to `when play begins`. It is followed when the story decides to end (not when the player simply gives up and quits), and before any epitaph like ``` transcript *** You have been poisoned *** ``` appears. For example: When play ends, say "Oh dear." Surprisingly, the end is not always the end: > phrase: {ph_resume} resume the/-- story > > This phrase causes an ended story to resume exactly as if no `end the story...` phrase had been used. Example: > > When play ends: > if the story has not ended finally: > say "Oh dear. Still, here's another chance."; > resume the story. > > The phrase is likely to be sensible only as part of a `when play ends` rule. Other traditional uses include giving the player three lives, as in an old-school arcade machine. ## Every turn {rules_et} {PM_NumberOfTurns} ^^{every turn+rb+} ^^{rules: run every turn} ^^{turns: rules run every turn} ^^{rules: arbitrary conditions for rules, using (when)+sourcepart+} ^^{when (condition)+sourcearg+: arbitrary conditions for rules} ^^{conditions: for rules} ^^{Inform 6 equivalent: |each_turn} ^^{Inform 6 equivalent: daemons} ^^{turn count (- number)+glob+} The passage of time in interactive fiction is broken up into a succession of turns, in each of which the player types a request and is given a response. Usually each such request triggers one action, but sometimes a whole sequence are fired off, as when the player types ``GET ALL`` in a cluttered room. As we've seen, the variable `turn count` holds the number of turns of play so far. By convention turn number 0 is the time when Inform prints up the banner and any initial text; it becomes turn number 1 when the player's first command is typed. One of the last things to happen in each turn is that Inform will apply any rules which have been set to occur `every turn`, like so: Every turn, say "The summer breeze shakes the apple-blossom." This is equivalent to writing: An every turn rule: say "The summer breeze shakes the apple-blossom." Note that the text about blossom, which will quickly become tiresome, is said at the end of every turn, not at the beginning, and in particular not before the player's first opportunity to type a command. As usual when defining rules, we can add stipulations: any condition can be attached using `when`. Every turn when the location is the Orchard, say "The summer breeze shakes the apple-blossom." Every turn when the player can see the rotting fish, say "Your nose twitches involuntarily." ## The time of day {kind_time} {var_time} ^^{time of day (- time)+glob+} ^^{turns: using time of day instead of turns} ^^{time: time of day} Inform keeps track of the time of day automatically: play ordinarily begins at 9 AM and each turn takes one minute. In some works of interactive fiction, time of day is crucial: in others, it is irrelevant or even, by a sort of tacit convention, non-existent. So Inform does nothing to act upon the time, or to reveal it to the player, without instruction. Nevertheless it is there. A sentence like the following allows the initial time to be set up as something other than 9 AM: The time of day is 3:13 PM. Here, `3:13 PM` is a constant value of a kind called simply `time`, and the value `time of day` is a time that varies. After one turn it will be 3:14 PM, then 3:15 PM and so on. Note that the sentence above is an assertion (a statement about the initial state of affairs), not an instruction which can be part of a rule. It would be equivalent to write: When play begins: now the time of day is 3:13 PM. We more often change `time of day` to take care of drastic events: At the time when the player loses consciousness: now the time of day is 10:12 AM; say "A mist comes over your vision, and when you come to, it is morning and you are in bed." ## Telling the time ^^{time: displaying times} ^^{English: displaying times in words} ^^{prompt, changing the prompt} ^^{command prompt (- text)+glob+} ^^{time of day (- time)+glob+} Now that we have the time of day, we can of course use this value in room descriptions and the like: The Clock Chamber is a room. "The dark chamber behind the clock face, a mill-room of gears which grind down the seconds. Through the glass you can see the reversed hands reading [the time of day]." It seems odd, though, to read a precise numerical description of the time here: after all, it isn't a digital clock. A friendlier version would use: > phrase: {phs_timewords} say "[(time) in words]" > > This text substitution produces the given time written out in English sentence form. For example: > > `"Through the glass you can see the reversed hands reading [the time of day in words]."` > > might produce > > Through the glass you can see the reversed hands reading twenty to nine. To reiterate an example which came up earlier, we could even work the time of day into the command prompt, which would lend the proper sense of urgency to a story played out against the clock: When play begins: now the command prompt is "[time of day] >". ## Approximate times, lengths of time ^^{time: displaying approximations} ^^{calculation: rounding to the nearest multiple} ^^{+to+(arithmetic value) to the nearest (arithmetic value) --> to the nearest} ^^{nearest: (arithmetic value) to the nearest (arithmetic value)+phr+}^^^{+to+(number) minutes --> minutes}^^^{+to+(number) hours --> hours} Clocks and watches vary considerably in how much detail they show, and we tend not to report the time over-precisely: half-past ten is an elastic concept. The following room description for the Clock Chamber comes across much more naturally: {*}The Clock Chamber is a room. "The dark chamber behind the clock face, a mill-room of gears which grind down the seconds. Through the glass you can see the reversed hands reading [the time of day to the nearest five minutes in words]." The phrase `... to the nearest ...` rounds off the given time, just as it sounds; as we'll see later, it can actually round off any arithmetic values, not just times. For instance, `9:58 PM to the nearest ten minutes` is 10:00 PM. Note that `ten minutes` here is also a value, and it's a value of a kind called `time period`, which is not quite the same as `time`. A `time period` can be positive or negative, and can be enormous: `360 hours 12 minutes` is a valid `time period` constant. In talking about lengths of time, rather than times of day, it's useful to have these: > phrase: {ph_durationmins} (number) minutes ... time > > This phrase converts numbers into lengths of time. Example: > > 15 minutes > > Because it's a phrase, not just a notation for writing constants down, the number doesn't have to be given literally: > > let X be 5; > if the player is in the Slow Room, now X is 10; > let deadline be the time of day plus X minutes; > > Note that lengths of time can't exceed 1440 minutes. > phrase: {ph_durationhours} (number) hours ... time > > This phrase converts numbers into lengths of time. Example: > > 10 hours > > Note that lengths of time can't exceed 24 hours. ## Comparing and shifting times ^^{time: calculations} ^^{time: comparing} ^^{calculation: with time}^^^{+to+(time) before (time) --> before}^^^{+to+(time) after (time) --> after} Carrying out easy calculations with times is straightforward: {*}The chronometer is in the Clock Chamber. "On one wall is a terribly self-important chronometer showing the time in major world cities. London: [time of day]. Paris: [one hour after the time of day]. Tokyo: [9 hours after the time of day]. Cupertino, California: [7 hours before the time of day]." Here we are using two phrases: > phrase: {ph_shiftbefore} (time period) before (time) ... time > > This phrase produces a time earlier by the amount given, keeping within the 24 hour clock. Example: > > 7 hours before 5:30 AM > > produces 10:30 PM. > phrase: {ph_shiftafter} (time period) after (time) ... time > > This phrase produces a time later by the amount given, keeping within the 24 hour clock. Example: > > 9 hours after 11 AM > > produces 8 PM. Similarly, we have conditions: > phrase: {ph_timebefore} if (time) is before (time): > > This condition is true if the first time occurs earlier in the day than the second. In recognition of the fact that very few stories begin before 4 AM, whereas many run on past midnight, the start of the day is taken to be 4 AM: thus 3:59 AM is after 11:10 PM, but 4:04 AM is before it. > phrase: {ph_timeafter} if (time) is after (time): > > This condition is true if the first time occurs later in the day than the second. In recognition of the fact that very few stories begin before 4 AM, whereas many run on past midnight, the start of the day is taken to be 4 AM: thus 3:59 AM is after 11:10 PM, but 4:04 AM is before it. These phrases are really just verbal conveniences, though, because we can do the same thing with everyday arithmetic. `10 minutes before 9:00 AM` is the same thing as calculating `9:00 AM minus 10 minutes`. ## Calculating times ^^{time: calculations} ^^{calculation: with time} ^^{numbers: converting to times} The ordinary arithmetic for numbers doesn't quite work for times. What would it even mean to add `1:00 PM` to `3:10 PM`, or, worse still, to multiply or divide them, or to take the square root of `9:00 AM`? But we _can_ subtract them: `3:10 PM minus 1:00 PM` does mean something — it produces `2 hours 10 minutes`, which is a value of the kind `time period`. And similarly we can add a time period to a time, to get a changed time: `9:00 AM plus 75 minutes` is `10:15 AM`, and `9:00 AM plus 24 hours` is just `9:00 AM` again. So, for example: {*}The Horological Chamber is a room. The clock error is a time period that varies. The broken grandfather clock is in the Chamber. "An erratic grandfather clock seems to say it is [the time of day plus the clock error]." To thump the mechanism: now the clock error is a random time period from -10 minutes to 10 minutes. When play begins, thump the mechanism. Instead of attacking the broken clock: thump the mechanism; say "You thump the clock, which now reads [the time of day plus the clock error].". We will occasionally need to perform more complex calculations with time, and in order to do that, it's a convenience to have a way to convert the time of day to numbers. Thus the phrase `the minutes part of ...` takes a time and produces a number from 0 to 59; similarly `the hours part of ...` extracts a number from 0 to 23, using the twenty-four hour clock. > phrase: {ph_minspart} minutes part of (time) ... number > > This phrase converts a time to a number, then takes the result mod 60, which in effect produces the number of minutes after the hours are thrown away. Example: > > minutes part of 12:41 PM > > produces 41. > phrase: {ph_hourspart} hours part of (time) ... number > > This phrase converts a time to a number, then divides the result by 60, which in effect produces the number of hours after minutes are thrown away. Example: > > hours part of 8:21 AM > > produces 8. If we need to convert a time period to a number of minutes, a nifty way to do this is to divide it by `1 minute`: 14 minutes divided by 1 minute The result being the number 14. And to go the other way, we can convert any number to a `time period` by writing `minutes` or `hours` after it. ## Future events {PM_AtWithoutTime} {PM_UnusedTimedEvent} {TIMEDEVENTS} ^^{time: events in the future} ^^{turns: events in the future} ^^{events in the future} ^^{future events} ^^{at (time)...+assert+}^^^{+to+(rule) in (time) from now --> in time}^^^{+to+(rule) in (number) turn/turns from now --> in turn}^^^{+to+(rule) at (time) --> at time} ^^{from now: (rule) in (time) from now+phr+} ^^{from now: (rule) in (number) turn/turns from now+phr+} ^^{now: (rule) in (time) from now+phr+} ^^{now: (rule) in (number) turn/turns from now+phr+} ^^{Inform 6 equivalent: timers} We often want to arrange for something to happen at some point in the future. Here is yet another timepiece: {*}An egg-timer is in the Chamber. "A plastic egg timer in the shape of a chicken can be pressed to set it going." Instead of pushing the egg-timer: say "It begins to mark time."; the egg-timer clucks in four turns from now. At the time when the egg-timer clucks: say "Cluck! Cluck! Cluck! says the egg-timer." The event here is called `the egg-timer clucks`, but this event name could have been anything we chose: as it happens, the event involves the egg-timer, but it doesn't need to have `egg-timer` in the name. Events like this happen only when instructed to happen, using one of the following phrases: > phrase: {ph_timefromnow} (rule) in (time period) from now > > This phrase causes the given rule to be run at a given time offset from the current time of day. Example: > > the egg-timer clucks in 18 minutes from now; > phrase: {ph_turnsfromnow} (rule) in (number) turn/turns from now > > This phrase causes the given rule to be run at a given number of turns after the current one. Example: > > the egg-timer clucks in four turns from now; > phrase: {ph_attime} (rule) at (time) > > This phrase causes the given rule to be run at a given time of day. Example: > > the egg-timer clucks at 11:35 AM; If we know in advance what time we want something to happen, we can more simply write: At 4 PM: say "The great bells of the clock tower chime four." (Note that in either case such rules begin with the word `at`: they are the only rules allowed to begin with the word `at`.) A small warning: timed events like these only have a chance to occur during the turn sequence, that is, once every turn. In most stories, one turn takes one minute, so there will in due course be a turn happening at exactly (say) 11:35 AM. But if the clock is being advanced faster than this, it's possible that there are turns at (say) 11:32 AM and then not until 11:37 AM. But an event set for 11:35 AM will nevertheless happen – it will run at the first available turn after that time, which will be 11:37 AM. Events can thus happen up to half an hour late, though Inform cancels them if the elapsed time is greater than that. The Scenes panel of the Index can be a useful way to see what events have been set. ## Actions as conditions {PM_PTAPTooComplex} ^^{actions: as conditions} ^^{rules: actions referred to in conditions} ^^{rules: past tense of conditions} ^^{conditions: actions as conditions} ^^{past tense, of conditions in rules} ^^{tense: of conditions in rules} ^^{English: tense: of conditions in rules} There are two ways that descriptions of actions can be used as conditions. First, we can simply describe an action, and then the condition will be true if that is what the player is trying to do, and not otherwise: if taking a container, ... This is actually an abbreviation for the longer, some would say preferable form: if we are taking a container, ... Secondly, we can talk about the past as well as the present, which is very useful since interactive fiction often contains situations which are changed by earlier events. There are limitations on what we can ask about the past, but one case which is often useful is to test whether a simple action has happened: if we have taken the lantern, ... So, for example, Instead of waiting when we have taken the lantern, say "No, your acquisitive nature is roused now, and simply waiting will no longer do." For the rule to apply, it is not enough that the action `taking the lantern` has been tried: it must have succeeded. On the other hand, it's enough for any actor to have taken the lantern: it doesn't have to be the player. Other forms of past-tense condition will follow in the next section. > [!WARNING] > There are other restrictions, too. The mention of "simple" action above is because this system within Inform only tracks the main noun involved, not any second noun, for example. That's fine for the action `taking the lantern`, but not for `putting the lantern on the shelf`. It also tracks only nouns which are things rather than rooms. All in all, this feature is best thought of as a convenience in handling simple commonly-needed cases: more elaborate tests will need to be made by hand. ## The past and perfect tenses {PM_PastSubordinate} {PM_PTAPMakesCallings} {PM_PastTableLookup} {PM_PastCallings} {PM_PastActionCalled} {PM_NonPresentTense} {PM_PastTableEntries} ^^{rules: past tense of conditions} ^^{rules: perfect tense of conditions} ^^{past tense, of conditions in rules} ^^{perfect tense, of conditions in rules} ^^{tense: of conditions in rules} ^^{English: tense: of conditions in rules} ^^{historical conditions} ^^{conditions: historical} ^^{time: conditions and rules referring back in time} ^^{(has been), for past conditions+sourcepart+} ^^{(had been), for past conditions+sourcepart+} ^^{(was), for past conditions+sourcepart+} ^^{conditions: historical: warning concerning variables and other varying qualities} ^^{historical conditions: warning concerning variables and other varying qualities} The remaining sections of this chapter go into more technical ways to think about the progress of the story through time, and can be skipped at a first reading. Conditions are clauses which require Inform to make a decision: is such-and-such true, or not true? We have already seen conditions attached to rules using `when`: Instead of waiting when the Sorting Hat is in the Hall: ... and, as we shall later see, we will often want to write instructions like: if the Sorting Hat is in the Hall, say "Hermione blinks apprehensively." The condition is `the Sorting Hat is in the Hall`, and during play this will sometimes be true and sometimes false. A condition in the form `X is Y` is of course written in the present tense, and refers to the current state of affairs. Three other tenses are allowed. First, the present perfect: if X has been Y ... is true if it has ever been the case that `X is Y` at the start of any turn (or any action). So, for instance, if the gate has been open ... will be valid if and only if the gate has ever been made open by any action (even if it is closed now), or if it started out by being open when play began. Next is the past tense: if X was Y ... holds if and only if `X is Y` was true at the start of the most recent action. This is convenient when trying to describe what has changed in the course of the action, but sometimes also when making the action itself happen. For instance: if the lantern was switched on, now the lantern is switched off; if the lantern was switched off, now the lantern is switched on; Completing the set is the past perfect: if X had been Y ... which records whether `X has been Y` was true at the start of the most recent action. All these verbs can of course be negated (though "wasn't" and "hadn't" are disallowed as poor style: we use `was not` and `had not` instead). So for example, if the player had not been in the Ballroom ... is true if the player hadn't visited the Ballroom at the start of the most recent action. Something we must watch out for is that variables might not have the same values in the past that they have now. As a result, writing conditions such as `if the noun has been open` is a bad idea, because in the past `the noun` very likely referred to something different. It is really only safe to talk in the past tense about definite, fixed things: `if the Great Gates of Kiev have been open` would be fine. ## How many times? ^^{historical conditions: times} ^^{conditions: historical: number of times} ^^{rules: counting repetitions for conditions} ^^{time: counting conditions with (for the Nth time)+sourcepart+} ^^{counting: conditions with (for the Nth time)+sourcepart+} ^^{(first time), counting conditions+sourcepart+} ^^{(once), counting conditions+sourcepart+} ^^{(twice), counting conditions+sourcepart+} ^^{|exactly: counting conditions} ^^{(only), counting conditions+sourcepart+} There are two further ways to examine the historical record. Given any condition, we can say - `if (...condition...) for the second time ...` - `if (...condition...) twice ...` - `if (...condition...) 2 times...` - `if (...condition...) two times...` (all of which are synonymous: the words once, twice, thrice, one, two, three, four, five, six, seven, eight, nine, ten, first, second, third, fourth, fifth, sixth, seventh, eighth, ninth and tenth all mean what they obviously should). The result is true if the condition holds now and has held for only one previous spell in the past. A condition holding for, say, fifteen consecutive turns without a break counts as only one `time` – so what we mean by `twice` here is that it is true now, was previously false for a while, and was previously true for a while before that, but no more. In effect, then, if the player is in the Ballroom for the third time ... is true if this is the third visit to the Ballroom. We can also say if the player is in the Ballroom for more than the third time ... or similarly `less than`, `at least`, `at most`. It would be more natural, though, to say if the player has been in the Ballroom three times ... The adjective `only` (or equivalently `exactly`) can be added to obtain if the player has been in the Ballroom only three times ... To recap, this means there have been exactly three visits to the Ballroom in history, whereas if the player is in the Ballroom for the third time ... means there have been exactly three visits, the third of which is still going on – an important distinction. ## How many turns? ^^{historical conditions: turns} ^^{conditions: historical: number of turns} ^^{rules: counting turns for conditions} ^^{turns: counting conditions with (for the Nth turn)+sourcepart+} ^^{counting: conditions with (for the Nth turn)+sourcepart+} ^^{|exactly: counting conditions} ^^{(only), counting conditions+sourcepart+} ^^{conditions: historical: warning concerning variables and other varying qualities} ^^{historical conditions: warning concerning variables and other varying qualities} So much for `times` – spells in which a condition is true. We can also test the length of time, in turns of play, that something has been true. Thus: if ... for three turns; means that the condition holds now, and held at the start of this turn, at the start of last turn, and at the start of the turn before that. In particular: if the floppy hat has been worn for three turns ... will be false if the hat is not currently worn (even if it has been often in the past) and, on the other hand, will be true if the hat has been worn for twenty turns. Here again we can be more specific. These are synonymous: - `if the floppy hat is worn for the third turn ...` - `if the floppy hat has been worn for only 3 turns ...` - `if the floppy hat has been worn for exactly three turns ...` all requiring that the hat wasn't worn four turns ago. As before, `more than`, `less than`, `at least` and `at most` so forth can also be used – say, `for at least 21 turns`. A warning: we must be careful when writing something like if the noun has been open ... since this tests whether it has ever been true that the noun of the then action was open: not whether the current noun-object has ever been open. Lastly, note that the beginning of play – when (usually) initial text and a banner is printed, followed by a room description – counts towards these counts. In effect, this is a turn: one in which the player compulsorily performs the looking action, rather than being asked for a command. (By convention it is numbered as turn number 0, and doesn't contribute towards the turn count.) # Scenes ## Introduction to scenes {SCENESINTRO} {kind_scene} ^^{scenes} As we have seen, Inform divides up space into individual places called `rooms`, and allows us to group rooms together into `regions` if we find that convenient. And Inform also divides time up, into individual turns. These too we can group together: the equivalent of a region is a `scene`. To put this another way, if we think of the interactive fiction as a stage play, then up to now it has simply contained endless dialogue and stage directions – there has been no convenient way to divide up its running time into dramatic episodes, in the same way that a playwright might make Act II take place in the same drawing-room as Act I, but (let us say) six months later, after many things have changed. The script contains cues for one scene to end and another to begin: when those cues are reached, the stage hands rearrange props, actors reposition themselves and so on. Inform also allows us to create scenes, with cues for them to start and end, and some stage machinery (so to speak) making it easy to move the action on. But interactive fiction is *interactive*, so the metaphor of the theatre only goes so far. We can have several different scenes going on at once – perhaps with the relevant events taking place in different rooms, which the player is free to walk between. And the player may make a choice which changes the story-line, causing scenes to happen which otherwise would not have happened, and so on. Scenes can even be `recurring`, that is, can repeat themselves. So organising the story-line into scenes is not simply a matter of making a list (Scene 1, then Scene 2, then Scene 3, *finis*). It is more like a chart in which one scene can lead in several possible ways to others – a sort of map of time, which as we shall see Inform displays in its "Scenes" index. ## Creating a scene {PM_ScenesNotPlay} {PM_ScenesDisallowCalled} {PM_ScenesOnly} {PM_ScenesUnknownEnd} {PM_ScenesOversetEnd} {PM_ScenesBadCondition} ^^{scenes: descriptions (displayed when scene begins)} ^^{descriptions (displayed): scene descriptions} ^^{description of (scene)+prop+} ^^{description of (scene)+propcat+} ^^{scenes: rules run at beginning <-- beginning of scene} ^^{scenes: rules run at end <-- end of scene} ^^{rules: run at beginning of scene} ^^{rules: run at end of scene} ^^{rules: for scenes} ^^{when (scene) begins / ends+sourcearg+} ^^{properties: of scenes} ^^{scenes: properties of scenes} As usual, we only need to say that something is a scene to make it so: Train Stop is a scene. We conventionally write scene names with capital letters, as this demonstrates. This works, and shows up in the "Scenes" index, but does nothing. We have given no instructions on when it begins – no cue, in stage-play terms – so it never will begin, and even if it did, nobody would notice since it does nothing. First, to give it a beginning: Train Stop begins when the player is in the Station for the third turn. In theory any condition can be used to cue the scene – here, it's `the player is in the Station for the third turn` – but it's wise to look for a state of affairs which will last at least a brief time, because scene changes only happen at the start and end of turns. (Something like `...when examining the timetable` may be true only for a part of the middle of a turn, and so go unnoticed.) Every scene has two rulebooks attached, one at each end, so to speak. These look very like `when play begins` and `when play ends`, and work in the same way. Thus: When Train Stop begins: now the Flying Scotsman is in the Station; say "The Flying Scotsman pulls up at the platform, to a billow of steam and hammering." When Train Stop ends: now the Flying Scotsman is nowhere; if the player is in the Station, say "The Flying Scotsman inches away, with a squeal of released brakes, gathering speed invincibly until it disappears around the hill. All is abruptly still once more." Thus when the scene begins, our imaginary stage-hands wheel in a steam train; when it ends, they get rid of it again. Note that we know where the player will be at the start of the scene, but by the end they may have wandered off across the fields, so we must be careful not to report something they might not be in a position to see. When Train Stop begins, we printed some text, but we did this by hand. We didn't need to, because Inform automatically prints out the description of a scene (if it has one) when the scene begins. Scenes can have properties, just like objects, and in particular they have the `description` property. For example, we could write: Arrival is a scene. "There's a flourish of trumpets." which saves us the trouble of writing the rule: When Arrival begins: say "There's a flourish of trumpets." We can also write rules like this which apply to a whole variety of scenes at once. For instance: A scene can be bright or dim. A scene is usually dim. Dawn is a bright scene. When a scene which is bright ends: say "So passes the bright [scene being changed]." Here, instead of naming a scene (`Train Stop`), we've given a description (`a scene which is bright`). When a scene begins, these general rules come before those which name the scene exactly; when it ends, the reverse is true. ## Using the Scene index ^^{Scenes page of Index panel+ui+} ^^{user interface: Index panel: Scenes page} ^^{Index panel+ui+: Scenes page} ^^{time: scene beginning/ending times} ^^{scenes: times of scenes beginning/ending} ^^{scenes: |Entire Game} ^^{Entire Game (- scene)+const+} ^^{SCENES+testcmd+} ^^{testing commands: >SCENES} But when we test the previous section's example, we find that after a brief wait, the train pulls up: but it never goes away again. We have given instructions on how the scene ends, but not when it ends, and as a result the scene goes on forever once started. Even with simple story-lines, and this one could hardly be simpler, it is surprisingly easy to overlook something so that the whole story-line is derailed. The Scenes page of the index is intended to help with this. The Plot section shows all of the scenes and how they are to begin, along with a key to the symbols used on it. One scene always included is "Entire Game", a special scene which, as its name implies, is always being played out. But if we look at the Scene index for the previous example, we will also see our Train Stop scene, and find that it is marked with the red warning symbol for "never ends". Let us fix this: Train Stop ends when the time since Train Stop began is 3 minutes. Note the useful value `time since Train Stop began`: > phrase: {ph_scenetimesincebegan} time since (scene) began ... time period > > This phrase produces the time since the named scene began, which only makes sense, of course, if it has indeed begun. Example: > > time since Entire Game began > phrase: {ph_scenetimesinceended} time since (scene) ended ... time period > > This phrase produces the time since the named scene ended, which only makes sense, of course, if it has indeed ended. Example: > > time since Formal Dinner ended The actual times, in case they are needed, can be obtained with: > phrase: {ph_scenetimewhenbegan} time when (scene) began ... time > > This phrase produces the time (i.e., the value of the `time of day` variable) at the moment when the given scene began. > phrase: {ph_scenetimewhenended} time when (scene) ended ... time > > This phrase produces the time (i.e., the value of the `time of day` variable) at the moment when the given scene ended. The testing command ``SCENES`` causes Inform to monitor the beginning and ending of scenes, and report on them. For instance: > ASK MONK ABOUT LODGING "Welcome a poor traveler for the night?" you ask, rubbing your fingers together to restore a little feeling. The monk looks you up and down for a moment and you sense his reaction hanging in the balance; then he slaps you on the back, hard enough to drive the air from your lungs. "In." [Scene 'Greeting' ends] The monk takes your elbow and pushes you imperiously toward dinner. [Scene 'Banquet' begins] ## During scenes ^^{conditions: for scenes} ^^{scenes: conditions for scenes} ^^{properties: of scenes} ^^{scenes: properties of scenes} ^^{during (scene)+sourcearg+} ^^{happening (scene)+adj+} ^^{recurring / non-recurring (scene)+prop+} ^^{non-recurring / recurring (scene)+prop+} ^^{recurring (scene)+propcat+} ^^{non-recurring (scene)+propcat+} ^^{scenes: recurring scenes} ^^{happened: if (scene) has happened+phr+} ^^{ended: if (scene) has ended+phr+} Scenes are not only useful for changing the setting, by moving items or people around and providing a little narration. We can also make the rules different in one scene from another. For instance, at a sleepy country halt there is no reason why one should not walk across the tracks: but if there is a train in the way, that would be impossible. Before going north during the Train Stop, say "The train blocks your way." instead. Any rule can have the clause `during ...` attached, provided that clause goes at the end and either explicitly names a scene, or gives a description of which scenes would match. This is especially useful with `every turn`: Every turn during the Train Stop, say "Water is sluiced out of the tank and into the engine." We can test whether a scene is happening with the adjective `happening`: if Train Stop is happening, ... > phrase: {ph_hashappened} if (scene) has happened: > > This condition is true if the given scene has both begun and ended. > phrase: {ph_hasnothappened} if (scene) has not happened: > > This condition is true if the given scene has not ended (or never started). > phrase: {ph_hasended} if (scene) has ended: > > This condition is true if the given scene ended at least once. > phrase: {ph_hasnotended} if (scene) has not ended: > > This condition is true if the given scene has never ended. We need to be a bit careful: it's possible to set things up so that the Train Stop scene will play out more than once, so `Train Stop is happening` and `Train Stop has happened` might both be true at once. The kind of value `scene` is one which is allowed to have properties – it has a tick in the "properties" column in the chart in the Kinds index – and this can be very useful in describing scenes. For instance, we could write: A scene can be thrilling or dull. Train Stop is dull. A scene has a text called cue speech. The cue speech of Train Stop is "All aboard!". Inform has the adjectives `recurring`, `non-recurring` and `happening` all built in to describe scenes, and the above would add `thrilling` and `dull`. Moreover, the `during` clause of a rule can give a description of a scene as easily as a specific scene name. For instance: Before going north during a dull non-recurring scene, ... ## Linking scenes together {LINKINGSCENES} ^^{scenes: linking to other scenes} Let us suppose that somebody gets off the train, after all, so that a second scene follows on. Brief Encounter is a scene. Brief Encounter begins when Train Stop ends. The effect of this is that they occur in sequence. If we add a third to the chain of scenes: Village Exploration is a scene. Village Exploration begins when Brief Encounter ends. ...we find another chance to fool ourselves: if we check the Scenes index again, we can see the linkages between these scenes, but we also see that Brief Encounter never ends (despite its name). All we have said is that another scene begins where Brief Encounter leaves off, but it never does, so this is moot. ## More general linkages ^^{scenes: linking to other scenes} ^^{scenes: beginning when play begins} ^^{starting conditions: scenes that begin at the beginning} ^^{initial state of the world: scenes that begin at the beginning} We are allowed to link the beginning or end of any scene to the beginning or end of any other scene. So, for instance: Luggage Trouble is a scene. Luggage Trouble begins when Brief Encounter begins. Thus the two scenes run concurrently, at least for a while. We can also add that: Luggage Trouble ends when Brief Encounter ends. This can be useful when a large, complicated scene really contains several smaller sub-scenes. A special exceptional case is that we can have any scene or scenes starting right at the outset: Railway Meeting is a scene. Railway Meeting begins when play begins. When play ends, of course, all scenes end, so there is no need to say that. ## Multiple beginnings and repeats ^^{scenes: linking to other scenes} ^^{scenes: recurring scenes} ^^{recurring / non-recurring (scene)+prop+} ^^{non-recurring / recurring (scene)+prop+} ^^{recurring (scene)+propcat+} ^^{non-recurring (scene)+propcat+} It is quite allowed for a scene to be linked to several other scenes, and this is useful if several alternate strands of plot are being brought together in a common resolution scene: Bittersweet Ending begins when Stranger's Rejection ends. Bittersweet Ending begins when Stranger's Acceptance ends. and we can also have the same scene beginning when a condition holds. In general, it will begin the first time it gets any chance to do so. All scenes are ordinarily set up so that they can happen only once. But sometimes we want them to repeat. Suppose the train calls not once only, but every twenty minutes. We could set this up with two scenes linked back to back like so: Train Stop is a recurring scene. Train Wait is a recurring scene. Train Wait begins when play begins. Train Stop begins when Train Wait ends. Train Wait begins when Train Stop ends. The difference here is that these scenes have been declared as `recurring`. In all other respects they are the same as any other scene. ## Multiple endings ^^{scenes: variations in ending} ^^{scenes: linking to other scenes} Interactive fictions vary considerably in the extent to which the player is allowed to influence the story-line. Sometimes the appearance of making choices is wholly bogus, as only one possible line is given more than lip service. But in other works, the player can radically change the outcome, and whole rafts of plot differ between one person's experience and another's. Inform allows multiple endings to its scenes to make this kind of branching story-line easy to achieve. Any scene can have up to 31 alternate endings, differentiated by name (unless the Z-machine format has been selected on the Settings panel, in which case, 15). These alternates are created as and when conditions are set for them: Brief Encounter ends happily when ... Brief Encounter ends wisely but sadly when ... `Ends happily` and `ends wisely but sadly` behave just like `ends`. We can have rules `When Brief Encounter ends happily, ...` and so forth, in addition to rules `When Brief Encounter ends, ...` – if a rule doesn't specify any particular ending, it applies to all of them. We can also link rules together from these branches, so Stranger's Acceptance begins when Brief Encounter ends happily. Stranger's Rejection begins when Brief Encounter ends wisely but sadly. With this set-up and that of the previous section, there are now two possible paths through the story: - (i) Train Stop - Brief Encounter - Stranger's Acceptance - Bittersweet Ending - (ii) Train Stop - Brief Encounter - Stranger's Rejection - Bittersweet Ending We might later need to know which of these paths has been taken, and to help with this Inform provides conditions like so: - `if Brief Encounter ended happily ...` - `if Brief Encounter did not end happily ...` - `if Brief Encounter ended wisely but sadly ...` - `if Brief Encounter did not end wisely but sadly ...` (For a scene which repeats, note that these conditions apply only to the most recent repetition: and that such conditions are always false if the scene is currently going on. `Brief Encounter did not end happily` will be true only when the scene has finished but in a different way.) ## Why are scenes designed this way? ^^{scenes: no way to force scenes to begin / end} ^^{limits: of scene changing mechanism} ^^{Scenes page of Index panel+ui+} ^^{user interface: Index panel: Scenes page} ^^{Index panel+ui+: Scenes page} In the part it plays in stories, time is like space. The endings of a scene (along with its beginning) are like the map connections leading out of a room. The Scenes index keeps track of the "map of time" through which these possible story-lines traverse. Some works of IF will have immensely complicated story-lines in only a few rooms, some will have no scenes at all despite a sprawling geography. The Scenes and World index tabs, side by side, show both kinds of map. Just as Inform uses a simple but practical design for the boundaries between rooms (map connections and doors, that is), it also simplifies transitions between scenes. Scenes are based on states of things: we give circumstances for them to begin or end. There is no phrase with the power to say "make Act II begin right now", so perhaps it is worth explaining why not. The state-based approach was chosen because: - it guarantees that each action falls entirely inside, or entirely outside, of any given scene (and therefore that `during...` clauses in the conditions for a rule are not affected by rule ordering); - it ensures that scene changes occur outside actions, like every turn rules; - it promotes a style of writing which makes it clearer to the reader of the source text when a scene begins and ends, and what conditions are guaranteed to be true during it; - it makes it possible for the Scenes index page to show this information in a communicative way. Settings in IF where one revisits the same location but at a different time, or after a dramatic change, have historically been difficult to test properly and prone to mistakes. (The classic example would be where a character killed during Act I reappears unharmed in Act II.) The design of scenes is an attempt to encourage a style of writing which minimises the risk of these accidents. Since scenes are, in the end, only a convenient way to organise rules, and do nothing that cannot be done by other means, this simplified system of scene changing does not really restrict us. # Dialogue ## If again this apparition come... ^^{dialogue: sections <-- (section)+ofsource+} ^^{dialogue beats <-- beats (dialogue) <-- dialogue: sections: beats} ^^{dialogue lines <-- lines (dialogue) <-- dialogue: sections: lines} ^^{dialogue choices <-- choices (dialogue) <-- dialogue: sections: choices} ^^{dialogue beats: |starting beat} ^^{|starting beat} Some stories are all about exploration: lone travellers going places and discovering things. But other stories are more intimate, and conversational. They involve characters talking to each other about what is happening. And sometimes the talking _is_ what's happening: the story might be a romance, or a political intrigue, or a detective mystery. "Dialogue" is what we'll call the sort of to-and-fro when characters get into a conversation — not necessarily a long talk, but where the story will only work for the player if the speakers seem to be making sense, and not repeating themselves endlessly, or making oblique comments out of nowhere. That means writing something closer to a script than to a rulebook. But that script can still be richly interactive and flexible. In Inform, this is set out in special _dialogue sections_ of the source text. Instead of being set out in sentences and paragraphs like a novel, or a non-fiction book, dialogue sections look like the script for a play or movie: what printers call "playtext". Regular sections cannot contain playtext, while dialogue sections cannot contain anything else. In this section, we'll get a taste for Inform's dialogue features by playing out parts of Act I, Scene 1 of _Hamlet_. Let's say that the player is Horatio, who has climbed to the castle battlements with his friend Marcellus to question Bernardo, a guard, about the recent sighting of a ghost. Section 1 - Elsinore The Battlements is a room. Marcellus and Bernardo are men in the Battlements. Fortinbras and the ghost are men. Section 2 - On the Battlements (dialogue) (This is the starting beat.) Player: "What, has this thing appear'd again to-night?" Bernardo: "I have seen nothing." Marcellus: "Horatio says tis but our fantasy." So here `Section 1 - Elsinore` is a regular section of source text: it creates a single room with two people in it, and two who are off-stage (for now). `Section 2 - On the Battlements` is a dialogue section, because its title ends with the bracketed word `(dialogue)` — this is what marks it out as special. Only section headings can be marked as `(dialogue)`, not chapter, part, book, or volume headings. There can be any number of dialogue sections in a story. The resulting story starts like so: ``` transcript Battlements You can see Marcellus and Bernardo here. You: "What, has this thing appear'd again to-night?" Bernardo: "I have seen nothing." Marcellus: "Horatio says tis but our fantasy." ``` That was the _performance_ of what is called a _beat_. Dialogue is divided up into _beats_ — small plot moments which usually consist of a few _lines_ of dialogue or narration. Each beat is opened by a _cue_ paragraph in brackets, followed by lines which occupy further paragraphs. So this dialogue section consists of a single beat, which contains three lines. The cue for the beat usually tells Inform when the beat should be performed. In this case, it's: (This is the starting beat.) and this tells Inform to perform it right at the start of the whole story, before the player has had a chance to type a single command. That little beat wasn't interactive in any way, and the player had to watch passively as it played out. Unless we want to party like it's 1599, we had better rewrite to offer _choices_ to the player: (This is the starting beat.) Player: "What, has this thing appear'd again to-night?" Bernardo: "I have seen nothing." Marcellus: "Horatio says tis but our fantasy." -- "Ask Bernardo what he saw." Player: "Well, sit we down, and let us hear Bernardo speak of this." Marcellus (now the ghost is in the Battlements): "Peace, break thee off! Look where it comes again." Bernardo: "In the same figure like the King that’s dead." -- "Dismiss this nonsense." Narration: "You sternly tell the guards to watch for Fortinbras, not their shadows." The beat now contains seven lines, but the action will split mid-way as the player decides, and so at least one of these lines will never be performed. The choice is between two alternatives marked `--`, and it leads to two alternative endings to the beat — note that these alternate paths are indented by one tab stop underneath the choices they continue from. So now play might run like so: ``` transcript Battlements You can see Marcellus and Bernardo here. You: "What, has this thing appear'd again to-night?" Bernardo: "I have seen nothing." Marcellus: "Horatio says tis but our fantasy." (1) Ask Bernardo what he saw. (2) Dismiss this nonsense. > 1 Ask Bernardo what he saw. You: "Well, sit we down, and let us hear Bernardo speak of this." Marcellus: "Peace, break thee off! Look where it comes again." Bernardo: "In the same figure like the King that's dead." > LOOK Battlements You can see a ghost, Marcellus and Bernardo here. ``` When it comes to the moment, then, the player is asked to choose which of two alternative courses of action to follow. Only ``1`` and ``2`` are accepted as answers to that choice prompt: ``` transcript (1) Ask Bernardo what he saw. (2) Dismiss this nonsense. > EXAMINE BERNARDO (Please type an option in the range 1 to 2 and press return.) ``` Once the beat has finished, the story goes back to accepted commands in the normal way that Inform stories do — in the example above the player typed ``LOOK`` and a looking action took place. How much dialogue appears in a story, versus traditional command-and-action play, is entirely up to the author. At the two extremes, there might be no dialogue at all, or the entire story might consist of one long branching mass of dialogue beats, each running into another, until the tale finishes — in such a way that the player never types a traditional command at all. But even if no commands are being typed, the rest of Inform is still at work beneath the surface. There's still a model world, keeping track of space and time. An example of that is that Inform won't perform a line of dialogue by somebody who is not within earshot. Suppose the beat had been written like so: (This is the starting beat.) Player: "What, has this thing appear'd again to-night?" Fortinbras: "Nope, it's just my army invading Denmark." Even though his line is in the script, the player would never see Fortinbras speak it because, at this moment, Fortinbras is still in Norway and not up on the Battlements — so that line is simply skipped over. Of course, if Fortinbras _had_ spoken this line, the others would certainly have reacted. We can have the script take care of that possibility too: (This is the starting beat.) Player: "What, has this thing appear'd again to-night?" Fortinbras: "Nope, it's just my army invading Denmark." Marcellus: "Sound the tocsin! My lords, we are besieged!" Again, the line by Marcellus is performed only if Marcellus is present to speak it, but there's a further restriction even if he is: he speaks only if Fortinbras has just spoken. That's because this line is indented underneath Fortinbras's line. Like the `--` choices, this is a branching point in the story. Had the script dragged in an even more unlikely speaker: Lady Bracknell: "A spectre?" then Inform would have complained. It allowed the line by Fortinbras to appear in the script because Fortinbras _is_ a character (that is, the story contains an object of the kind `person` whose name is `Fortinbras`); but Lady Bracknell must be from a different play altogether. So Inform is tracking who the speakers are, and where they are, and what has been said so far, in order to keep dialogue going realistically. We can also move people around to manage their entrances and exits. This isn't done with "Enter" and "Exit", the way Shakespeare would have done things. Instead we'll use Inform's much more flexible `now` phrase as a sort of stage direction: Marcellus (now the ghost is in the Battlements): "Peace, break thee off! Look where it comes again." If this line is performed, the ghost moves to the Battlements, but only then. And we can even have actors carry out actions: Bernardo (after taking the spyglass): "Sire, I must scan th' horizon." Here, _if_ the line is about to be performed, the action `Bernardo taking the spyglass` is tried: and if it succeeds, the line is indeed performed. Variety can enter the script even if the beat doesn't branch, because the lines performed in a beat are just like other text in Inform: they can contain "substitutions" in square brackets. So, for example: Bernardo: "Who [one of]stands[or]watches[or]hides[at random] there, good Marcellus?" Marcellus: "I count only [list of people in the Battlements]." These variations are only a small taste of what Inform's dialogue system can handle, and the rest of this chapter goes into that in some detail, so this won't be a short chapter. But as always, the easy things which are needed most often are quite quick to pick up, and the rest can be skipped until necessary. If this section has a moral (other than the inadvisability of killing a king in his own castle), it's this: Dialogue sections in Inform may look a little different from other Inform material, but the system they are built on is still Inform. There are still rooms, and things, and people, and actions, and a whole simulated world to help guide the performance, and to be changed by it. ## Dialogue sections ^^{dialogue: sections: formatting of} ^^{line breaks: in formatting dialogue} ^^{tabs, for indentation+ofsource+} ^^{indentation+ofsource+} ^^{source text: different in dialogue sections} ^^{dialogue beats} ^^{dialogue beats: |starting beat} ^^{|starting beat} ^^{dialogue lines: speaker of} ^^{speaker (- thing)+actvar+} ^^{dialogue lines: narration} ^^{narration (dialogue lines)} ^^{dialogue choices} ^^{|--: for dialogue choices} ^^{punctuation: double-dash: for dialogue choices} To recap, then, all dialogue material must appear in special _dialogue sections_ in the source text. A section is a dialogue section if its titling line ends with `(dialogue)`. For example: Section 2 - On the Battlements (dialogue) Dialogue sections can contain square-bracketed comments, just like regular sections, but otherwise they can only contain special dialogue material. ### Each item is its own paragraph Dialogue sections are organised by paragraphs, not sentences. Jamming lines, cues, and so on together without paragraph breaks between them will not work. For example, this: Julian: "I say, that's the swarthy fellow we saw at Brannigan's Rocks." Anne: "Yes, and that's gelignite he's carrying in that old red blanket." should have read: Julian: "I say, that's the swarthy fellow we saw at Brannigan's Rocks." Anne: "Yes, and that's gelignite he's carrying in that old red blanket." So, then, a dialogue section is a series of _beats_, and each beat begins with a _cue_ paragraph in round brackets, and then contains one or more of the following items, each in its own paragraph: 1) Lines spoken by a `person`, which can include the `Player`. Lines broadly have the syntax `Speaker: "Speech."` 2) `Narration` lines, where action is described but is not written as the direct speech of any person. These look like `Narration: "What is happening."` (To avoid confusion, do not call a character `Narration`.) 3) Choices, which are different options which the player might take at this point in the conversation. These are introduced with a double-dash `--`. 4) Flow markers. These have yet to appear, but are written with arrows `->` or `<-`. They guide the flow of dialogue through beats. ### Indentation by tabs shows how dialogue branches The other general feature of dialogue sections to watch out for is _indentation_, which is typed by using tab characters to move inwards from the left margin. When something is indented, it belongs to the thing above it which is indented by one tab stop less. Beat cues cannot be indented: they belong only to themselves. But lines, narration, choices and flow markers can all be indented. In general, indentation marks where a branch takes place: it's possible that the dialogue will flow down into this branch, but also possible that it won't. The general rule is that the branch is taken only if the item branched from is performed. For example: -- "Confiscate the gold" Player: "I'll take that bullion, you foreign rascal." Here the player's line of dialogue lies on a branch which is only performed if the `-- "Confiscate the gold"` choice is exercised. Similarly: Julian (to Dick): "Let's get some fresh eggs from Spiller's Farm." Dick: "Topping, and some cream and strawberries too." Here the branch containing Dick's line will be performed only if Julian's line is performed. (Because it's spoken `to Dick`, it requires both to be present.) In general, then, if one line is a direct reply to another one, and there is any uncertainty about who might or might not be present, indentation should be used: Speaker One: "A speech." Speaker Two: "A reply." Speaker One: "A rebuttal." Speaker Three: "An intervention." Speaker Two: "A cross response." Here, the cross response will only be performed if the speech _and_ the reply _and_ the rebuttal are all performed. But it makes no difference whether the intervention was made or not. Indentation can go down as well as up, and this allows branches to converge back together in what some other dialogue systems (such as Ink) call a "gather". For example: Marcellus: "It's just Scotch mist, blown east from old Aberdeen." Bernardo: "Nay, sire, it's a ghoul!" -- (if the shortbread is carried) "Assuage his night terrors" Player (before Bernardo eating the shortbread): "Here, take this old Highlands cure." Bernardo (now Bernardo is not scared): "Hoots mon, that's better." -- "Reprimand Bernardo" Player: "I don't care if it is haunted, guard the Battlements." Narration: "The bell tolls two of the morn." Here we have two lines of dialogue, and then a divide according to which option the player chooses. Note that the `Narration:` line is at the same indentation level as the two choices where the dialogue branches: so this is where the branches come together again. The practical effect is that every performance of the beat ends with the tolling of the bell. ## Dialogue beats and their cues ^^{dialogue: cues <-- dialogue beats: cues for <-- cues (dialogue)} ^^{dialogue beats: as values} ^^{values: dialogue beats as values} ^^{dialogue beats: as scenes} ^^{scenes: defined by dialogue beats} ^^{dialogue beats: conditions} ^^{conditions: for dialogue beats} ^^{dialogue: conversational subjects <-- conversational subject} ^^{dialogue: structure of conversation} ^^{dialogue: cues: named} ^^{this is the (name) beat+cue+} ^^{dialogue: cues: as scenes} ^^{this is the (name) scene+cue+} ^^{dialogue: cues: about a subject} ^^{dialogue beats: about a subject <-- subjects (of dialogue)} ^^{about (subject)+cue+} ^^{dialogue: cues: conditions} ^^{if (a condition)+cue+} ^^{unless (a condition)+cue+} ^^{dialogue: cues: before another beat} ^^{before (a beat)+cue+} ^^{dialogue: cues: after another beat} ^^{after (a beat)+cue+} ^^{immediately after (a beat)+cue+} ^^{later+cue+} ^^{next+cue+} ^^{dialogue: cues: required speakers} ^^{requiring (subject)+cue+} ^^{recurring+cue+} ^^{fully recurring+cue+} ^^{spontaneous+cue+} ^^{dialogue beats: properties} ^^{properties: of dialogue beats} ^^{performed / unperformed (dialogue beat)+prop+} ^^{unperformed / performed (dialogue beat)+prop+} ^^{performed (dialogue beat)+propcat+} ^^{unperformed (dialogue beat)+propcat+} ^^{recurring / non-recurring (dialogue beat)+prop+} ^^{non-recurring / recurring (dialogue beat)+prop+} ^^{recurring (dialogue beat)+propcat+} ^^{non-recurring (dialogue beat)+propcat+} ^^{voluntary / involuntary (dialogue beat)+prop+} ^^{involuntary / voluntary (dialogue beat)+prop+} ^^{voluntary (dialogue beat)+propcat+} ^^{involuntary (dialogue beat)+propcat+} ^^{spontaneous / unspontaneous (dialogue beat)+prop+} ^^{unspontaneous / spontaneous (dialogue beat)+prop+} ^^{spontaneous (dialogue beat)+propcat+} ^^{unspontaneous (dialogue beat)+propcat+} Each beat begins with a cue paragraph, which must be placed in round brackets. These usually contain a single sentence, but can have more, so long as it all remains a single paragraph. Such sentences must end with full stops, placed inside the brackets. So this is correct: (About the paranormal.) But this is not: (About the paranormal). As a more extensive, and valid, example: (About the Ghost. After the haunting beat. If the Ghost is in Elsinore. Recurring. This is the Marcellus gets anxious beat.) And semicolons can also be used instead of full stops, if we want to. This doesn't change the meaning. For example: (After the haunting beat; about the paranormal; recurring.) As these example cues suggest, the cue can do a lot, but the main idea is to say under what circumstances the beat should be performed. ### Naming a beat Inform has a built-in kind of value called `dialogue beat`, and each beat declared in the source text corresponds to a value of this kind. Beats are by default nameless, since authors mostly don't need to refer to them as values. But there are times when we do want that, so: (This is the Marcellus gets anxious beat.) Here, the beat for which this is the cue will have the value `Marcellus gets anxious beat`. The name has to end with the word `beat`. As we shall see, this enables rules or phrases in regular sections of the source text to ask, say, `if the Marcellus gets anxious beat is unperformed`, or to say `perform the Marcellus gets anxious beat`. The name `starting beat` is reserved. If a beat is given this name, then it is performed at the start of play, as in the Elsinore haunting dialogue with which this chapter began. Names of beats have to be unique, so it follows that there can only be one starting beat. ### Making a beat its own scene If a cue says that it is not just a beat, but also a scene, like so: (This is the fire drill scene.) then _two_ values are created: a beat called `fire drill beat`, and also a scene called `fire drill scene`. These values have different kinds — `dialogue beat` and `scene` respectively — but their fates are tied together. The scene automatically starts and ends when the beat begins and ends its performance, and vice versa. That is, if some other condition causes the scene to end while the performance of the beat is still mid-way, then the performance stops right there. This enables Inform's powerful scene-plotting machinery to mesh well with its dialogue engine. For example, `When the fire drill scene begins: ...` rules can be written, which will fire when the performance of the beat begins. ### Making a beat `about` something `About` clauses tell Inform what a beat is talking about. As we'll see in the next section, Inform is always tracking what people are discussing: it is maintaining a set of live conversational subjects. It can only do this if beats (and sometimes lines as well) are marked up to show what they are about. For example: (About the ghost and the Battlements.) Bernardo: "The battlements of Elsinore have been lately haunted, 'tis true." At its simplest, an about sentence is the word `about` followed by a list of one or more issues being discussed — in this example, two. These have to be descriptions of objects, so a beat cannot be `about 102`, for example, or `about 10:13 pm`, because numbers and times are not objects. On the other hand, they do not need to be specific names. For example: (About any dark room.) Bernardo: "Every dark place in this castle is filled with footsteps." ### Restricting the availability of a beat `If` and `unless` conditions in the cue for a beat make it performable only when the given condition is met, or not met. For example: (If Denmark is rotten.) (Unless Hamlet has the skull.) Note that this imposes _extra_ conditions which the beat has to meet in order to be performed: it may still not be performed for other reasons. For example, (About the Gravedigger; unless Hamlet has the skull.) introduces a beat which will only be performed if the Gravedigger is being discussed, _and_ Hamlet does not have the skull. ### The after, before, later, next, and immediately after clauses for a cue These say that the new beat can be performed only when another beat has already been performed at some point in the past; or, has not. For example: (After the Marcellus gets anxious beat.) This is equivalent, in fact, to writing the condition sentence: (If the Marcellus gets anxious beat is performed.) ...but is simpler to read and understand. Similarly: (Before the Marcellus gets anxious beat.) The special one-word sentence `Later` can only be used on the second or subsequent beats in a dialogue section, and means the same as `after` applied to the previous beat in that section. Thus (About fish.) ... (Later; about chips.) ... means the same thing as (About fish. This is the fishmonger beat.) ... (After the fishmonger beat; about chips.) ... `Immediately after` is equivalent to `after`, except that it allows the beat to be performed only the very next turn after the named beat was performed. The one-word `Next` is the corresponding version of `Later`, applying `immediately after` to the previous beat. For example: (About Pygmalion and mentioning Cyprus.) Galatea: "I haven't seen him around since I left Cyprus." (Next, about Cyprus.) Player: "Do you think he's still there?" Galatea: "Maybe! I don't yet have a good understanding of object permanence!" (About Cyprus.) Player: "Did you like Cyprus?" Galatea: "Yes, it was great, if you don't mind the weather." The effect here is that we'd see > ASK GALATEA ABOUT PYGMALION Galatea: I haven't seen him around since I left Cyprus. > ASK HER ABOUT CYPRUS Player: Do you think he's still there? Galatea: Maybe! I don't yet have a good understanding of object permanence! `Immediately before` is, of course, impossible to arrange, so Inform doesn't provide that syntax. ### Who is required to be present for a beat Consider this beat: (About the Zeppelin.) Hans: "See our prodigious rate of climb, Ludwig!" Ludwig: "Jawohl, Hans." There would not be much point in performing this beat unless Ludwig and Hans were within earshot of the player, because none of the lines could actually be spoken, and so it would complete silently. Because of that, each beat has a list of _required speakers_. If the source text explicitly says that the beat needs to be performed, then it will be performed whether or not the required speakers are present, but if Inform is making its own decision to perform the beat (or not), then it will always look to make sure the required speakers are at hand. (More exactly, if the player `can hear` them, a test performed with the `audibility relation`). By default, the required speakers are all those whose names explicitly appear as speakers of lines within the beat: so in the case of the beat above, that will be Hans and Ludwig. But if that is not what the author wants, the cue can be more explicit: (About the Zeppelin; requiring Hans.) Hans: "What a prodigious rate of climb!" Ludwig: "Jawohl, Hans." Inform might now choose to perform this beat even if Ludwig is not there, though of course Hans would then receive no reply to his remark. ### Giving a beat properties As was mentioned above, each beat is a value of the `dialogue beat` kind. That kind has several either-or properties. If the name of such a property is included in the cue, then the beat gets the property in question. Out of the box, dialogue beats come with the following either-or properties already defined: - `performed` or `unperformed`. Has this been performed yet? - `recurring` or `non-recurring`. Can the director choose this beat more than once in the same play-through? - `voluntary` or `involuntary`. This affects only beats for which the player is the first speaker, and only when the director is in active mode. (See [When the director is active] for what this means.) Can such a beat be triggered just because it seems relevant? - `spontaneous` or `unspontaneous`. Only has an effect when the director is in active mode. Can the director bring this beat up out of nowhere to fill a gap in the conversation, even though it has no relevance at the moment? By default, at the start of play, all beats are `unperformed`, `non-recurring`, `voluntary` and `unspontaneous`. But this is easy to change: (Spontaneous; recurring.) Bridget (recurring): "Are we nearly there yet?" As a special case, a beat can also be described as `fully recurring`. This makes not only the beat `recurring`, but also all the lines and choices which belong to it. For example: (Spontaneous; fully recurring.) Bridget: "Are we nearly there yet?" ## When the director is passive ^^{dialogue: director <-- director (dialogue)} ^^{dialogue: director: passive mode} ^^{talking about+action+} ^^{DIALOGUE+testcmd+} ^^{testing commands: >DIALOGUE} ^^{concepts+kind+} Dialogue is managed during play by a component of Inform called the _director_, which we think of as being like the director of a play. It sometimes has to manage quite a complex situation, so the testing command ``DIALOGUE`` causes the director to explain itself as it goes along; and ``DIALOGUE ALL`` even more so. At any given time the director is either _passive_ or _active_. Passive means that the director performs dialogue as it's asked to do so, but not otherwise. The director is always passive at the start of play and becomes active only if we explicitly ask it to: see [When the director is active]. When the director is passive, beats are performed only as follows: - If there is a beat called the `starting beat`, it is performed at the start of play, after the initial room description but before the player has been asked for a command. This is done by the `performing opening dialogue beat rule` in the `startup rulebook`. - In response to the phrase `perform B`, where `B` is a named beat. - In response to the phrase `if dialogue about X intervenes`, where `X` is a potential conversational subject. - When a beat which is already being performed calls explicitly for another beat to be performed with a flow marker. (See [Flow Markers] for more.) - When the action `talking about` is tried. This action represents somebody trying to raise a subject in conversation. For example: Romance is a concept. Instead of kissing the Princess: try talking about romance. If there's a suitable beat of dialogue available which is `about romance`, it will then be performed. The same will happen if the player types commands like ``ASK ABOUT ROMANCE`` or ``TALK ABOUT ROMANCE``, because those commands are understood as the action `talking about romance`. Note that `talking about` is just one way to nudge the dialogue director into action. A rule like `Instead of talking about romance` would block attempts to do this which arose from the `talking about` action, but would not block such dialogue arising from some other cause. ## When the director is active ^^{dialogue: director} ^^{dialogue: director: active mode} ^^{dialogue: conversational subjects} The director remains in passive mode until and unless we say so, using: > phrase: {ph_directoractive} make the dialogue/dialog director active > > Switches the dialogue director to active mode. Which can be undone again: > phrase: {ph_directorpassive} make the dialogue/dialog director passive/inactive > > Switches the dialogue director to passive mode. All of the ways dialogue can begin in passive mode are still true for active mode (see [When the director is passive]). But in active mode, the director can also fill conversational lulls by trying to find relevant things to talk about, and people to talk about them. To do this, the director tracks a list of "live conversational subjects" which it might be interesting to talk about. The idea is that if somebody has just mentioned visiting Barcelona, then Barcelona might become a live subject. If conversation then lapses, the director will try to keep it going by finding something which somebody present can say about Barcelona. A lull in conversation is a turn in which no other dialogue has been performed. It's sometimes useful to know whether or not that's the case, so a simple phrase is provided: > phrase: {ph_dialoguethisturn} if dialogue has been performed this turn: > > This means exactly as it reads. The business of filling this dead air is then carried out by the `dialogue direction rule` in the `turn sequence rulebook`. What happens is that the director looks for a suitable beat to perform, where "suitable" means that: - the beat either has not been performed before or has the `recurring` property, _and_ - all required speakers for the beat are within earshot, _and_ - any `if`/`unless` conditions in the cue are met, _and_ - any `after`, `before`, `later`, `next`, and `immediately after` conditions in the cue are met. That quite likely still leaves multiple beats to choose from, so the director makes a selection based on its _list of live conversational subjects_: 1) The director first tries to choose a suitable beat which is `about` a live conversational subject, except that it will not choose a beat for which the player is the first speaker unless that beat has the `involuntary` property. 2) Failing that, the director tries to find a suitable beat marked as having the `spontaneous` property. 3) Failing even that, the director will give up, and the story will continue in silence for another turn. The list of live conversational subjects is best thought of as pretty ephemeral, and with a rapid turnover: - A subject becomes live whenever a line of dialogue `mentioning` it is performed. For example, if Bernardo says this line: Bernardo (mentioning Denmark): "This bodes some strange eruption to our state." then `Denmark` becomes a live conversational subject. - Similarly, if a whole dialogue beat is `about` something, then that becomes a live conversational subject as soon as performance of the beat begins. - Newly raised subjects appear at the beginning of the list, and less fresh ones at the end. - The list is truncated so that at most 20 different subjects can be live, with the least fresh subjects discarded as having likely been forgotten about. - When the director (in active mode) is forced to perform a `spontaneous` dialogue beat — in effect, changing the subject entirely — the list is wiped altogether. Something to bear in mind is that the director tracks this list all of the time, even though it only uses it in active mode. So if it is switched into active mode having been passive up to now, it may be starting with some subjects already live. ## Entrances and exits ^^{dialogue lines: stage directions in} ^^{use options: catalogue: |nameless room descriptions} ^^{nameless room descriptions+useopt+} ^^{(Stage), implicit room+sourcepart+} ^^{on-stage / off-stage (thing)+adj+} ^^{off-stage / on-stage (thing)+adj+} It's possible to write an entire story made of nothing but dialogue, beginning with a starting beat being performed, and then more beats flowing from that until the story ends. In a story like that, there's no need even to create any rooms. For example: "Not much to say" Section of conversation (dialogue) (This is the starting beat.) Narration: "Welcome!" -- "Hello!" -> end the story saying "A world full of promise." -- "Goodbye." -> end the story saying "A missed opportunity." This is a complete story, though not much of one, of course. It does take place in a room, because Inform automatically creates a room called `Stage` where the above takes place, but this is never visible to the player since the `Use nameless room descriptions` option is automatically selected. Characters can be created and introduced by being moved to the `Stage` as needed. Here, `Raphael` is off-stage at the start of play, but is moved into play by the opening line of narration, thanks to the stage direction `now Raphael is on-stage`: "Perugia 1508" Raphael is a man. Section of conversation (dialogue) (This is the starting beat.) Narration (now Raphael is on-stage): "Raffaello Sanzio da Urbino approaches from the Tiber bridge." Raphael: "No, no, I really can't take on one more thing. The Holy Father wants another Madonna by Friday." -- "And I want an Adoration of the Magi right now." -> end the story saying "You somehow end up 852 ducats the poorer." -- "Be reasonable, Raff." Raphael: "You couldn't afford me, Primo." -> end the story saying "You somehow end up with a chalk sketch of three indeterminate-aged women which is, nevertheless, another casual work of genius." If `Raphael` had not been moved to the `Stage`, he could not have spoken, because he wasn't in earshot. Multiple people can enter at the same moment: Narration (now Raphael is on-stage; now Leonardo is on-stage): "Raffaello Sanzio da Urbino approaches from the Tiber bridge, arguing intensely with Leonardo di ser Piero da Vinci." Or indeed: Narration (now everyone is on-stage): "Raffaello Sanzio da Urbino approaches from the Tiber bridge, flanked by a knot of his pupils and rivals." Similarly, `now X is off-stage` is equivalent to an exit for `X`. The timing here is a little important. This does not work as expected: Michelangelo (now Michelangelo is on-stage): "Sorry, didn't mean to drip paint on you." The trouble is that Michelangelo can only perform the line if he is on-stage, but he only becomes on-stage through the line being performed: catch-22. He had better arrive in some earlier narration, or after somebody else has spoken. On the other hand, this does work: Raphael (now Raphael is off-stage): "'I'm expected in Città di Castello,' Raff says, turning on his heel and striding away." Here the timing works in our favour, because Raphael performs the line and is then taken off-stage by the `now`. This way of marshalling our characters is probably best suited to single-room stories, or those which (as in the examples above) don't even specify a single room. If we have a world of multiple locations, it's better to say exactly where the characters go to and come from: Raphael (now Raphael is in Saint Nicholas): "'I'm expected in Città di Castello,' Raff says, turning on his heel and striding away." And if we have joined multiple rooms together into a map, we can even have the actors walk around this map: Raphael (before going northwest): "'I'm expected in Città di Castello,' Raff says, turning on his heel and striding away." ## Managing dialogue beats ^^{dialogue beats} ^^{dialogue: director: invoking within a specific action} ^^{dialogue beats: as part of an action} ^^{performed / unperformed (dialogue beat)+prop+} ^^{unperformed / performed (dialogue beat)+prop+} ^^{performed (dialogue beat)+propcat+} ^^{unperformed (dialogue beat)+propcat+} ^^{recurring / non-recurring (dialogue beat)+prop+} ^^{non-recurring / recurring (dialogue beat)+prop+} ^^{recurring (dialogue beat)+propcat+} ^^{non-recurring (dialogue beat)+propcat+} ^^{voluntary / involuntary (dialogue beat)+prop+} ^^{involuntary / voluntary (dialogue beat)+prop+} ^^{voluntary (dialogue beat)+propcat+} ^^{involuntary (dialogue beat)+propcat+} ^^{spontaneous / unspontaneous (dialogue beat)+prop+} ^^{unspontaneous / spontaneous (dialogue beat)+prop+} ^^{spontaneous (dialogue beat)+propcat+} ^^{unspontaneous (dialogue beat)+propcat+} ^^{available / unavailable (dialogue beat)+adj+} ^^{unavailable / available (dialogue beat)+adj+} ^^{relevant / irrelevant (dialogue beat)+adj+} ^^{irrelevant / relevant (dialogue beat)+adj+} ^^{being performed (dialogue beat)+adj+} ^^{testing phrases: showme the beat structure of (dialogue beat)+phr+} ^^{dialogue: conversational subjects: making live / dead} There are many ways to manage dialogue. At one extreme we can put the dialogue director into active mode, and let the automatics do everything, so that conversation happens whenever appropriate in the course of play. Or we can keep it passive, but then run the entire story as one big script of dialogue. If we don't want either of those, though, and want a turn-based story in which there's just occasional dialogue which we will control explicitly as the author, Inform provides an extensive set of phrases to help with that. For example: "Just Idol Talk" The Jade Temple is a room. A green idol is here. Louisiana Smith is a man in the Jade Temple. Instead of taking the idol: perform the warning-off beat. Section of conversation (dialogue) (About the green idol. This is the warning-off beat.) Louisiana: "Don't touch that thing, kid." The important point there was the `perform` phrase: > phrase: {ph_performbeat} perform (a dialogue beat) > > Immediately perform the given beat of dialogue, regardless of any restrictions placed on it by its cue paragraph, or whether it has been performed before. What's good about `perform` is that it's simple to predict: it does exactly what it's told to do. Unfortunately, that's often not really what we want. For example, what happens if the player tries taking the idol twice? ``` transcript > GET IDOL Louisiana: "Don't touch that thing, kid." > GET IDOL > ``` This is very unsatisfactory. What happened here is that the warning-off beat was indeed performed a second time, but because its only line had been performed already, that line was skipped. So nothing was done at all, and yet the action stopped. We could in fact make Louisiana willing to repeat himself: (About the green idol. This is the warning-off beat.) Louisiana (recurring): "Don't touch that thing, kid." But is this very much better? ``` transcript > GET IDOL Louisiana: "Don't touch that thing, kid." > GET IDOL Louisiana: "Don't touch that thing, kid." ``` So this is a more nuanced way to write it: Check taking the idol: if dialogue about the idol intervenes: stop the action. The key phrase here is: > phrase: {ph_dialogueintervenes} if dialog/dialogue about (an object) intervenes > > Tries to perform dialogue about the given conversational subject, and has the result `true` if such a beat has successfully been performed, and `false` if no good beat could be found. All conditions on the beat must have been met, and it must either have been `unperformed` or else `recurring`. This is a sort of compromise between telling the director exactly what to do, and letting the director do as it pleases. We're giving it permission to try to start a conversation about a given subject — in this case, the idol — but on the understanding that it may well not find anything to say. That's why this is framed as an `if...` condition. A modest variation: > phrase: {ph_dialogueintervenesled} if dialog/dialogue about (an object) led by (an object) intervenes > > Tries to perform dialogue about the given conversational subject, and has the result `true` if such a beat has successfully been performed, and `false` if no suitable beat could be found. If there's a choice of beats available, the director will prefer one in which the first speaker is the person `led by`. But if no such beat can be found, it will still perform some other beat provided at least the subject can be matched. This, then, would give Louisiana first chance to react if multiple people might want to speak: Check taking the idol: if dialogue about the idol led by Louisiana intervenes: stop the action. As has already been said, `dialogue beat` is a kind, and each different beat declared in the source text is a value of this kind: that's how `perform` works, applied to any `dialogue beat` value. We've also seen that dialogue beats have four either-or properties available to them: - `performed` or `unperformed`. By default, `unperformed`. - `recurring` or `non-recurring`. By default, `non-recurring`. - `voluntary` or `involuntary`. By default, `voluntary`. - `spontaneous` or `unspontaneous`. By default, `unspontaneous`. Being properties, these can all be changed during play: When the conference scene begins: now the fire alarm beat is spontaneous. New properties for dialogue beats can also be created: A dialogue beat can be testing only or meant for production. Which enables beats to be tagged in arbitrary ways: (Testing only.) Bernardo: "Sorry to break the fourth wall, but will this program ever work?" In addition, the following adjectives can be tested at run-time: - `available` rather than `unavailable` if the beat currently meets its preconditions for being performed — its `after` or `before`, `if` and `unless` conditions. - `relevant` rather than `irrelevant` if the beat is `about` a topic in the current list of live conversational subjects. - `being performed` if the beat is currently in mid-performance. The following phrases are available: > phrase: {ph_listofspeakers} list of speakers required by (a dialogue beat) ... list of objects > > Results in the set of speakers required to be present for the beat to be performed. > phrase: {ph_firstspeaker} first speaker of (a dialogue beat) ... object > > The first specific person who speaks a line in the beat. Note that this may be `nothing`, if the beat contains only narration, or is vague about who speaks the lines. > phrase: {ph_showmebeat} showme the beat structure of (a dialogue beat) > > For debugging. In effect, beats are miniature programs, but can be quite intricate: this prints a listing. The following relations are also sometimes useful: - `B is about S` is true if `S` matches something in the `about` list for `B`. Note that this can be true for multiple values of `S`. This relation is called `topicality`. - `B is performable to S` is true if `B` is either `recurring` or `unperformed`, and if all of the speakers on the `requiring` list for `B` can be heard by `S`. This relation is called `performability`. So, for example, `the warning-off beat is about the green idol` throughout play of the little example above, whereas `the warning-off beat is performable to the player` only up to the point where is is first performed: since it's not a `recurring` beat, it then isn't performable again. Note that the command parser is able to recognise dialogue beat names, and of course actions can be set up for them. For example: Performing is an action out of world applying to one dialogue beat. Carry out performing: say "[the dialogue beat understood] requires [list of speakers required by the dialogue beat understood]."; repeat with L running through dialogue lines: if L is in the dialogue beat understood: now L is unperformed; perform the dialogue beat understood. Understand "perform [dialogue beat]" as performing. So, for example, ``PERFORM WARNING-OFF BEAT`` would run through it as if for the first time. The above phrases all work in both passive and active mode. In active mode, much depends on the list of live conversational subjects, so Inform also provides some phrases for examining and tinkering with that list — though in practice its automatic management is often fine. > phrase: {ph_makelive} make (an object) a live conversational subject > > Add this to become the frontmost member of the list of live conversational subjects tracked by the dialogue director. > phrase: {ph_makedead} make (an object) a dead conversational subject > > Remove this from the list of live conversational subjects tracked by the dialogue director. > phrase: {ph_clearsubjects} clear conversational subjects > > Empty the list of live conversational subjects tracked by the dialogue director. > phrase: {ph_getlivelist} live conversational subject list ... list of objects > > Returns the dialogue director's list of live conversational subjects. > phrase: {ph_setlivelist} alter the live conversational subject list to (list of objects) > > Sets the dialogue director's list of live conversational subjects to an arbitrary collection. These phrases are useful when something sudden and unexpected happens, which would obviously grab everyone's attention: At 11:10 pm: now the elephant is in the Drawing Room; say "An elephant crashes in through the French windows!"; clear conversational subjects; make the elephant a live conversational subject. And these phrases can also be used to strengthen the automatic list management performed above. For example: After printing the name of (T - an object) when performing a dialogue line: make T a live conversational subject. With such a rule in force, performing this line: Bernardo: "The castles in [Barcelona] are warmer at night." would automatically make Barcelona a live subject. Emptying the list regularly is one way to be especially sure that no residual topics linger impossibly long: say, if the story jumps from the night before to next morning. For example, we might want this: When a scene begins: clear conversational subjects. One way to watch how the list is managed in practice is to add a rule like so, just for testing purposes: Every turn: showme the live conversational subject list. ## About about ^^{dialogue: cues: about a subject} ^^{dialogue beats: about a subject} ^^{about (subject)+cue+} ^^{dialogue lines: mentioning a subject} ^^{concepts+kind+: in dialogue} ^^{dialogue: conversational subjects: beats about} ^^{dialogue: conversational subjects: lines mentioning} The whole idea of making the dialogue director "active" is that it enables conversation to develop naturally, in a way which dovetails with everything else that happens in the story. This works best if dialogue beats are marked up with what they are `about`, and if good use is made of marking lines as `mentioning` things. A beat can be `about` any object, but it's mostly sensible to have beats about things — interesting items in the story, or people — or else objects of the `concept` kind, which are used for more abstract ideas. We can freely create those, like so: Denmark and Horatio's philosophy are concepts. And then dialogue sections can make use of them: (About the ghost.) Marcellus (mentioning Denmark): "Something is rotten in the state of Denmark." (About Horatio's philosophy.) Hamlet (to Horatio): "There are more things in heaven and earth, Horatio, than are dreamt of in your philosophy." Being `about X, Y and Z` means that it involves all of the subjects `X`, `Y` and `Z`. This plays in two directions: - The beat is suitable to be performed whenever _any_ of `X`, `Y` or `Z` are live conversational subjects. - If the beat does indeed begin performance, they _all_ become live. For example, the first beat below is `about Velma and the robbery`. As we begin, Velma is live, but the robbery is not. Performance of the first beat changes that, and makes the second beat suitable to be performed soon. (about Velma and the robbery) Fred: "Velma totally hasn't been the same since that bullion robbery." (about the robbery) Fred: "Velma used to work the Lufthansa cargo desk at Stuttgart, and..." `About` clauses only have to describe objects, not necessarily name them exactly. For example: A concept can be frightening or safe. The paranormal is a frightening concept. Garden design is a safe concept. ...then: (About any frightening concept.) would make the beat suitable if the paranormal were in play, but not for garden design. Similarly: (About any woman in the Dining Room.) Or one might, for example, create a `discrediting` relation from concepts to people, and then have: (About any concept which discredits Gordon.) Douglas (to Carolyn): "And you say the marriage wasn't a success?" Vague descriptions like this will match the current live subject list, for purposes of choosing relevant beats, but will not add to the live list when the beat is performed. For example: (About a dwarf.) Snow White: "I have eight? no, seven indentured miners right now. No point remembering their names, they die so quickly. I just go by appearances. The present lot are Doc, Grumpy, Happy, Sleepy, Bashful, Sneezy, and Dopey. Might let Sneezy go, actually, don't want a sudden cave-in to knock out all seven at once. You can only buy fresh dwarfs on Wednesdays, you see, so one bad sneeze on a Thursday and..." ...would match any of the dwarfs for purposes of relevance, but not make any of them live topics when the beat is performed. Writing it this way, on the other hand, would: (About Doc, Grumpy, Happy, Sleepy, Bashful, Sneezy, and Dopey.) And then, for example: (About Bashful.) Snow White: "He's a varmint like all the rest of them." If a beat is bringing up unexpected new information, which should not be matched for relevance purposes when the beat is being chosen, `mentioning` should instead be used on the dialogue itself. For example: (About a dwarf.) Snow White (mentioning diamonds): "He's a varmint like all the rest, but the diamonds are in these crazy low tunnels, and I can't afford to muss my hair. I'm still super-active on the pageanting circuit, you know." ## Dialogue lines ^^{dialogue lines} ^^{dialogue lines: speaker of} ^^{speaker (- thing)+actvar+} ^^{dialogue lines: narration} ^^{narration (dialogue lines)} ^^{dialogue lines: as values} ^^{values: dialogue lines as values} ^^{dialogue lines: matching potential speakers} ^^{interlocutor (- thing)+actvar+} ^^{dialogue lines: mentioning a subject} ^^{dialogue: conversational subjects: lines mentioning} ^^{dialogue lines: conditional} ^^{dialogue lines: properties} ^^{dialogue: director: speaker selection rules} ^^{narrated / unnarrated (dialogue line)+prop+} ^^{unnarrated / narrated (dialogue line)+prop+} ^^{narrated (dialogue line)+propcat+} ^^{unnarrated (dialogue line)+propcat+} ^^{performed / unperformed (dialogue line)+prop+} ^^{unperformed / performed (dialogue line)+prop+} ^^{performed (dialogue line)+propcat+} ^^{unperformed (dialogue line)+propcat+} ^^{recurring / non-recurring (dialogue line)+prop+} ^^{non-recurring / recurring (dialogue line)+prop+} ^^{recurring (dialogue line)+propcat+} ^^{non-recurring (dialogue line)+propcat+} ^^{elaborated / unelaborated (dialogue line)+prop+} ^^{unelaborated / elaborated (dialogue line)+prop+} ^^{elaborated (dialogue line)+propcat+} ^^{unelaborated (dialogue line)+propcat+} ^^{performance notes: named} ^^{this is the (name) line+perfnote+} ^^{performance notes: to an interlocutor} ^^{to (person)+perfnote+} ^^{performance notes: mentioning a subject} ^^{mentioning (subject)+perfnote+} ^^{performance notes: conditions} ^^{if (a condition)+perfnote+} ^^{unless (a condition)+perfnote+} ^^{performance notes: before an action} ^^{before (an action)+perfnote+} ^^{performance notes: after an action} ^^{after (an action)+perfnote+} ^^{performance notes: setting a condition} ^^{now (a condition)+perfnote+} ^^{performance notes: without speaking} ^^{without speaking+perfnote+} ^^{performance notes: performance styles} ^^{performance styles} ^^{|spoken normally} ^^{performance styles: |spoken normally} ^^{|': in elaborated dialogue lines+sourcepart+} ^^{punctuation: apostrophe: in elaborated dialogue lines} By this point many lines of dialogue have already appeared, some of them with cryptic notes in brackets. It's time now to look at the full range of possibilities. A dialogue line occupies a single complete paragraph, and takes one of these forms: Speaker: "Line which is said." Speaker (some performance details): "Line which is said." If given, the performance details are one or more clauses, divided by full stops or semicolons, and placed in round brackets after the speaker name. ### The speaker The speaker is either the word `Narration`, which means that the line is not dialogue, but bridging narration in the story: Narration: "Jojo walks over to the jeep." Or else it is a description of who speaks. Usually that will be a literal name of somebody, but it need not be. These are all potentially valid speakers: - `Marcellus:` - `A woman:` - `Somebody who is not Marcellus:` - `The tallest person in the Dining Room:` Such vague descriptions sometimes match multiple possible speakers, and if so, the dialogue director chooses them using the following criteria, with the most important first: - On-stage (i.e., enclosed by some room) rather than off-stage. - Audible to the player rather than not. - Being the interlocutor of the previous speech in the same beat rather than not. - Being a `person` rather than an inanimate object. - Not being the immediately previous speaker. If there are several equally good possibilities under these criteria, a random choice is made. If there are none, the line of dialogue is skipped and not performed at all (and therefore is not given the `performed` property). ### The name Just as every beat is a value of the kind `dialogue beat`, so every line is a value of the kind `dialogue line`. These are usually nameless, but can be given names, which would allow the source text to manipulate them. For example: Marcellus (this is the reluctant admission line): "Something is rotten." The name has to end with `line`, and has to be unique: two different lines cannot have the same name. Most lines never need naming, of course, but the occasional use of names allows for tricks like: Bernardo (if the reluctant admission line is performed): "Look, we've got to face it. Marcellus was right, Denmark's in trouble." ### The interlocutor Most lines are delivered to the whole room in general, but some are pointedly spoken _to_ somebody, even if others are listening. If so, that person is called the _interlocutor_. `to` plus a description of an object specifies who that person is. This is useful for lines which make sense only in the presence of somebody else. For example: Marcellus (to Bernardo; if the Prince cannot hear Marcellus): "The Prince looks moody tonight, i'faith." The line will not be performed unless Marcellus can hear Bernardo. Being the interlocutor also makes somebody slightly more likely to be chosen as the next speaker: see above. ### What is mentioned `mentioning ...` says that the line makes a conversation subject live when it is performed. For example: Marcellus (mentioning the ghost): "I be mighty afear'd of the Ghost." A whole list of subjects can be given: `mentioning the Ghost and Denmark` would give two, for example. As usual, it's possible to be vague: `mentioning the people in the Dining Room`, for example. But the whole point of `mentioning` is to single out what's important, so it's unlikely to be a good idea to allow too many things to be caught at a time by such a description. ### Making the line conditional `if` or `unless` plus any condition causes the line to be skipped (and not given the `performed` property) if this requirement fails. ### Actions as stage directions The `before` and `after` clauses say that an Inform action should be tried along with the performance of the line. Note that `before` means the line is performed before the action, and `after` means it is performed after. Unless otherwise specified, the actor of the action is the speaker, so this is an exception to the general rule of Inform that the default actor is the player. For example: Gravedigger (after taking the shovel): "Here goes another shallow one." would be performed as: ``` transcript The gravedigger takes the shovel. Gravedigger: "Here goes another shallow one." ``` In the case of `after`, the action must succeed, or else the line is not performed after all. For example, if some rule made it impossible for any person to take the shovel, the Gravedigger would not in fact get it, and therefore his line would make no sense: so it would not be performed. The actor need not be the speaker, but the action has to succeed whoever the actor may be: Gravedigger (to Hamlet; after Hamlet silently taking the shovel): "Hey, I saw you picking up that shovel! That's a union job, sweet Prince!" As with `try`, the keyword `silently` causes uninteresting text such as ``The gravedigger takes the shovel.`` to be left unsaid. ### Now conditions as stage directions `now` plus a condition allows the world model to be changed immediately after the line is performed. For example: Marcellus (now Marcellus is in the Banqueting Hall): "Oh my. I'm running for it!" It's legal to pile up multiple `after`, `before` and `now` clauses on the same line, at your own risk: Marcellus (after taking the ghost detector; after examining the ghost; now Marcellus is in the Banqueting Hall; before jumping): "Marcellus grabs the equipment, takes a quick reading, and panics. 'Oh my. I'm running for it!' And he makes a running jump." The sequence is: `after` actions first, in declaration order; then actual performance of the line; then `now` effects; then `before` actions, in declaration order. If any of the `after` actions should fail, the process stops there. ### Lines without speaking The performance note `without speaking` makes a line non-verbal: something like a gesture, which may not involve words but is still performed by somebody. Marcellus (without speaking): "Marcellus throws up his hands, appalled." The difference between this and `Narration:` is that there is a speaker, `Marcellus`. Because this is non-verbal, he needs to be visible, not audible. Similarly there can be an interlocutor, who must be visible to the speaker rather than audible to him. For example: Marcellus (without speaking, to Bernardo): "Marcellus points a horrified finger, and nudges Bernardo." Unlike regular dialogue lines, this won't be performed if it's dark, and needs both Marcellus and Bernardo to be present. ### Performance styles Using just the name of a `performance style`, but with the word `spoken` removed, indicates that the line is performed this way. By default it is performed in the style `spoken normally`: that is, Bernardo: "Well, good night." is equivalent to: Bernardo (normally): "Well, good night." But if we have created a performance style called `spoken with asperity`, then: Marcellus (with asperity): "I've had it with these goddam ghosts." ...would perform it that way. See [Managing dialogue lines] for more. ### Properties of lines `dialogue line` comes with the following either-or properties built in: - `narrated` or `unnarrated`. Is this a `Narration:` line? - `performed` or `unperformed`. Has this been performed yet? - `recurring` or `non-recurring`. Can the director perform this line more than once in the same play-through? (Note that this same property has the same name, and a similar meaning, for scenes and beats.) By default, no. - `elaborated` or `unelaborated`. Is the speech more than a simple piece of reported speech? By default, lines are `unperformed` and `non-recurring`. Whether they are `narrated` depends on whether they give the speaker as `Narration`, and whether they are `elaborated` depends on the text of the line. For example: Katie: "I suppose." Katie: "Your daughter gives her most grown-up pout. 'Whatever.'" The first line there is `unelaborated`, the second `elaborated` - because it contains internal quotation marks, so it's read as being a mixture of narration and speech, rather than purely being speech. It affects only how the line is performed. An unelaborated line is printed as `Speaker: "Speech."`, whereas an elaborated line is printed exactly as written, the assumption being that it will contain its own indication of who's speaking and which words are actually said. So we see: ``` transcript Katie: "I suppose." Your daughter gives her most grown-up pout. "Whatever." ``` To qualify as `elaborated`, a speech must have at least two quotation marks `'` at word boundaries. The source text can override this in either direction: Katie (unelaborated): "You call this 'peanut butter' but it's really icky." In practice, the commonest property to specify is `recurring`: Katie (recurring): "Have you seen my iPad cable?" This allows the line to be performed any number of times: otherwise it will be skipped on a second performance of the same beat. ### The speech text for a line The performed line is an Inform text, in double-quotes. This can contain text substitutions in square brackets, in the usual way for Inform text, giving access to an enormous range of effects. When such text is printed, the activity variable `speaker` will exist for it, and will hold the identity of the speaker performing the line. (If the line is narration, it will still exist, but will be equal to `nothing`.) Similarly for `interlocutor` and `style`. So for example: A person in the Lounge: "[The speaker] self-importantly [declare]: 'The greatest TV show of all time is [if the speaker is female]Gilmore Girls[if not]24[end if].'" might be performed as: ``` transcript Henry self-importantly declared: "The greatest TV show of all time is 24." ``` ## Managing dialogue lines ^^{dialogue lines} ^^{dialogue lines: properties} ^^{dialogue lines: textual content of} ^^{performance styles} ^^{|spoken normally} ^^{performance styles: |spoken normally} ^^{narrated / unnarrated (dialogue line)+prop+} ^^{unnarrated / narrated (dialogue line)+prop+} ^^{narrated (dialogue line)+propcat+} ^^{unnarrated (dialogue line)+propcat+} ^^{performed / unperformed (dialogue line)+prop+} ^^{unperformed / performed (dialogue line)+prop+} ^^{performed (dialogue line)+propcat+} ^^{unperformed (dialogue line)+propcat+} ^^{recurring / non-recurring (dialogue line)+prop+} ^^{non-recurring / recurring (dialogue line)+prop+} ^^{recurring (dialogue line)+propcat+} ^^{non-recurring (dialogue line)+propcat+} ^^{elaborated / unelaborated (dialogue line)+prop+} ^^{unelaborated / elaborated (dialogue line)+prop+} ^^{elaborated (dialogue line)+propcat+} ^^{unelaborated (dialogue line)+propcat+} ^^{available / unavailable (dialogue line)+adj+} ^^{unavailable / available (dialogue line)+adj+} ^^{verbal / non-verbal (dialogue line)+adj+} ^^{non-verbal / verbal (dialogue line)+adj+} ^^{performance notes: without speaking} ^^{without speaking+perfnote+} ^^{interlocutor (- thing)+actvar+} ^^{speaker (- thing)+actvar+} ^^{style (- performance style)+actvar+} This is where we meet two more kinds: `dialogue line` and `performance style`. Each different line of dialogue in the source text is a different `dialogue line` value. That's true even if the texts are the same, as in the famous dialogue between Laurence Olivier (Szell) and Dustin Hoffman (Babe) in _Marathon Man_ (1976): Szell: "Is it safe?" Babe: "Are you talking to me?" Szell: "Is it safe?" Babe: "Is what safe?" Szell: "Is it safe?" Babe: "I don't know what you mean." ...and so on. The three times Szell asks "Is it safe?" are three different `dialogue line` values. Every line is spoken in a `performance style`. Out of the box, Inform comes with just one defined `performance style`, called `spoken normally`. (Performance styles should have names beginning with `spoken`.) But more can always be defined: Spoken angrily and spoken softly are performance styles. And this enables: Szell (softly): "Is it safe?" Babe (angrily): "I don't know what you mean." Performance styles really exist as a hook for ambitious extensions of the Inform dialogue system which, for example, change character art or pose for speakers who become angry, or which apply emotional parameters to autogenerated voice performance, in the event the game is using a text-to-speech engine. See [Performing something]. Inform will not allow the following words to be used after `spoken` in the names of instances of this kind: `and`, `or`, `if`, `unless`, `before`, `after`, `now`, `to`, `this`, `without`. So, for example, it will issue a problem message rather than define `spoken before thinking`. This avoids ambiguity when lines are declared. As has already been said, `dialogue line` is a kind supporting the following either-or properties: - `narrated` or `unnarrated`. By default, `narrated` for a `Narration:` line, and otherwise `unnarrated`. - `performed` or `unperformed`. By default, `unperformed`. - `recurring` or `non-recurring`. By default, `non-recurring`. - `elaborated` or `unelaborated`. By default, `elaborated` if the speech text includes two or more quotation marks at word boundaries, and otherwise `unelaborated`. In addition, the following adjectives can be applied to dialogue lines: - `available` rather than `unavailable` if the line currently meets its preconditions for being performed — its `if` and `unless` conditions. - `non-verbal` rather than `verbal` if it is a non-verbal communication, written as being performed `without speaking`. And note that `L is in B` can be used to test whether or not the dialogue line `L` belongs to the beat `B` — note that every line is always part of just one beat. This makes it possible to iterate over the contents of `B` (`repeat with L running through dialogue lines in B`), or extract, say, `the list of dialogue lines in B` or `the number of dialogue lines in B`. The performance of a line is carried out by a collection of rulebooks called an _activity_ called `performing`. See the chapter on [Activities], and its section [Performing something] for more, but the gist is that Inform performs `L` by delegating the job to whatever rules exist in the `for performing` rulebook, applied to `L`. Ordinarily this rulebook contains just one rule, the `default dialogue performance rule`, which looks like this: For performing a dialogue line (called L) (this is the default dialogue performance rule): if L is narrated or L is elaborated or L is non-verbal: say "[textual content of L][line break]"; otherwise: say "[The speaker]"; if the interlocutor is something: say " (to [the interlocutor])"; say ": '[textual content of L]'[line break]". But it's possible to create new rules which pre-empt this standard way of doing things. As a very simple example: For performing a narrated dialogue line (called L): say "[italic type][textual content of L][roman type][line break]". Something to note here is that _in performing rules like this_ there are special variables whose values can be used: - `speaker`. This will be `nothing` for a line which is `narrated`. Note that the alternative is for it to be `something`, rather than `somebody`, because inanimate objects like loudspeakers do sometimes speak. - `interlocutor`. This will be `nothing` unless a line is spoken `to` somebody. Again, it might be a `thing` rather than a `person`: a microphone, for instance. - `style`. This will be whatever `performance style` the line is delivered with, so by default it will be `spoken normally`. Note that these variables do not exist outside of the `performing` activity, and in the case of `speaker` and `interlocutor`, can't even always be known at any other time. Consider this line, for example: A woman other than Katie (to an animal): "[The speaker] crouches down to look at [the interlocutor]. 'Do you need feeding now?'" Until the actual moment of performing this, we can't know who exactly will speak, or who is spoken to. For the same reason, we can't know the exact text of what will be said, because it depends on who those people turn out to be. So the following tempting phrase, useful though it may be, can only safely be used in rules attached to the `performing` activity: > phrase: {ph_textualcontent} textual content of (a dialogue line) ... text > > This produces the text of the speech made, but it's only really safe to use this phrase in a rule belonging to the `performing something` activity, because the text may make reference to the current `speaker` and `interlocutor` — which are variables existing only inside that activity. ## Decision points ^^{dialogue beats: branches} ^^{dialogue beats: player choices} ^^{|--: for dialogue choices} ^^{punctuation: double-dash: for dialogue choices} ^^{dialogue choices} ^^{dialogue choices: based on actions} ^^{dialogue choices: automatic} ^^{asking the player: for a dialogue choice} ^^{querying the player: for a dialogue choice} ^^{(before), in dialogue choices+sourcepart+} ^^{(after), in dialogue choices+sourcepart+} ^^{(instead of), in dialogue choices+sourcepart+} ^^{(otherwise), in dialogue choices+sourcepart+} ^^{flow markers} ^^{dialogue beats: flow markers <-- dialogue: sections: flow markers} ^^{|<-: flow marker} ^^{(step through), automatic dialogue choice+sourcepart+} ^^{(step through and stop), automatic dialogue choice+sourcepart+} ^^{(cycle through), automatic dialogue choice+sourcepart+} ^^{(shuffle through), automatic dialogue choice+sourcepart+} ^^{(choose randomly), automatic dialogue choice+sourcepart+} A _decision point_ is reached when the director is performing a beat and comes to a run of _choices_. The idea is that the player selects one of these choices, and then dialogue continues down whichever branch is called for. ### Textual choices So far, we have only seen one sort of decision: where the player is offered specific options as the choices, and has to type 1, 2, ..., to indicate which to take. Border agent: "Business or pleasure?" -- "Business." Agent: "Then where is your C-34d section (xciii) visa exemption waiver proffer certificate D?" -- "Pleasure." Agent: "Fill out the address of your hotel and the name of your vessel, like it's the 1930s still." Those are called _textual choices_, since they consist of text like `"Business."`. But there are also two other ways a decision can present itself. ### Action choices _Action choices_ cause the dialogue director to halt (temporarily) and allow the player to type a command, which is then understood as causing an action in the normal way. For example: Border agent: "Passport, please." -- before giving the passport to the agent Agent: "Enjoy your stay." -- otherwise Agent: "Federal law forbids any suspicious activity here, Ma'am. You're going to have to go with these officers." So, for example, ``` transcript Border agent: "Passport, please." > GIVE PASSPORT TO AGENT Border agent: "Enjoy your stay." ``` Notice the `before` in the `-- before giving the passport to the agent` branch. This means that dialogue intercepts the action, and it never actually takes place. (So the player retains the passport, and none of the normal rules which might prevent the action from taking place are consulted.) If `after` is used rather than `before`: -- after jumping Agent: "Ma'am, it's a serious offence to jump on the spot in an airport." ...then the action _does_ take place, and only then will the Agent speak. But now suppose the action is one which might conceivably fail: suppose the player is smuggling something in a briefcase, and we want to anticipate ``DROP BRIEFCASE``. The case, however, might be handcuffed to the player's wrist: and we don't know whether it will be or not when the dialogue takes place. Let's suppose that we have written this rule: Check dropping the briefcase: if the player is wearing the handcuff, say "It's chained to your wrist!" instead. If the dialogue writes the choice this way: -- before dropping the briefcase Agent: "I saw you! Pick that case up at once!" then we've somehow implied that the player _has_ dropped the case, which would be unrealistic with the handcuff in use. But if we have: -- after dropping the briefcase Agent: "I saw you! Pick that case up at once!" then the dropping action does actually take place, so that the briefcase is now on the ground. Somehow, what we want is for all the checking rules on the action to take place, but then for the action itself to be intercepted _if_ it turned out to make sense. And that's indeed possible: -- instead of dropping the briefcase Agent: "I saw you! Pick that case up at once!" So to sum up: 1) `-- before (an action)` is selected whenever the player successfully types a command which generates this action. No rules are run to check whether it makes sense, and the action itself is not carried out. 2) `-- instead of (an action)` is selected whenever the player successfully types a command which generates this action _and_ the action makes it through the "before" and "check" stages, that is, the action isn't somehow stopped by a `check` or `before` rule. Nevertheless, even though this means that Inform thinks the action is a possible one to carry out, it isn't actually carried out. 3) `-- after (an action)` is only selected when the player successfully types a command which generates this action, _and_ it gets through "before" and "check" rules, _and_ it actually takes place. 4) `-- otherwise` is selected only if none of the other choices were selected. There can only be one of these, and it must be the last choice in the run. It is always automatically `recurring`, so that it won't mysteriously fail to be chosen on a second run through the same decision. Note that there doesn't have to be an `-- otherwise` option. There usually is, as a catch-all, but if not, and none of the choices match, then the decision is left hanging for another turn and reconsidered then. This seems a good point to give an advance preview of flow markers. The following, slightly less hostile, immigration experience obliges the player to keep typing commands until realising that ``GIVE PASSPORT TO AGENT`` is the sensible thing to do. Border agent: "Passport, please." -- (recurring) before giving the passport to the agent Agent: "Enjoy your stay." -- (recurring) otherwise Agent: "Just the passport, if you please, Ma'am." <- Note that the success branch simply runs out of things to say, and so the dialogue ends with the agent saying "Enjoy your stay." But the failure branch runs into the _flow marker_ `<-`. This tells the director to go back to the last decision and try again. ``` transcript Border agent: "Passport, please." > DROP BRIEFCASE Border agent: "Just the passport, if you please, Ma'am." > GIVE PASSPORT TO AGENT Border agent: "Enjoy your stay." ``` ### Automatic choices "Automatic" choices sounds like a contradiction in terms, but really what happens is that it's Inform itself which makes the choice, rather than the player. For example: -- step through Liza: "One." -- or Liza: "Two." -- or Liza: "Three." In an automatic choice, the first choice explains how to make the decision, and the rest must all be just `-- or`. In this case, what `step through` means is that the first time this choice is encountered, the first option is chosen (so Liza says "One."); the second time, the second option; the third time, the third option; and on the fourth and subsequent times, nothing is done. An alternative is: -- cycle through Liza (recurring): "One." -- or Liza (recurring): "Two." -- or Liza (recurring): "Three." This is like `step through` except that the fourth time, we go back to Liza saying "One.", and the fifth time she says "Two.", and so on, round and round. Note that the choices in an automatic choice are always recurring, but that any dialogue within them is not. This is why we have to mark Liza's lines as `recurring` here. There are altogether five of these automatic mechanisms: - `step through`: each in turn, but only once through, then do nothing - `step through and stop`: each in turn, but repeat the last one indefinitely - `cycle through`: each in turn, going back to the start after the last - `shuffle through`: a random permutation, and then another random permutation when that completes, and so on - `choose randomly`: make an entirely random choice every time ## Dialogue choices ^^{|--: for dialogue choices} ^^{punctuation: double-dash: for dialogue choices} ^^{dialogue choices} ^^{dialogue choices: as values} ^^{values: dialogue choices as values} ^^{dialogue choices: conditional} ^^{dialogue choices: properties} ^^{performed / unperformed (dialogue choice)+prop+} ^^{unperformed / performed (dialogue choice)+prop+} ^^{performed (dialogue choice)+propcat+} ^^{unperformed (dialogue choice)+propcat+} ^^{recurring / non-recurring (dialogue lichoicene)+prop+} ^^{non-recurring / recurring (dialogue choice)+prop+} ^^{recurring (dialogue choice)+propcat+} ^^{non-recurring (dialogue choice)+propcat+} As we've seen, then, a dialogue choice is written as a paragraph beginning with `--`. Much like dialogue lines, dialogue choices can have optional annotations given to them between round brackets. But if we forget about those, the possible ways to write a choice are: Syntax | What it's for --------------------------- | ------------- `-- "Text"` | A textual choice. `-- before (an action)` | An action choice. `-- instead of (an action)` | An action choice. `-- after (an action)` | An action choice. `-- otherwise` | Concluding a set of action choices. `-- step through` | Beginning an automatic set of choices. `-- step through and stop` | Beginning an automatic set of choices. `-- cycle through` | Beginning an automatic set of choices. `-- shuffle through` | Beginning an automatic set of choices. `-- choose randomly` | Beginning an automatic set of choices. `-- or` | Concluding an automatic set of choices. All of these were covered in [Decision points], so that just leaves the optional details placed in brackets. The conventions are just like those for dialogue lines: ### The name Just as every beat is a value of the kind `dialogue beat`, and every line is a value of the kind `dialogue line`, so every option is a value of the kind `dialogue choice`. These are usually nameless, but can be given names, which would allow the source text to manipulate them. For example: -- (this is the desperate choice) "Run for it in blind hope" The name has to end with `choice`, and has to be unique: two different choices cannot have the same name. ### Conditions on a choice `if` or `unless` plus any Inform condition imposes a condition for the choice to be available. It's sometimes worth bearing in mind that this just might make _all_ of the options unavailable. Consider this: -- (if the player is in the Great Hall) "Duck!" Narration: "You duck." -- (if the player can see the Lake) "Swim for it!" Narration: "You swim." What if the player is neither in the Great Hall, nor in sight of the Lake? The answer is that the decision vanishes entirely, and the player is not even aware that there might have been one. When placing conditions on choices, this can be a very useful phrase to know: > phrase: {ph_dialoguechoices} current choice list ... list of dialogue choices > > This phrase can only sensibly be used when testing conditions applied to dialogue choices: it produces the list of those available _so far_. That can be used to make later choices only available if earlier ones aren't, or similar effects. For example: -- "Hurl myself at the window." -- "Tunnel through the wall." -- (if the current choice list is empty; recurring) "Admit to being out of ideas." The first time this decision is performed, two options will be available — the first two. The player will choose one. If the decision is performed again, the player will be offered the one not chosen earlier. Should the decision ever come up again, the new option `"Admit to being out of ideas."` will be offered instead. ### Properties of a choice Exactly as for beats and lines, a `dialogue choice` can have these either-or properties: - `performed` or `unperformed`. Has this been chosen yet? - `recurring` or `non-recurring`. Can the director offer this choice more than once in the same play-through? ## Flow markers ^^{flow markers} ^^{dialogue beats: flow markers} ^^{|<-: flow marker} ^^{|->: flow marker} ^^{dialogue beats: stopping} ^^{(-> stop), flow marker+sourcepart+ --> stop} ^^{(-> end the story), flow marker+sourcepart+ --> end the story} ^^{(-> perform) beat, flow marker+sourcepart+ --> perform} ^^{(-> another choice), flow marker+sourcepart+ --> another choice} ^^{story structure: ending: in a dialogue beat} ^^{end of story: in a dialogue beat} Flow markers are written `<-` or `->`, and cause the dialogue director to interrupt its normal performance of a beat. `<-` generally makes a backwards jump in the same beat, while `->` leads out to another beat. Flow markers actually have much in common with choices, and can accept exactly the same bracketed notes as choices have: they can be named and they can be conditional. For example, <- (unless Polonius is in Elsinore) -> (if Hamlet is not in the Graveyard) stop All flow markers are always `recurring`, without any need to say this. ### Flow back `<-` on its own goes back to either the most recent decision point in the same beat, or (if there hasn't been a decision) to the start of the beat. As with control mechanisms in all programming languages, that makes it possible to get into endless loops: (This is the ill-advised beat; fully recurring.) Fatboy Slim: "Right about now, the funk soul brother." Fatboy Slim: "Check it out now, the funk soul brother." <- But it is extremely useful for situations like this one: -- "Option which turns out not to work." Recording angel: "That didn't work. Try again." <- -- "Another option which turns out not to work." Recording angel: "No, try again." <- -- "The one option which works." Recording angel: "Well done." In effect this repeats the decision up to three times until the player heads down the track we want. Because the options above are `non-recurring`, the choices dwindle with each wrong guess until the player can only choose `"The one option which works."`. ### Flow through another beat `-> perform B`, where `B` is the name of a beat, causes the director to perform that beat at this point. Note that after `B` finishes, the original beat _continues where it left off_. That nesting can go up to 20 beats deep. This too can be dangerous if wrongly handled: (This is the equally ill-advised beat; fully recurring.) Fatboy Slim: "Right here, right now." -> perform the equally ill-advised beat But `-> perform` is very useful as a way of incorporating what amounts to a complicated sub-scene which is only needed in some situations. -- "Climb the chimney" Narration: "You get only a few feet, and covered in soot." <- -- "Get into the wardrobe." Narration: "Hmm, there seems no end to these fur coats." -> perform the Narnia visit beat Narration: "Goodness, back at that wardrobe you only dimly remember." The beat to be performed can also be the name of a variable, as in `the redirected beat` in the following example: The redirected beat is a dialogue beat that varies. The redirected beat is the Queensryche beat. Section 1 - Specific chat (dialogue) (This is the starting beat.) Example Friend: "Shall we listen to some music?" -> perform the redirected beat (This is the Queensryche beat.) Example Friend: "I so like Queensryche, even without the diacritic." ### Flow to a stop `-> stop` causes the current beat to finish right here, and is convenient when a drastic choice short-circuits what might otherwise have been a lengthy conversation. -- "Run for the Numidian desert and live off locusts and honey" -> stop -- "Ask if the eternal fate of the soul is determined at death" Augustine: "The purgatorial fires purify only those who die in communion." -- "But ..." Note that `-> stop` stops only the current beat. If one beat is performing another one using `-> perform`, and the second one stops, the first one then resumes. ### Flow to the end of the story There are four variants of this: -> end the story -> end the story finally -> end the story saying "TEXT" -> end the story finally saying "TEXT" These correspond exactly to the Inform phrases which `end the story`. All beats are abandoned at this point, of course, so this is even more drastic than `-> stop`. ### Flow to another choice Finally, and only seldom needed, `-> another choice` can be used to clarify that what look like lots of options for a single decision are in fact two decisions in a row. For example: -- "Boxers." Narration (after wearing the boxer shorts): "You feel less naked." -- "Briefs." Narration (after wearing the briefs): "You feel somewhat less naked." -> another choice -- "White hat." Narration (after wearing the white hat): "You feel noble." -- "Black hat." Narration (after wearing the black hat): "You feel ignoble." The reason for the `-> another choice` flow marker is simply that we want two sets of two options, not one set of four. If any dialogue had appeared in between the two decisions, there would have been no need for the `-> another choice`, but since it didn't, we need some marker to hold the decisions apart from each other. `-> another choice` has to be unconditional, and doesn't get a name or properties: it isn't really present in the story at all. ## Managing dialogue choices ^^{flow markers: as a sort of dialogue choice} ^^{dialogue beats: flow markers: as a sort of dialogue choice} ^^{dialogue choices: flow markers as choices} ^^{performed / unperformed (dialogue choice)+prop+} ^^{unperformed / performed (dialogue choice)+prop+} ^^{performed (dialogue choice)+propcat+} ^^{unperformed (dialogue choice)+propcat+} ^^{recurring / non-recurring (dialogue lichoicene)+prop+} ^^{non-recurring / recurring (dialogue choice)+prop+} ^^{recurring (dialogue choice)+propcat+} ^^{non-recurring (dialogue choice)+propcat+} ^^{flowing / offered (dialogue choice)+adj+} ^^{offered / flowing (dialogue choice)+adj+} ^^{story-ending (dialogue choice)+adj+ --> story ending} ^^{offering something+descactivity+} ^^{offering+activity+} ^^{dialogue choices: offering+activity+} As has been mentioned already, each different choice in the source text is a different `dialogue choice` value, and in fact so is each different flow marker: under the surface, a flow marker is really just a special sort of choice. A `dialogue choice` comes with two either-or properties already defined: - `performed` or `unperformed`. By default, `unperformed`. - `recurring` or `non-recurring`. By default, `non-recurring`. In addition, the following adjectives can be applied to choices: - `flowing` rather than `offered` if the choice is a `->` or `<-` flow control marker rather than a `--` option offered as part of a decision. - `story-ending` if the choice is a flow marker ending the story. All `story-ending` choices are `flowing`, but not vice versa. Just as was also true for dialogue lines, `C is in B` can be used to test whether or not the dialogue choice `C` belongs to the beat `B` — note that every choice is always part of just one beat. This makes it possible to iterate over the contents of `B` (`repeat with C running through dialogue choices in B`), or extract, say, `the list of unperformed dialogue choices in B`. When the dialogue director wants to offer a decision based on textual choices to the player, it usually does so with a simple numbered list of options, and then asks the player to type a number. This is a lowest-common-denominator sort of thing to do, but many other user interfaces could be imagined: an Inform story presented on a website might want clickable options, for example. Because of that, Inform routes this business through an _activity_. See the chapter on [Activities], and its section [Offering something] for more, but the gist is that Inform delegates the job to whatever rules exist in the `for offering` rulebook, applied to a list of choices. Ordinarily this rulebook contains just one rule, the `default offering dialogue choices rule`, which looks like this: For offering a list of dialogue choices (called L) (this is the default offering dialogue choices rule): let N be 0; repeat with C running through L: increase N by 1; say "([N]) [textual content of C][line break]"; say conditional paragraph break; let M be a number chosen by the player from 1 to N; set the dialogue selection value to M; say "[bold type][textual content of entry M of L][roman type][paragraph break]". This produces a simple numbered list, then asks the player to type one of those numbers (insisting and asking again if they type something else), and then prints back the chosen option in bold face. # Phrases ## What are phrases? {PHRASES} ^^{phrases} ^^{|nothing: +to+do nothing} Phrases are instructions to Inform to do something, or to decide whether something is true or false, or to produce a value, or to say something. Inform has around 350 phrases built-in, and the chapters so far have already defined about 100 of those. In this chapter we'll see some key phrases for organising instructions of what to do, and also see how to define entirely new phrases. Just to run through the four sorts of phrase with examples: (a) Phrases to do something. These are the ones used in the body of a rule. For example, When Train Stop begins: move the Flying Scotsman to the Station; say "The Flying Scotsman pulls up at the platform." Rules like this begin with a "preamble", the beginning part which tells Inform when or how they apply, and then follow on with a list of instructions – here, just two of them. `move ... to ...` and `say ...` are both phrases. Inform provides about 130 of these built-in. It's actually not quite true that they all do something, because one of them is: > phrase: {ph_nothing} do nothing > > This phrase does nothing at all. It is very occasionally useful to make a rule which does nothing: > > This is the largely ineffective rule: > do nothing. (b) Phrases to decide whether a condition is true. These are the ones which can be used in an `if`: if action requires light: ... Not all conditions come from phrases. For example, `if the front door is closed` and `if Peter is wearing the sandals` have meanings which come from the verbs `to be` and `to wear`. Inform provides about 60 built-in conditions, which give a friendly wording for questions which would be lengthy or difficult to write in any other way. (c) Phrases to decide a value. For example: square root of 16 produces a number, 4 of course, and can be used whenever a number is expected. Inform provides about 100 built-in phrases like this. (d) Text substitutions. These are actually just phrases whose definition begins with `To say ...`. Example: "It's now [time of day in words]." Inform provides about 60 built-in text substitutions. ## The phrasebook {PM_BareTo} ^^{to (phrase name)...+assert+} ^^{phrases: defining} ^^{defining: phrases} ^^{Inform 6 equivalent: functions} ^^{Inform 6 equivalent: procedures} ^^{Phrases page of Index panel+ui+} ^^{user interface: Index panel: Phrases page} ^^{Index panel+ui+: Phrases page} ^^{punctuation: colon <-- colon} ^^{|:}^^^{|: --> ;} The Phrasebook is Inform's collection of recognised phrases, and it can always be browsed using the Index panel of the same name. Even the smallest project has a good-sized phrasebook, since it contains all of the built-in phrases. But most projects also define new phrases of their own. Here is a simple definition of a new phrase: To spring the trap: say "'Sproing!' go the hinges and, with a flash of silver, the enormous blades whisk together!"; end the story. Inform allows us to use whatever conventions of layout we prefer, but it's customary to use indentation like this, dividing off the preamble from the phrases which follow. As can be seen, definitions of new phrases look very like rules. What makes this definition a simple one is that the wording is fixed. The only way to use this would be from another phrase or rule, like so: Instead of entering the cage: spring the trap. In the next section we'll see how to give more complicated definitions which, like `move ... to ...`, allow for the wording to change with the circumstances. ## Pattern matching {PM_TokenWithoutOpenBracket} {PM_TokenWithoutCloseBracket} {PM_TokenWithEmptyBrackets} {PM_TokenWithNestedBrackets} {PM_BadTypeIndication} {PM_TokenMisunderstood} {PM_PhraseTooLong} {PM_AdjacentTokens} {PM_SaySlashed} ^^{phrases: phrase parameters} ^^{parameters: of phrases}^^^{parameters <-- arguments} ^^{Inform 6 equivalent: functions with parameters} ^^{pattern matching: phrase definitions} ^^{type-checking: in phrase definitions} ^^{kinds: in phrase parameters} ^^{punctuation: slash: separating synonymous words in phrase definitions} ^^{|/: separating synonymous words in phrase definitions}^^^{punctuation: slash <-- slash} ^^{punctuation: double-dash: optional words in phrase definitions} ^^{|--: optional words in phrase definitions}^^^{punctuation: double-dash <-- double-dash} ^^{punctuation: brackets: for phrase parameters} ^^{|( ): for phrase parameters} In this section, let's make the following new phrase: To admire (item - an object): say "You take a long look at [item].". This does very little, of course, but it does allow the wording to be different each time the phrase is used: admire the diamonds; admire Mr Cogito; admire the honey sandwich; and our single definition covers all of these possibilities. The bracketed part of the definition, `(item – an object)`, tells Inform to expect an object in that position, and Inform enforces this carefully. So this definition might tell Inform what `admire the barricade` means, but not what admire "blue cheese"; admire 63; mean. Unless some other definition sorts the matter out, Inform will reply to uses like this with a Problem message: ``` problems **Problem.** You wrote 'admire 63' ![Reveal](doc_images/Reveal.png), but '63' has the wrong kind of value: a number rather than an object. ``` The object does not need to be named literally, but can be anything which works out to be an object: for instance, After dropping something in the Auction House: admire the noun. which Inform allows because `noun`, here, is a name for the object which is being acted on. Inform decides which definition to apply in a process called "pattern matching". The bracketed part of the example definition has the form `(name – description)`. The definition only applies if the text being matched refers to a value which fits the description – for instance, the diamonds agreed with `object`, but 63 did not. If the definition does apply, then the Inform works through the rest of the phrase using `name` to mean whatever value matched. For example: To slam shut (box - an open container): say "With great panache, you slam shut [the box]."; now the box is closed. When this phrase is followed, `box` means whatever open container the pattern-matcher found when it was called for. For example, if Inform reads slam shut the Dutch armoire; then it acts on this by following the definition of `slam shut ...`, using the Dutch armoire object as the value of `box`, so it prints: With great panache, you slam shut the Dutch armoire. and renders it closed. The description given in a definition can even be a single, specific value. For instance, we could define: To grant (bonus - a number) points: increase the score by the bonus. To grant (bonus - 7) points: say "You shiver uncontrollably." which would withhold this unlucky bounty. That would mean that: grant 7 points; grant seven points; would each produce uncontrollable shivers, because Inform uses the definition applying to the number 7; but grant six points; would increase the score by 6. In general Inform always follows the principle that more specific definitions take priority over more general ones. So although the definitions: To grant (bonus - a number) points: ... To grant (bonus - 7) points: ... both apply to the case of `grant 7 points`, Inform uses the second, because it's the more specific of the two possibilities. Sometimes it will not be possible to tell if the value supplied meets the requirements until the story is actually playing. If, at run-time, no definition fits some phrase which has to be carried out, a run-time problem message is produced. Finally, and more straightforwardly, we can specify variations in wording using slashes between alternative words in a `To ...` definition. For instance: To grant (bonus - a number) point/points: ... allows the final word to be either `point` or `points`. Slashes like this can only be used with literal words, not bracketed values, and give alternative forms only of a single word at a time; the alternative `--` means "no word at all", and thus makes it optional: To grant (bonus - a number) point/points/--: ... makes `grant 3` do the same as `grant 3 points`. If we need more variation than that, we should make more than one definition. ## The showme phrase ^^{testing phrases: showme (value)+phr+} We've already seen the ``SHOWME`` command, which can be typed into the Story panel to look at the state of something, usually a thing or room. ``SHOWME`` is a testing command which has no effect once the work is released; eventual players can't use it. Inform also has a phrase called `showme`, which works in much the same way: > phrase: {ph_showme} showme (value) > > This phrase is intended for testing purposes only. If used in a story file running inside the Inform application, it prints a line of text showing the given value and its kind; in a Released story file, it does nothing at all. Example: > > When play begins: showme 11. > > produces > > number: 11 > > More usefully: > > Every turn: showme the score. > > Now, every turn, we get a line in the story's transcript like so: > > "score" = number: 0 > > Inform uses the quotation marks and equals sign to show that it had to do some work to find the answer. `score` wasn't a constant value – it was a variable, and Inform had to look up the current value. `Showme` is a convenient way to see what's going on inside a phrase which isn't behaving as expected, or to find out the kind of a value. Here are some trickier examples. Suppose our design includes: The matching key of the blue door is the brass Yale key. If we then try this: When play begins: showme matching key of the blue door. we get, when the story starts up, "matching key of the blue door" = object: brass Yale key Why is this an `object`, when we know that the key is actually a `thing`? After all, if we `showme key` instead, we get: thing: brass Yale key The answer is a little technical: it's because Inform guarantees that the matching key is always an object, but not that it's always a thing – it just happens to be a thing at the moment. There's not really a contradiction, because a `thing` is a kind of `object`, so in fact the key is both. If we try `showme matching key`, we get something like this: objects valued property: property 23 which is even more technical – people never need to print the names of abstract property names during play, so Inform doesn't provide any good way of doing it. It is reduced to printing out an internal ID number (`property 23`) instead of the name (`matching key`). This can't be helped: `showme` is a way to lift the lid and see what's going on inside Inform's machinery, and some of the corners are dark. All the same, `showme` can be very useful in tinkering with rules to make them work properly. It prints nothing at all in a Release version of a project, so it's impossible for these private notes to be shown accidentally to our eventual readers. ## Conditions and questions {kind_truthstate} {PM_TruthStateToDecide} ^^{phrases: deciding a condition} ^^{conditions: defined by phrases} ^^{|truth state} ^^{values: truth state values} ^^{|true / false} ^^{|false / true} ^^{darkness: testing whether in darkness} ^^{querying the player: yes/no} ^^{asking the player: yes/no} ^^{(YES), querying yes/no+commandpart+} ^^{(NO), querying yes/no+commandpart+} ^^{consents: if player consents+phr+} A variety of "conditions" have already appeared in this documentation. A condition is a phrase which describes a situation which might be true, or might be false, and examples might include: Mr Kite is in Bishopsgate the score is greater than 10 Sherlock Holmes suspects a woman These are all examples of sentences, formed by putting nouns either side of a verb, and clearly a wide range of conditions can be written this way. But there are also a few special conditions built into Inform which have a fixed wording, and test questions difficult to address with ordinary sentences. For instance: > phrase: {ph_indarkness} if in darkness: > > This condition is true if the player currently has no light to see by. Note that the test is more complicated than simply testing > > if the player is in a dark room, ... > > since the player might have a torch, or be inside a cage which is itself in a dark room, and so on. Another example of a condition not easily written as a sentence is: > phrase: {ph_consents} if player consents: > > This condition is unusual in doing something and not simply making a silent check: it waits for the player to type ``YES`` (or Y) or NO (or N) at the keyboard, and then is true if the answer was yes. Example: > > say "Are you quite sure you want to kiss the Queen? "; > if the player consents: > ... Whether it's put to the player like this or not, testing a condition is really asking a question, and there is always a yes/no answer. In Inform this answer is not usually a value (unlike in some other computer programming languages), but it can be made into one. Firstly, we need a special kind of value to hold answers like this. It's called `truth state`, and it has just two possible values, written as `true` and `false`. We then need: > phrase: {ph_whether} whether or not (a condition) ... truth state > > This phrase converts a condition into its result as a value, which is always either `true` or `false`. Example: > > whether or not 20 is an odd number > > produces the truth state `false`. This is mostly useful for storing up results to look at later: > > let victory be whether or not all the treasures are in the cabinet; > > and then subsequently: > > if victory is true, ... As another example, in most stories this: When play begins: showme whether or not in darkness. ...will produce a line: "whether or not in darkness" = truth state: false In short, `truth state` is a kind of value like any other. That means it can be the kind of a variable: Salvation earned is a truth state that varies. and it can similarly be used in table columns, lists, or anywhere else where values are allowed. ## If {PM_IfOutsidePhrase} ^^{conditions: testing} ^^{type-checking: in conditions} ^^{conditions: equality} ^^{comparisons: equality} Inform's most powerful phrases are those which control the others, making them repeat, or be skipped. > phrase: {ph_if} if (a condition) , (a phrase) & if (a condition): > > This phrase causes the single phrase, or block of phrases, following it to be obeyed only if the condition is true. (If the condition must contain a comma for some reason, the block form should be used.) Example: > > if the red door is open, say "You could try going east?" The sense of an `if` can be reversed by using the word `unless` instead: > phrase: {ph_unless} unless (a condition) , (a phrase) & unless (a condition): > > This phrase causes the single phrase, or block of phrases, following it to be obeyed only if the condition is false. (If the condition must contain a comma for some reason, the block form should be used.) Example: > > unless the red door is closed, say "You could try going east?" `Unless` is clearly unnecessary, but it can be a good way to make the source text easier for humans to read. As we have seen, there are many different forms of condition in Inform. They usually take a form quite like an assertion sentence, except that they're questions and not statements of fact. For example: if the score is 10, ... if all of the people are in the Atrium, ... Questions like this are checked by Inform to see if they make sense. The following doesn't, for instance: if 10 is a door, say "Huzzah!"; This produces the baffled reply: ``` problems **Problem.** In the line 'if 10 is a door, say "Huzzah!"' ![Reveal](doc_images/Reveal.png), I can't determine whether or not '10 is a door', because it seems to ask if a number is some sort of door. ``` ## Grouping phrases together {PM_BeginWithoutEnd} {PM_BlockNestingTooDeep} {PM_EndWithoutBegin} {PM_WrongEnd} {PM_CantUseOutsideStructure} {PM_BothBlockSyntaxes} {PM_NotInOldSyntax} {PM_MisalignedIndentation} {PM_RunOnsInTabbedRoutine} {PM_EmptyIndentedBlock} ^^{(begin), in phrases+sourcepart+} ^^{(end), in phrases+sourcepart+} ^^{|end if} ^^{Inform 6 equivalent: code blocks} ^^{indentation+ofsource+} ^^{tabs, for indentation+ofsource+} ^^{punctuation: colon} ^^{|:} In practice it is not enough to apply `if` to a single phrase alone: we want to give a whole list of phrases to be followed if a condition holds. We do this by grouping them together. This is the standard way to do that: To comment upon (whatever - a thing): if whatever is transparent, say "I see right through this!"; if whatever is an open door: say "Oh look, an open door!"; if whatever is openable, say "But you could always shut it." Here we group two phrases together under the same `if`. Note that the comma after the condition `whatever is an open door` has become a colon, and that the indentation in the list of phrases shows how they are grouped together. In the example above, the source moves two tabs in from the margin; the maximum allowed is 25. Indentation is the convention used in this manual and in the examples, but in the very early days of Inform a more explicit notation using the words `begin` and `end` was also allowed: To comment upon (whatever - a thing): if whatever is transparent, say "I see right through this!"; if whatever is an open door begin; say "Oh look, an open door!"; if whatever is openable, say "But you could always shut it."; end if. While this syntax is still allowed for the time being, to keep old source text working, it is more cumbersome and reads less naturally, so authors are advised not to write new source text this way. ## Otherwise {PM_NonCaseInIf} {PM_MisalignedOtherwise} {PM_MisalignedCase} {PM_MisarrangedOtherwise} {PM_DoubleOtherwise} {PM_OtherwiseIfAfterOtherwise} {PM_CaseValueNonConstant} {PM_CaseValueMismatch} {PM_OtherwiseWithoutIf} {PM_OtherwiseInNonIf} ^^{conditions: with (otherwise/else)+sourcepart+} ^^{+to+if (a condition): with (otherwise/else)+sourcepart+} ^^{Inform 6 equivalent: |switch/case} ^^{|--: separating cases} ^^{punctuation: double-dash: separating cases} ^^{abbreviations: chains of equality tests} We often need code which does one thing in one circumstance, and another the rest of the time. We could do this like so: if N is 2: ... if N is not 2: ... but this is not very elegant, and besides, what if the action we take when N is 2 changes N so that it becomes something else? Instead we use `otherwise`: > phrase: {ph_otherwise} otherwise if (a condition) & otherwise unless (a condition) & otherwise (a phrase) & else if (a condition) & else unless (a condition) & else (a phrase) > > This phrase can only be used as part of an `if ...:` or `unless: ...`, and provides an alternative block of phrases to follow if the first block isn't followed. Example: > > if N is 2: > ... > otherwise: > ... > > When there is only a single phrase we can use the shortened form: > > if N is 2, say "Hooray, N is 2!"; > otherwise say "Boo, N is not 2..."; > > We can also supply an alternative condition: > > if N is 1: > ... > otherwise if N is 2: > ... > otherwise if N is greater than 4: > ... > > At most one of the `...` clauses is ever reached – the first which works out. If the chain of conditions being tried consists of checking the same value over and over, we can use a convenient abbreviated form: > phrase: {ph_switch} if (value) is: > > This phrase switches between a variety of possible blocks of phrases to follow, depending on the value given. Example: > > if the dangerous item is: > -- the electric hairbrush: > say "Mind your head."; > -- the silver spoon: > say "Steer clear of the cutlery drawer." > > One alternative is allowed to be `otherwise`, which is used only if none of the other cases apply, and which therefore guarantees that in any situation exactly one of the blocks will be followed. > > if N is: > -- 1: say "1."; > -- 2: say "2."; > -- otherwise: say "Neither 1 nor 2."; This form of `if` layout is not allowed to use `begin` and `end` instead of indentation: it would look too messy, and would scarcely be an abbreviation. It is also not allowed to use `unless` instead of `if`, because the result would be too tangled to follow. ## While ^^{loops: in phrases} ^^{(begin), in phrases+sourcepart+} ^^{(end), in phrases+sourcepart+} ^^{|end while} ^^{indentation+ofsource+} ^^{tabs, for indentation+ofsource+} ^^{Inform 6 equivalent: |while} The next control phrase is `while`, which has the form: > phrase: {ph_while} while (a condition): > > This phrase causes the block of phrases following it to be repeated over and over for as long the condition is true. If it isn't even true the first time, the block is skipped over and nothing happens. Example: > > while someone (called the victim) is in the Crypt: > say "A bolt of lightning strikes [the victim]!"; > now the victim is in the Afterlife; We must be careful not to commit mistakes like the following: while eggs is eggs: say "again and "; which, as sure as eggs is eggs (which is very sure indeed), writes out again and again and again and again and again and ... forever. (Inform won't prevent this: we will find out the hard way when the story is played.) While we would probably never write anything so blatant as that, the mistake is all too easy to commit in disguised form. We should never design a loop, as repetitions like this are called, without worrying about if and when it will finish. Experience shows that it is much more legible to lay out `while` loops as blocks, even in these rare cases when only a single phrase forms the body of the block. ## Repeat {PM_CalledInRepeat} ^^{loops: counted} ^^{loops: through values} ^^{counted loops} ^^{(running from), looping through values+sourcepart+} ^^{Inform 6 equivalent: |for} ^^{limits: of numeric values} ^^{numbers: limits of numeric values} ^^{Z-machine: numeric limits} ^^{Glulx: numeric limits} ^^{virtual machine: numeric limits} The other kind of loop in Inform is `repeat`. The trouble with `while` is that it's not obvious at a glance when or whether the loop will finish, and nor is there any book-keeping to measure progress. A `repeat` loop is much more predictable, and is more or less certain to finish. There are several forms of `repeat`, of which the simplest is similar to the old "FOR ... NEXT" loop from the home-computer programming language BASIC, for those with long memories: > phrase: {ph_repeat} repeat with (a name not so far used) running from (arithmetic value) to (arithmetic value) & repeat with (a name not so far used) running from (enumerated value) to (enumerated value): > > This phrase causes the block of phrases following it to be repeated once for each value in the given range, storing that value in the named variable. (The variable exists only temporarily, within the repetition.) Example: > > repeat with counter running from 1 to 10: > ... > > This, and runs through the given phrases ten times. Within those phrases, a special value called `counter` has the value 1 the first time through, then the value 2, then 3 and so on up to 10. (It can of course be called whatever we like: this is only an example.) The range can be from any kind where ranges make sense – anything on which arithmetic can be done, so for instance > > repeat with moment running from 4 PM to 4:07 PM: > ... > > and also any enumeration: > > Colour is a kind of value. The colours are red, orange, yellow, green, blue, indigo and violet. > > ... > repeat with hue running from orange to indigo: > ... We are allowed to "nest" loops, that is, to put one inside another. {*}To plot a grid with size (S - a number): repeat with x running from 1 to S: say "Row [x]:"; repeat with y running from 1 to S: say " [y]"; say "." If we then write plot a grid with size 5; then the result is ``` transcript Row 1: 1 2 3 4 5. Row 2: 1 2 3 4 5. Row 3: 1 2 3 4 5. Row 4: 1 2 3 4 5. Row 5: 1 2 3 4 5. ``` Thus the innermost phrase, the say which mentions `y`, happens 25 times. Whenever dealing with numbers in Inform we may need to remember that if the Settings for the project are set to use the Z-machine, the range is restricted to -32768 up to 32767. Repeating with a counter up to exactly 32767 is hazardous, because the counter can never break through this barrier: it's infinity, so far as Inform is concerned, and that can cause the repetitions to go on forever. (On Glulx, numbers can be very much larger.) ## Repeat running through {PM_BadRepeatDomain} ^^{(running through), looping through objects+sourcepart+} ^^{loops: through objects} ^^{object loops} ^^{Inform 6 equivalent: |objectloop} ^^{|called: in describing things} Inform is not used very much for numerical work, so the kind of repeat loop described in the previous section is not much used. Inform's natural domain is really the world of things and rooms, so the following kind of repeat is much more useful. > phrase: {ph_runthrough} repeat with (a name not so far used) running through (description of values): > > This phrase causes the block of phrases following it to be repeated once for each value matching the description, storing that value in the named variable. (The variable exists only temporarily, within the repetition.) Example: > > repeat with item running through open containers: > ... > > If there are no containers, or they are all closed, the phrases will not be followed at all. Inform will issue a Problem message if the range of the loop may be infinite: for example, it won't allow: > > repeat with X running through odd numbers: > ... > > On the other hand it will allow: > > repeat with T running through times: > ... > > which repeats 1440 times, starting with T at midnight and finishing at 11:59 PM. See the Kinds index for which kinds of value can be repeated through. As with counting the `number of ...` objects satisfying some property, we can run through a wide variety of possibilities – any description whose range is possible for Inform to search. For example: repeat with dinner guest running through the people in the Dining Room: ... repeat with possession running through things carried: ... repeat with event running through non-recurring scenes which are happening: ... The following lists the whereabouts of all men in lighted rooms: {*}repeat with suspect running through the men who are in a lighted room: say "[The suspect] is in [the location of the suspect]."; One small note of caution: if what the `repeat` loop does is to change the things being repeated through, changing in particular whether items not yet reached will qualify to be repeated through, the results can be unexpected. Rather than writing `repeat with X running through D`, it may be safer to try `while there is D (called X)`, though note that this will only finish if X is always changed so that it no longer qualifies. ## Next and break {PM_CantUseOutsideLoop} ^^{Inform 6 equivalent: |continue} ^^{Inform 6 equivalent: |break} ^^{loops: interrupting} So `repeat` and `while` phrases cause a block of other phrases to be repeated, over and over. The number of repetitions and the flow of "control" has so far been controlled only by the way the original loop was described. But in fact it's also possible to change this from inside the block being repeated, using these: > phrase: {ph_next} next > > This phrase can only be used inside a `repeat` or `while` block, and causes the current repetition of the block to finish immediately. That either means the next repetition begins, or (if we are already at the last one) the loop ends too. Example: > > repeat with X running from 1 to 10: > if X is 4, next; > say "[X] ". > > produces the text "1 2 3 5 6 7 8 9 10 ", with no "4" because the `say` phrase was never reached on the fourth repetition. In Monopoly terms, `next` is "Advance to Go" rather than "go directly, do not pass Go, do not collect $200" – the next iteration begins with the variable, if there is one, having cleanly moved on to the next value, just as if the loop had been run through in the normal way. (`Next` is called `continue` in a fair number of programming languages, so Inform issues a specific problem message to help people who forget this.) > phrase: {ph_break} break > > This phrase can only be used inside `repeat`, `while` block, and causes both the current repetition and the entire loop to finish immediately. Example: > > repeat with X running from 1 to 10: > if X is 7, break; > say "[X] ". > > produces the text "1 2 3 4 5 6 ", with nothing after "6" because the loop was broken at that point. The `say` wasn't reached on the 7th repetition, and the 8th, 9th and 10th never happened. ## Stop ^^{phrases: interrupting} ^^{Inform 6 equivalent: |return} Now that it's possible to define phrases where different things are done in different circumstances, we sometimes want to halt early. This is what `stop` is for. > phrase: {ph_stop} stop > > This phrase causes the current rule to end immediately. It is most often used in the definition of other phrases: > > To judge the score: > if the score is 0, stop; > say "The score is [score in words] more than it was a half-hour ago." > > In the case when the score is 0, the `stop` ends the phrase immediately, so that the subsequent text is printed only if the score is not 0. > > `Stop` can also be used in action rules, though this is not very good style – it's clearer to use `stop the action`, which is exactly equivalent. ## Phrase options {PM_TooManyPhraseOptions} {PM_PhraseOptionsExclusive} {PM_NotAPhraseOption} {PM_NotTheOnlyPhraseOption} {PM_SayWithPhraseOptions} ^^{options, for phrases} ^^{Inform 6 equivalent: functions with optional parameters} ^^{phrases: options for small variations} ^^{punctuation: comma: separating phrase options} ^^{|,: separating phrase options} There are sometimes several slightly different ways to perform a given task but which have substantially the same definition. In the following example: To go hiking, into the woods or up the mountain: if into the woods, say "Watch out for badgers."; if up the mountain, say "Better take your compass."; say "You go hiking." ...a phrase has been set up which can be used in three ways: go hiking; go hiking, into the woods; go hiking, up the mountain; Note that commas must be used to divide these "phrase options" from the rest of the text of the phrase. Within the definition of the phrase, the option's name is a valid condition, and if up the mountain, ... tests whether it is set; we can also test if it is not set using: if not up the mountain, ... A more substantial example from the Standard Rules is given by a phrase used mostly for internal, technical reasons: > phrase: {ph_listcontents} list the/-- contents of (object) > > This phrase produces a list of all things whose holder is the given object, according to Inform's traditional conventions for room descriptions and inventory listings. Example: > > list the contents of Marley Wood, as a sentence, with newlines > and including all contents; > > Where this is possible, it's generally better to use `"[list of things in ...]"` instead, which produces the same result in an acceptable way for the middle of a sentence. Note that this phrase is allowed to have multiple options specified, whereas `go hiking` above was not: this is because it was defined thus: To list the contents of (something - an object), with newlines, indented, as a sentence, including contents, including all contents, giving inventory information, giving brief inventory information, using the definite article, listing marked items only, prefacing with is/are, not listing concealed items, suppressing all articles and/or with extra indentation: ... The significant difference is the word `and/or` instead of `or`, which signals that more than one option can apply at a time. ## Let and temporary variables ^^{variables: temporary} ^^{variables: changing temporary variables} ^^{temporary variables <-- local variables} ^^{defining: temporary variables} ^^{phrases: temporary variables in phrases} ^^{Inform 6 equivalent: local variables} ^^{type-checking: for temporary variables} ^^{+to+now (a condition): changing temporary variables} A variable, as we have seen, is a name for a value which changes, though always remaining of the same kind. For instance, if `target` is a number variable (or `number that varies`) then it may change value from 2 to 4, but not from 2 to `"fishknife"`. To make complicated decisions, phrases often need to remember values on a temporary basis. We have already seen this for the counter in a `repeat` loop, which exists only inside that loop, and then is no longer needed. We can also make temporary variables using `let`: > phrase: {ph_let} let (a name not so far used) be (value) & let (a temporary named value) be (value) > > This phrase creates a new temporary variable, starting it with the value supplied. The variable lasts only for the present block of phrases, which certainly means that it lasts only for the current rule. Examples: > > let outer bull be 25; > let the current appearance be "reddish brown"; > let the special room be Marley Wood; > > The kinds of these are deduced from the values given, so that, for instance, > > say "The outer bull scores [the outer bull in words] when you practice archery in [special room]." > > produces > > The outer bull scores twenty-five when you practice archery in Marley Wood. > > The variable name should be a new one; if it's the name of an existing one, then the kinds must agree. So: > > let outer bull be 25; > let outer bull be 50; > > is a legal combination, because the second `let` simply changes the value of the existing `outer bull` variable to a different number. > phrase: {ph_letdefault} let (a name not so far used) be (name of kind) > > This phrase creates a new temporary variable of the given kind. The variable lasts only for the present block of phrases, which certainly means that it lasts only for the current rule. Example: > > let inner bull be a number; > > The variable created holding the default value for that kind – in this case, the number 0. A handful of very obscure kinds have no default values, and then a problem message is produced. Inform also disallows: > > let the conveyance be a vehicle; > > because temporary variables aren't allowed to have kinds more specific than `object`. (This is a good thing: suppose there are no vehicles in the world?) It's quite safe in such cases to use > > let the conveyance be an object; > > instead, which creates it as the special object value `nothing`. Temporary variables made by `let` are only temporarily in existence while a phrase is being carried out. Their values often change: we could say let x be 10; now x is 11; for instance, or indeed we could `let x be 10` and then `let x be 11`. But although we are allowed to change the value, we are not allowed to change the kind of value. The name `x` must always have the same kind of value throughout the phrase to which it belongs, so the following will not be allowed: let x be 45; now x is "Norway"; (The difference between using `let` and `now` here is that `let` can create a new temporary variable, whereas `now` can only alter things already existing: on the other hand, `now` can change many other things as well, whereas `let` applies only to temporary variables.) ## New conditions, new adjectives ^^{phrases: deciding a condition} ^^{to decide whether/if+assert+} ^^{adjectives: defining: with (to decide whether)+sourcepart+} ^^{defining: adjectives: with (to decide whether)+sourcepart+} ^^{conditions: defining with (to decide whether)+sourcepart+} ^^{definition+assert+: with phrase logic} ^^{(it), in source text+sourcepart+} ^^{pronouns: (it), in source text+sourcepart+} ^^{punctuation: colon} ^^{|:} ^^{Inform 6 equivalent: |rtrue/rfalse} We can create new conditions by defining a phrase with `to decide whether` (or equivalently `to decide if`): To decide whether danger lurks: if in darkness, decide yes; if the Control Room has been visited, decide no; decide yes. If the player is indeed in darkness, the decision is "yes" because the `decide yes` stops the process right there. We can now write, for instance, if danger lurks, ... In fact, `danger lurks` is now a condition as good as any other, and can be used wherever a condition would be given. Rules can apply only `when danger lurks`, for instance. > phrase: {ph_yes} yes & decide yes > > This phrase can only be used in the definition of a phrase to decide whether a condition holds. It ends the decision process immediately and makes the condition true. > phrase: {ph_no} no & decide no > > This phrase can only be used in the definition of a phrase to decide whether a condition holds. It ends the decision process immediately and makes the condition false. We can also supply definitions of adjectives like this. So far, new adjectives have been defined like so: {*}Definition: a supporter is occupied if it is described and something is on it. If we want to give a definition which involves more complex logic, we can use a special form allowing us to make arbitrary decisions. In this longer format, the same definition would look like so: {*}Definition: a supporter is occupied: if it is undescribed, decide no; if something is on it, decide yes; decide no. Here `it` refers to the supporter in question. Note that there are now two colons in this sentence, one after `Definition`, the other after the clause being defined. But that apart, it's a phrase like any other: it must end in `yes` or `no` just as the `danger lurks` example must. `Decide no` and `decide yes` are needed so often that they can be abbreviated by leaving out `decide`: Definition: a supporter is occupied: if it is undescribed, no; if something is on it, yes; no. ## Phrases to decide other things {PM_ReturnWrongKind} {PM_UnknownValueToDecide} {PM_RedundantReturnKOV} ^^{phrases: deciding a value} ^^{to decide what/which (value)+assert+} ^^{Inform 6 equivalent: return value} ^^{type-checking: in phrases that decide values} A condition is a yes/no decision, but we can also take decisions where the result is a value. Suppose we want to create a "grand prize", which will have different values at different times in play. Each time the "grand prize" is referred to, Inform will have to decide what its value is, and the following tells Inform how to make that decision: To decide which treasure is the grand prize: if the Dark Room has been visited, decide on the silver bars; decide on the plover's egg. Note that we have to say what kind the answer will be: here it's a kind of thing called `treasure` (which we're supposing has already been created), and as it turns out only two treasures are ever eligible anyway (we're also supposing that the plover's egg and the silver bars are treasures already created, of course). And note also that the phrase must in all cases end with a `decide on ...` to say what the answer is: > phrase: {ph_decideon} decide on (value) > > This phrase can only be used in the body of a definition of a phrase to decide a value. It causes the calculation to end immediately, with the outcome being the given value, which must be of the kind expected. Example: > > To decide which number is double (N - a number): > let D be N times N; > decide on D. Now that we have `grand prize` created, we can use it just as we would use any other value, so for instance: if taking the grand prize, ... As this is something of a dialect difference between English speakers, `what` and `which` are synonymous here, i.e., we could equally well write something like: To decide what number is the target score: ... (A phrase to decide if something-or-other is exactly the same thing as a phrase to decide a truth state, and indeed, if we want to then we can use `decide on T`, where T is a truth state, in its definition. For instance: To decide if time is short: if the time of day is after 10 PM, decide on true; ... decide on whether or not Jennifer is hurried. `Decide on true` is exactly equivalent to the more normally used `decide yes`, and of course it is optional. The last line is more interesting since it effectively delegates the answer to another condition.) ## The value after and the value before ^^^{+to+(name of kind) before (enumerated value) --> before}^^^{+to+(name of kind) after (enumerated value) --> after} ^^{calculation: incrementing} ^^{calculation: decrementing} ^^{values: kinds of value: comparisons} ^^{comparisons: of enumerated values} A point which has come up several times in recent chapters is that enumerated kinds of value have a natural ordering. For example, if we write: Colour is a kind of value. The colours are red, orange, yellow, green, blue, indigo and violet. ...then we not only have seven possible values, we have put them into a sequence, in order of their naming. We can't perform arithmetic on colours, of course, but we can perform comparisons on them. Thus `red < yellow` is true, while `green >= violet` is not. (More on comparisons in the chapter on [Quantities and Equations], which also covers arithmetic.) It's also sometimes useful to get at the sequence directly. First, the two ends: > phrase: {ph_enumfirst} first value of (name of kind) ... value > > This phrase produces the first-created value of the given kind, which should be an enumeration. Example: if we have > > Colour is a kind of value. The colours are red, orange, yellow, green, blue, indigo and violet. > > then `first value of colour` is red. > phrase: {ph_enumlast} last value of (name of kind) ... value > > This phrase produces the last-created value of the given kind, which should be an enumeration. Example: if we have > > Colour is a kind of value. The colours are red, orange, yellow, green, blue, indigo and violet. > > then `last value of colour` is violet. And now how to step forward and back: > phrase: {ph_enumafter} (name of kind) after (enumerated value) ... value > > This phrase produces the next-created value of the given kind, which should be an enumeration. Example: if we have > > Colour is a kind of value. The colours are red, orange, yellow, green, blue, indigo and violet. > > then `colour after orange` is yellow. > phrase: {ph_enumbefore} (name of kind) before (enumerated value) ... value > > This phrase produces the previous-created value of the given kind, which should be an enumeration. Example: if we have > > Colour is a kind of value. The colours are red, orange, yellow, green, blue, indigo and violet. > > then `colour before blue` is green. # Advanced Actions ## A recap of actions ^^{actions} ^^{ACTIONS+testcmd+} ^^{testing commands: >ACTIONS} ^^{+to+try (action)} ^^{+to+silently try (action)} ^^{actions: performing with (try)+sourcepart+} ^^{actions: suppressing success messages with (try silently)+sourcepart+} Actions are impulses to do something, which arise sometimes through typed commands like ``EXAMINE TAPESTRY`` and sometimes through `try` phrases occurring in other rules: Before examining the tapestry, try switching the ultraviolet light on. Every action either succeeds or fails, though failure may not be a bad thing (something better may have happened). Besides any rules applied in the source text, actions are subject to basic realism rules. A general rule ensures that actions are rejected if the actor would need to touch something which is out of reach, or see something which is invisible; and a couple of hundred other built-in rules police individual actions. For instance, if the ``ACTIONS`` testing command has been used to switch monitoring on, then: > UNLOCK CAGE WITH WATERMELON [unlocking cage with watermelon] That doesn't seem to fit the lock. [unlocking cage with watermelon - failed the can't unlock without the correct key rule] Actions generated by `try` phrases are allowed to run `silently`, which means that if nothing out of the way happens and they succeed, then nothing is printed. For instance: Before examining the tapestry: say "(Switching on the lamp first.)"; silently try switching the ultraviolet light on. There are many ways to impose extra rules on actions, and we have seen three main kinds: Before rules, intended so that preliminary activities like the one above can happen before the action is tried; Instead rules, which block or divert the intention, or may cause something spectacularly different to happen; and After rules, which allow for unexpected consequences after the action has taken place. ## How actions are processed {ARSUMMARY} ^^{actions: processing sequence} ^^{actions: rules for actions found in rulebooks} ^^{rules: for actions found in rulebooks} ^^{rulebooks: for actions} ^^{failure: for actions} ^^{success: for actions} ^^{visibility+rel+: in action processing sequence} ^^{touchability+rel+: in action processing sequence} ^^{before (action)+rb+: in action processing sequence} ^^{rules: before rules} ^^{instead of (action)+rb+: in action processing sequence} ^^{rules: instead rules} ^^{after (action)+rb+: in action processing sequence} ^^{rules: after rules} ^^{check (action)+rb+} ^^{carry out (action)+rb+} ^^{report (action)+rb+} The following flow chart shows the natural course of events when Inform deals with a new action – a `taking` action in the case drawn. For quite a long time, the action may still fail, and it may be that nothing actually happens: but eventually a deciding line is crossed, and once that happens the action will certainly succeed. ![achart](doc_images/achart.png) The coloured boxes on this chart represent "rulebooks", that is, collections of rules with a common purpose. The orange boxes for Before, Instead and After were covered in the chapter on [Basic Actions], but the blue boxes are new. The orange boxes are where we put rules to handle unusual situations, or unexpected events: special rules to cover the opening of a container which happens to be booby-trapped, or walking through a doorway into a room where a surprise party is about to be sprung. Blue boxes hold the mundane, everyday rules – the generic ways that particular actions behave. Every action provides these: `Check` rules, to see if it makes sense – for instance, to see that the player is not trying to take their own body, or a whole room, or something they already have; then `Carry out` rules, to actually do what the action is supposed to do – in the case of taking, to move an object into the player's possession; and finally `Report` rules, which tell the player what has happened – perhaps printing up "Taken." When we create a new action, we add a new column to the blue rows in this diagram. As we shall see, we can also put new rules into the existing blue boxes: for instance, if we wanted to increase physical realism by forbidding the player to carry more than a certain weight, we would want to add a new `check taking` rule, and this is entirely legal. In subsequent chapters, we will see ways to intervene at almost every point in the above diagram – from how "Can we see or touch things?" is reckoned, to each and every individual rule in all of these books. In fact, the full system is still more elaborate than the diagram above: see the `action-processing rules` rulebook in the Index of a project for the full picture. Action-processing may be the single most important thing Inform does, so the system is designed to be immensely flexible. On the other hand, that does make it a lot to take in at one look. Newcomers should probably concentrate on `Instead` and `After` as the basic tools for designing the situations turning up routinely in interactive fiction. There are guidelines at the end of this chapter offering advice on which tricks to use when it comes to more complicated needs. ## Giving instructions to other people {var_person_asked} ^^{actions: instructing other characters}^^^{characters (people) <-- actors <-- other people}^^^{characters (people) <-- NPC <-- people}^^^{characters (people) <-- person+kind+: characters} ^^{characters (people): giving instructions to other characters} ^^{instructing other characters} ^^{ordering other characters} ^^{asking (actor) to try+action+ <-- +to+try (action): in (asking) action+sourcepart+} ^^{person asked (- object)+glob+} ^^{actor (- person)+actvar+} ^^{player: as opposed to the actor} So far, all actions have been carried out by the player: which is fine for exploring the passive world of an empty warehouse, but less good for a drama in which other characters have to be contended with. In fact, an action can be carried out by anybody – by any instance of the `person` kind, that is, which includes all the men, women and animals in the story, and not only the player. In interactive fiction, players conventionally ask other characters to do something with commands like ``WILL, GO WEST``. Clearly this should not produce the same action as ``GO WEST``, because a different person will be trying it: this person is called the `actor`, and while the actor is ordinarily the player, here it is the character called Will. Inform distinguishes these two actions like so: going west asking Will to try going west These both use the `going action`: the notation `asking... to try...` is not some kind of `asking` action in its own right. (There _is_ an asking action, for things like asking somebody for directions, but this is unrelated to that.) As a result, we can write rules like so: Instead of asking Will to try going west, say "Will scratches his head, baffled by this talk of westward. Is not the ocean without bound?" To write rules like this, we sometimes want to generalise about who is supposed to do the deed. To do this we can refer to `person asked`, just as the `noun` stands for whatever noun was typed: Instead of asking somebody to try taking something, say "I don't think we ought to tempt [the person asked] into theft, surely?" So if the player types ``ALGY, TAKE SANDWICH``, the `person asked` would be Algy; the `noun` would be the sandwich; and there would be no `second noun`. ## Persuasion {rules_per} ^^{actions: instructing other characters: persuasion rules} ^^{persuasion+rb+} ^^{+toout+persuasion succeeds / fails (persuasion rules)} ^^{rules: persuasion rules for instructing characters} ^^{rules: for other characters} ^^{actions: rules for other characters} ^^{success: for persuasion} ^^{failure: for persuasion} ^^{paragraph breaks: for fooling persuasion refusal} ^^{instead of (action)+rb+: as failure of persuasion} ^^{rules: instead rules} ^^{characters (people): obeying and refusing} `Asking ... to try ...` actions run through their Before and Instead rules like any other actions, but then (if no rule has intervened) something different happens: Inform has to decide whether the person asked consents to try the action or not. By default, the answer is always no, and text like the following will be printed: > WILL, GO WEST Will has better things to do. However, we can intervene to make the answer "yes", using a special kind of rule which produces a yes/no answer. The following examples show how we can give broad or narrow permission, as we choose: Persuasion rule for asking people to try going: persuasion succeeds. Persuasion rule for asking Will to try going west: persuasion succeeds. Such a rule can either declare that `persuasion succeeds`, or that `persuasion fails`, or make no decision and leave it to another rule to say. If it decides that persuasion fails, it is also allowed to say something, describing why: in that event, the standard message ("Will has better things to do.") is suppressed. For example, Persuasion rule for asking Will to try going: say "Will looks put out, and mutters under his breath."; persuasion fails. The following rule, which is really only suitable for testing, makes everybody infinitely obliging: {*}Persuasion rule for asking people to try doing something: persuasion succeeds. Supposing that Will does decide to cooperate, a new action is generated: Will going west and this is then subject to all of the usual action machinery. For instance, we could write a rule such as: Instead of Will going west, say "He runs out into the waves, but soon returns, rueful." So in this case the new action (`Will going west`) failed: but the original action, `asking Will to try going west`, is still deemed to have succeeded – after all, Will *did* try. To put it more formally, `asking X to try A` succeeds if the persuasion rules succeed, and otherwise fails. Note also that `Instead of...` rules written for other people will be treated by Inform as failures, even if we write something like Instead of Will pulling the cord: say "The bell rings." and thus may produce unsatisfactory results such as > WILL, PULL CORD The bell rings. Will is unable to do that. If we wish to write new successful actions for another character, we will need to create appropriate carry out and report rules for them: these will be explained in the sections to follow. (Finally, note that the mechanism Inform uses to see if we have printed a refusal message of our own, in the event of persuasion rules failing, can be fooled if we write a persuasion rule explicitly ending with a `"[paragraph break]"` text substitution.) ## Unsuccessful attempts {var_reason} {rules_fail} ^^{unsuccessful attempt by+rb+} ^^{actions: instructing other characters: unsuccessful attempts} ^^{rules: unsuccessful attempts by other characters} ^^{rules: for other characters} ^^{actions: rules for other characters} ^^{reason the action failed (- rule)+glob+} ^^{characters (people): reporting unsuccessful actions} ^^{ACTIONS+testcmd+} ^^{testing commands: >ACTIONS} ^^{Actions page of Index panel+ui+} ^^{user interface: Index panel: Actions page} ^^{Index panel+ui+: Actions page} Suppose, finally, that Will not only consents to try the action, but it also survives its passage through Before and Instead rules. What happens then? In principle, what happens to Will is exactly what would have happened to the player in Will's place. For instance: > WILL, GO EAST Will leaves to the east. If on the other hand Will's attempt is frustrated because one of the checking rules stops him, then Will's action fails. For instance, if Will tries going northeast but there is no room to northeast, one of the rules checking the `going` action will stop him. We will then see this: > WILL, GO NORTHEAST Will is unable to do that. This is rather a generic message, and we may want something more interesting. We can provide that using yet another special kind of rule: Unsuccessful attempt by Will going: say "Will blunders around going nowhere, as usual." Even that is still a little generic, though, because it treats all of the various ways that `going` can fail as the same. If we have ``ACTIONS`` switched on, we can see what goes on behind the scenes when we ask Will to walk into a door: > WILL, GO WEST [asking Will to try going west] [(1) Will going west] [(1) Will going west - failed the can't go through closed doors rule] Will blunders around going nowhere, as usual. [asking Will to try going west - succeeded] (The "(1)" lets us know that a new action is starting during the old one, and before the old one finishes: sometimes we go up to three or four deep, though seldom more in practical cases.) We can now rewrite the `unsuccessful attempt` rule like so: Unsuccessful attempt by Will going: if the reason the action failed is the can't go through closed doors rule, say "Will looks doubtful and mumbles about doors."; otherwise say "Will blunders around going nowhere, as usual." The value `reason the action failed` is set to whichever checking rule threw out the action which Will tried. The names of these rules try to be self-explanatory – at any rate, those with gnomic names are not useful for this sort of thing, and can be ignored – and can be found out either using ``ACTIONS`` or by consulting the Actions index: > ACTIONS Actions listing on. > TAKE ME [taking yourself] You are always self-possessed. [taking yourself - failed the can't take yourself rule] Finally, note that `unsuccessful attempt` rules apply only when the person in question is being asked to perform the action by somebody else – as in the examples above. ## Spontaneous actions by other people ^^{actions: spontaneous by other people} ^^{actions: performing with (try)+sourcepart+} ^^{+to+try (actor) trying (action)} ^^{characters (people): acting spontaneously} ^^{unsuccessful attempt by+rb+: not used for spontaneous actions} The player's actions happen not only when they type a command, but can also happen spontaneously as a result of a `try` phrase. try going west try asking Will to try going west The latter might, of course, result in Will trying going west: or it might not – that depends on the persuasion rules. But as the author, we have the ultimate powers of persuasion, and can make Will act in any way we like, without asking: try Will going west Nobody in the simulated world requested this: it is an impulse felt by Will alone, so that – from the player's point of view – Will is acting spontaneously. The player need not be anywhere nearby, and may never know what happened. Recall that when actions work their way down through the flow-chart, they are stopped before reaching the `report` stage – when the player is told about them – if they are running `silently`. This is also where Inform stops an action which is not witnessed by the player. To repeat a point in the previous section: `unsuccessful attempt` rules do not apply to actions which the author has caused to happen, using `try`. When such actions fail, they invoke no special set of rules. Indeed, when `try` causes somebody other than the player to try an action, nothing will be printed to report back on success or failure. If Will can't go west, that's his problem. Note that the text `try Will going west` involves the actor's name immediately placed next to the action he is to try, which in a very few cases might cause ambiguities. If the actor's name contains a participle like `going` – say, if Will's full name turned out to be Mr Will Going – then we would have to write out the action name in full, using `trying` to clarify matters: try Will Going trying going west ## New actions {NEWACTIONS} {PM_MatchedAsTooLong} {PM_MultiwordPastParticiple} {PM_GrammarMismatchesAction} {PM_ActionAlreadyExists} {PM_ActionBothValues} {PM_ActionClauseUnknown} {PM_ActionMisapplied} ^^{actions: defining new actions} ^^{defining: actions} ^^{Inform 6 equivalent: verbs} ^^{(applying to), in defining actions+sourcepart+} ^^{(requiring), in defining actions+sourcepart+} ^^{(visible thing), in defining actions+sourcepart+} ^^{(touchable thing), in defining actions+sourcepart+} ^^{(carried thing), in defining actions+sourcepart+} ^^{light: requirement in defining actions} ^^{actions: referring to current action with (action)+sourcepart+} ^^{understand (verb) as (action)+assert+} ^^{understanding: verbs} ^^{Inform 6 equivalent: synonyms} ^^{synonyms} ^^{understanding: requirements for objects in actions}^^^{understanding <-- parsing} It is not often that we need to create new actions, but a large work of interactive fiction with no novelty actions is a flavourless dish. Here we shall create an action for photographing things. The Ruins is a room. "You find this clearing in the rainforest oddly familiar." The camera is in the Ruins. "Your elephantine camera hangs from a convenient branch." A carved post is here. Photographing is an action applying to one thing and requiring light. In theory that text is already sufficient to make the new action, but what we have so far is rudimentary to say the least. The two qualifications give Inform the useful information that we cannot photograph in the dark, and that we need to be photographing something – not, as in the case of waiting or taking inventory, acting without reference to any particular thing external to ourselves. The word `visible` here tells Inform that we do not need to be able to touch the thing in question: a line of sight is good enough. These two stipulations were necessary because the default arrangement is that any object must be in touching range, and that most actions can be performed in darkness. (Also, note that if you invent an action which needs to apply to directions like `north` or `south`, you need to make this apply to visible things, because the object used inside Inform to represent the idea of `north` can be seen but not touched. So for understanding purposes, `visible thing` is understood as meaning any visible thing or direction: it's more general than `thing`, not more specific.) Occasionally, when writing general rules about actions, it can be useful to find out what the current action's requirements are: the following conditions do what they suggest. > phrase: {ph_requirestouch} if action requires a/-- touchable noun: > > This condition is true if the action being processed is one whose (first) noun is an object which needs to be touchable by the actor. For example, it's true for `taking`, but false for `examining`. > phrase: {ph_requirestouch2} if action requires a/-- touchable second noun: > > This condition is true if the action being processed is one whose second noun is an object which needs to be touchable by the actor. For example, it's true for `putting the brick in the sack`, but false for `throwing the brick at the window`. > phrase: {ph_requirescarried} if action requires a/-- carried noun: > > This condition is true if the action being processed is one whose (first) noun is an object which needs to be carried by the actor. For example, it's true for `dropping`, but false for `taking`. > phrase: {ph_requirescarried2} if action requires a/-- carried second noun: > > This condition is true if the action being processed is one whose second noun is an object which needs to be carried by the actor. > phrase: {ph_requireslight} if action requires light: > > This condition is true if the action being processed is one which can only be performed if the actor has light to see by. For example, it's true for `examining`, but false for `dropping`. Here are two further examples, one involving no nouns, and one involving two: Blinking is an action applying to nothing. Scraping it with is an action applying to two things. These actions now exist, but are not yet useful because (1) they never happen, and (2) even they did happen, nothing would follow, because Inform has not yet been given rules for what they should say and do. Problem (1) is easily overcome: Understand "blink" as blinking. Understand "scrape [something] with [something]" as scraping it with. Now when the player types ``BLINK``, the blinking action will be generated, and ``SCRAPE POTATO WITH BRUSH`` similarly. We will return to the whole subject of parsing, as this process of understanding the player's commands is called, later on, but this gives the gist of it. As for problem (2), see the next section. But it's worth pausing first to establish that there are three different ways to write about actions in Inform. Suppose we run this: The Inform Test Kitchen is a room. The sweet potato and the wire brush are here. Scraping it with is an action applying to two things. When play begins: showme the scraping it with action; showme scraping potato with brush. This shows two subtly different values, with different kinds: ``` transcript action name: scraping it with action: scraping the sweet potato with the wire brush ``` 1) `scraping it with action` refers to the action without thinking about any particular use of it. It means the business of scraping in general, not any one instance of scraping. The word `it` stands in for the position of the first noun. (This is why we wrote `Scraping it with is...` in the declaration, and why the `Understand` line ended with `as scraping it with`.) This is a value with the kind `action name`. Similarly for our other examples: `photographing action` and `blinking action` are also values of the kind `action name`. 2) On the other hand, `scraping the sweet potato with the wire brush` is a specific act of scraping, and that is a value of the kind `action`. Similarly for `photographing the carved post` and `blinking`, which are also `action` values. The third way to talk about actions is to generalise about them with a so-called "action pattern". These are not values, but are conditions which actions might or might meet. (It's the difference between numbers like 2, 7 or -40, and requirements like "being between 1 and 10".) For example: Instead of scraping a door with something: if scraping an open door with something, say "[The noun] swings away."; say "You give [the noun] a good scrape." The rule is set to run only if the current action matches the pattern `scraping a door with something`; the `if` produces the text about swinging away only if the current action matches `scraping an open door with something`. This, on the other hand, does not work: Instead of scraping it with: ... And that is because `scraping it with` is not a pattern: `it` does not say anything about what goes in the first position. ### See Also - [Understanding] for the full story. ## Irregular English verbs ^^{understand (verb) as (action)+assert+} ^^{understanding: verbs} ^^{English: irregular verbs} ^^{actions: irregular verbs in action names} Our three example actions can be recognised in play using the following: Understand "photograph [something]" as photographing. Understand "blink" as blinking. Understand "scrape [something] with [something]" as scraping it with. The last of these examples shows why Inform does not risk generating this automatically: English is so full of irregular verbs. Inform could have guessed "blink" and "photograph", but might then have opted for "scrap" instead of "scrape". Inform does risk automatically generating the past participle of an action. (Many past participles are never needed, so the stakes are lower if Inform gets this wrong.) What usually happens is that the "-ing" is replaced with "-ed", thus photographed, blinked, scraped – but Inform has a dictionary of some 460 irregular exceptions, such as caught, fled, crossbred, taken, woven. So with luck Inform will guess correctly. If not, we can get around this like so: Squicking is an action with past participle squacked, applying to one thing. ## Check, carry out, report ^^{actions: rules for new actions} ^^{rules: for new actions} ^^{rulebooks: for new actions} ^^{check (action)+rb+} ^^{carry out (action)+rb+} ^^{report (action)+rb+} ^^{(instead), to stop the action+sourcepart+} The normal behaviour of an action is specified by its three associated rulebooks – check, carry out and report. In the case of our `photographing` example, these rulebooks will be: 1) **Check photographing**. Here, for instance, we need to verify that the player has the camera. If any of our checks fail, we should say why and stop the action. If they succeed, we say nothing. 2) **Carry out photographing**. At this stage no further checking is needed (or allowed): the action now definitively takes place. At this point we might, for instance, deduct one from the number of exposures left on the film in the camera, or award the player points for capturing something interesting for posterity. But we should say nothing. 3) **Report photographing**. At this stage no further activity is needed (or allowed): whatever effect the action had, it has happened and is now over. All we can do is to say what has taken place. So far we have not really gone into the business of what rulebooks are, and we don't do so here either – suffice to say that we can now create whatever rules we need: A check photographing rule: if the camera is not carried: say "You can hardly photograph without a camera, now can you?" instead. In fact, writing `a check photographing rule` is over-formal. We can more simply label our rules like so: Check photographing: if we have photographed the noun: say "You've already snapped [the noun]." instead. Report photographing: say "Click!" For the sake of brevity, photography has no interesting consequence (no points to be won, no film to use up), so there are no carry out rules here. Note the way we used the word `instead` once again to stop actions in their tracks. We can continue to add rules at any point, and a classic thing that happens when testing a new work is that the designer realises there is a case which has not been thought of: Check photographing: if the noun is the camera: say "That would require some sort of contraption with mirrors." instead. As a pedantic footnote here: It sometimes comes as a surprise to power users of Inform that with a two-noun action like our example `scraping it with`, rules like `Check scraping it with` can legally be written (and similarly for carry out and report). This appears to contradict what we said about rules like `Instead of scraping it with` being wrong, because `scraping it with` is an action name not an action pattern. In fact this is not a contradiction. For reasons of efficiency, there is not one single `Check` rulebook with hundreds or thousands of rules in: there is one for each action, whose name consists of the word `Check` followed by the action name. So `Check photographing` is the rulebook holding the example rules above. Similarly for `Check scraping it with`. In any case, it is _also_ legal to write `Check scraping something with`, or `Check scraping a door with something edible`, and similar. So there is no actual need to use `it` in the names of `Check` rules, and it's perhaps better style not to, but the fact that `Check scraping it with` works is not a bug. ## Action variables {PM_ActionVarsPastTense} {PM_ActionVarAnd} {PM_ActionVarOverspecific} {PM_ActionVarUnknownKOV} {PM_ActionVarValue} {PM_BadMatchingSyntax} ^^{actions: variables for actions} ^^{variables: for actions} ^^{defining: action variables} ^^{(matched as), in describing action variables+sourcepart+} ^^{|called: in defining action variables} ^^{setting action variables+rb+} For some complex situations, it can be useful to keep track of a few values throughout the processing of the action. This is not an everyday occurrence: in the Standard Rules, for instance, only two or three out of 90 actions need to do this. But suppose we want to write a more deluxe version of our `photographing` action. This time, rather than having a single thing called the "camera", we will provide a whole range of possible cameras, varying in quality: Photographing is an action applying to one visible thing and requiring light. Understand "photograph [something]" as photographing. The Studio is a room. Sally is a woman in the Studio. A foam-lined tote bag is in the Studio. A camera is a kind of thing. A camera has a number called picture quality. The digital SLR camera is a camera in the tote bag. The player carries a camera called the instant one-shot camera. The picture quality of the SLR camera is 10. The picture quality of the one-shot is 2. Definition: a camera is sharp if its picture quality is 5 or more. And we will want the photographing action to have the player use the best-quality camera which comes to hand. We will give the action a variable called the 'camera photographed with', thus: The photographing action has an object called the camera photographed with. Every action's variables must be named differently from those of all other actions, because there are some `before` rules (for instance) which take effect for many different actions, and which might need access to any of their variables. So action variables should be named in a way marking out to which action they belong. The best way to do this is to include the past participle of the action name – just as `camera photographed with` contains the past participle `photographed` of the action `photographing`. This value is created when the action begins, and disappears when the action ends. (If the action should happen a second time before the first time was completed, a second copy of the value is created, leaving the original undisturbed.) When the action begins, the value starts out as something neutral – so if it is a number, it starts out as 0, if a text, it starts out as the blank text `""`, and so on. Here it is an object, so it starts out as nothing – the value meaning no object at all. But of course we want to give it a value ourselves. We can do that using the `setting action variables` rulebook. For instance: Setting action variables for photographing: now the camera photographed with is the sharpest camera which is carried by the actor. The `setting action variables` rulebook is run through before even the before rules, and it has no power to stop or change the action. Its rules should say nothing and do nothing other than to set rulebook variables like this one. Note that it is intended to work for any actor, not only the player: so rather than referring to the player as the performer of the action, we need to write `the actor`, as in the example above. (See subsequent sections for more on actors.) We can now write rules such as: A check photographing rule: if the camera photographed with is nothing: say "You can hardly photograph without a camera, now can you?" instead. Only rules to do with the photographing action – before, instead, after, check, carry out, or report rules, and so on – are allowed to see the 'camera photographed with' value: it's the private property of the action. A further elaboration allows us to make rules about photographing neater to write. If we create our variable like so: The photographing action has an object called the camera photographed with (matched as "using"). ...then we are now allowed to add an optional 'using ...' clause onto a description of the action. The clause has to be introduced with a single word: here, it's 'using'. For instance, we could write rules such as Instead of photographing something using the one-shot camera: say "But you promised to give this to Sally's nephew." Check photographing something using the noun: say "That would require some sort of contraption with mirrors." instead. Report photographing something using a sharp camera: say "You feel cool and important as the shutter clicks." (This is the method used by the Standard Rules to attach optional clauses such as `to`, `with` and `through` to the going action.) ## Making actions work for other people ^^{rules: for new actions for other characters} ^^{rules: for other characters} ^^{actions: rules for other characters} ^^{player: as opposed to the actor} The `photographing` action now works very nicely when the player does it. But not when others try. Suppose that neither the player, nor Clark Gable, is holding the camera: > PHOTOGRAPH CLARK You can hardly photograph without a camera, now can you? > CLARK, PHOTOGRAPH ME > An uncanny silence. What has happened is that the rules written so far are all implicitly restricted to the player only. This is because when we write – Check photographing: if the camera is not carried: say "You can hardly photograph without a camera, now can you?" instead. the action is `photographing`, not `Clark photographing`. In the next few sections we shall see how to make the rules work nicely for everybody. This is a little bit harder, so it should be noted right away that in many projects there is no need. In a story which has no other characters who succumb to persuasion, for instance, only the player will ever try the action. ## Check rules for actions by other people {PM_DuplicateRuleName} {PM_RuleWithComma} ^^{check (action)+rb+: for other characters} ^^{rules: for other characters} ^^{actions: rules for other characters} ^^{ACTIONS+testcmd+} ^^{testing commands: >ACTIONS} ^^{unsuccessful attempt by+rb+} ^^{reason the action failed (- rule)+glob+} ^^{|someone: in actions} If we want to impose the restriction about carrying the camera on other people, we need a rule like the following: Check someone photographing: if the person asked does not carry the camera, stop the action. Implicitly, that `someone` excludes the player. Note that we say nothing in this rule, stopping the action without a word: after all, Clark might well be out of sight when trying this. If he is within sight, then we read: > CLARK, PHOTOGRAPH ME Clark Gable is unable to do that. We saw before that Inform's built-in rules all have handy names (the `can't drop what's already dropped rule`, and such), and that these are useful when writing better "unable to..." messages. So for a deluxe version, we end up with: Check someone trying photographing (this is the other people can't photograph without the camera rule): if the person asked does not carry the camera, stop the action. And now, with ``ACTIONS`` on, we find that: > CLARK, PHOTOGRAPH ME [asking Clark Gable to try photographing yourself] [(1) Clark Gable photographing yourself] [(1) Clark Gable photographing yourself - failed the other people can't photograph without the camera rule] Clark Gable is unable to do that. [asking Clark Gable to try photographing yourself - succeeded] which means that we could have, say, Unsuccessful attempt by Clark photographing: if the reason the action failed is the other people can't photograph without the camera rule, say "Clark is too suave to be embarrassed. 'Frankly, my dear, I don't have a camera.'"; otherwise say "Clark tries, and fails, to take a photograph." ## Report rules for actions by other people ^^{report (action)+rb+: for other characters} ^^{rules: for other characters} ^^{actions: rules for other characters} ^^{|someone: in actions} Report rules for the player's actions are easy to write, and for many actions, they are not much harder for other people either: Report photographing: say "Click!" Report someone photographing: say "Click! [The person asked] takes a snapshot of [the noun]." But once other people are involved, we have to go to some trouble to get all of the possibilities right. Here is a case which did not immediately occur to the author of the `going` action, for instance: > GET IN CAGE You get into the cage. > CLARK, GET IN AUTOMOBILE Clark Gable gets into the automobile. > CLARK, PUSH CAGE WEST Clark Gable goes west in the automobile, pushing the cage in front, and you along too. **The Lot** (in the cage) In the Lot you can see an automobile (in which is Clark Gable). We said before that report rules are skipped if the action is running `silently`, or if the action is one that the player does not witness. But that is also a tricky concept. Inform's doctrine is that you witness an action if you can see any of the actor, the noun or the second noun at either the beginning or the end of the action; except that being able to see a backdrop does not count. Thus if Clark Gable, in Beverly Hills, photographs the Hollywood sign then we do not witness this from Sunset Boulevard merely because we, too, can see the Hollywood sign. While the report rules for actions by the player must actually report something, report rules for other people's actions are under no such obligation. For instance, if Clark unlocks a door from the other side to the player, then this counts as an action that the player witnesses – and after all, it could be argued that the player should hear the key turning in the lock – but in fact the standard rules for reporting locking choose to say nothing. ## Actions for any actor ^^{rules: for any actor (including the player)} ^^{actions: rules for any actor (including the player)} ^^{actor (- person)+actvar+} In the previous sections, we created a new action by providing one set of rules for the player and another for anybody else who might try to perform it. These rules began with action descriptions in one of the following forms: Instead of taking a container, ... Instead of P taking a container, ... The first form implies that the player must be performing the action: the second allows for any person matching P to be the action, except that this person must not be the player. That means that all rules seen so far either affect only the player, or only other people. This is often convenient, but sometimes we need to set up a complicated action which really does work in the same way for every actor – for instance, the built-in Inform actions provided by the Standard Rules aim to do this. We can write such rules thus: Instead of an actor taking a container, ... Here the rule applies to anyone who tries taking a container, player or not. Inside such a rule, the special value 'the actor' is the person performing the action. For instance, the Standard Rules include this one: Carry out an actor wearing (this is the standard wearing rule): now the actor wears the noun. ## Out of world actions {OUTOFWORLD} ^^{|out of world} ^^{actions: |out of world} ^^{Inform 6 equivalent: |meta} ^^{every turn+rb+: not for (out of world) actions+sourcepart+} ^^{time: not passing for (out of world) actions+sourcepart+} ^^{turns: not passing for (out of world) actions+sourcepart+} ^^{before (action)+rb+: not used for (out of world) actions+sourcepart+} ^^{rules: before rules} ^^{instead of (action)+rb+: not used for (out of world) actions+sourcepart+} ^^{rules: instead rules} ^^{after (action)+rb+: not used for (out of world) actions+sourcepart+} ^^{rules: after rules} The actions seen so far are all impulses causing the protagonist inside the fictional world to do something, or at least try to. But when the player types ``QUIT`` or ``SAVE``, that is not a request for anything to happen in the fictional world: it is an instruction to the program simulating that world. In fact, just the same, such requests are treated as actions, but of a special category called "out of world" actions. They do not cause time to pass by, so the turn counter does not advance, nor does this command cycle count as a turn at all; and they are altogether exempt from `Before`, `Instead` and `After` rules. Only the player is allowed to try them. We can also create new out-of-world actions. Suppose we want a dialogue like so: > ROOMS You have been to 1 out of 8 rooms. Here is a complete implementation: Requesting the room tally is an action out of world. Report requesting the room tally: say "You have been to [number of visited rooms] out of [number of rooms] room[s]." Understand "rooms" as requesting the room tally. It is important not to use `out of world` actions for anything affecting what goes on in the fictional world, or realism will collapse, and action-processing may also fail to work in the usual way. `Out of world` actions should be reserved for providing commands like ``ROOMS``, which monitor events rather than participate in them. ## Reaching inside and reaching outside rules {rules_ri} ^^{rules: reaching inside / outside} ^^{rules: access to things referred to in actions} ^^{actions: reaching inside / outside rules} ^^{reaching inside / outside+rb+} ^^{actions: requirements for actions} ^^{touchability+rel+: in action processing sequence} ^^{Inform 6 equivalent: scope rules} The flow chart back at the start of this chapter shows that, early on in processing an action (between Before and Instead), Inform asks the question "Can we see or touch things?" This is where it enforces the requirements in the action's definition: Photographing is an action applying to one visible thing and requiring light. Scraping it with is an action applying to two things. Seeing and touching are two different questions, which Inform answers in different ways. We shall see ways to modify or entirely alter what can be seen using the `deciding the scope of something` activity when we get to the Understanding and chapter on [Activities]s, and later in this chapter we will change the definition of touchability. What both have in common is that they are complicated questions, affected by the circumstances. We cannot simply declare that the player can touch a given lever, or can see in a given room: we must arrange for there to be no barriers between the player and the lever, or for there to be a light source in the room. An example of rules applying to given objects is provided by the way that Inform decides whether the player can reach something or not. For instance, suppose the following: {*}The Laboratory is a room. In the Laboratory is a conical flask. The flask is closed and transparent. In the flask is an antibumping granule. The player will be able to examine the granule but not to take it, as that would require reaching through glass. Suppose the player does type ``TAKE GRANULE``: then Inform looks for potential barriers between the player and the granule, and of course finds the conical flask. If, as in this case, the thing to be touched is on the inside, then Inform asks the `reaching inside` rules for permission. There are two reaching inside rules built in to Inform: - `can't reach inside rooms rule` - `can't reach inside closed containers rule` and in fact the second of these rules will cause the taking action to fail, because the conical flask is a closed container. (The other rule has to do with a player in one room able to see another room through, say, a telescope – merely having a line of sight doesn't give the ability to reach into the frame.) Symmetrically, Inform also has `reaching outside` rules, used if the player is inside something and wants to reach an object in the wider room. (From a bed, probably yes; from a cage, probably no.) This ordinarily contains just one rule: can't reach outside closed containers rule ## Visible vs touchable vs carried ^^{actions: requirements for actions} ^^{(requiring), in defining actions+sourcepart+} ^^{(visible thing), in defining actions+sourcepart+} ^^{(touchable thing), in defining actions+sourcepart+} ^^{(carried thing), in defining actions+sourcepart+} ^^{light: requirement in defining actions} ^^{understanding: requirements for objects in actions} ^^{taking+action+: implicit taking} ^^{implicitly taking something+activity+} ^^{implicitly taking something+activitycat+} To recap, actions are created like so: Photographing is an action applying to one visible thing and requiring light. Depositing it in is an action applying to two things. Taking inventory is an action applying to nothing. When an action applies to things, rather than values, Inform allows some restrictions on access to be put in place. Inform often allows impossible actions to be tried — eating a door, say, or putting a suitcase inside itself — so that they can be stopped later on a checking process, and a good explanation can be given. Most of those rules have to be specific to the actions involved. But some actions are impossible for spatial reasons. For example, if the Mona Lisa is inside a sealed glass box, and the player is outside that box, then many different actions are immediately out of the question: eating the painting, rubbing it, taking it, putting it in a rucksack, and so on. The reason in each case is the same: you can't get at it. So Inform provides a common system, shared by all actions, to check on this. Under this system, every thing involved in an action is subject to one of three possible levels of restriction: 1) `visible`. This is the weakest level of restriction — no restriction at all. The word `visible` is used very loosely here, and refers to the fact that typed commands only normally understand the names of things the player can see. Because of that almost all actions involve visible things, and so it's not a stringent requirement. But to reiterate: `visible` here actually means unrestricted. There is no requirement for the actor to be `able to see` the item in the sense of the `visibility relation`. 2) `touchable`. Here the actor must be `able to touch` the thing, as decided by the `touchability relation`. A full definition of that can be found in [The built-in verbs and their meanings], but roughly speaking it means the actor is in the same room as the object, and there are no physical barriers in between. This is the default level of restriction: so, for example, `an action applying to two things` requires both things to be `touchable`. There is one small exception, which is that touchability is waived in the case when an actor other than the player would need to touch a door or backdrop. (This is a compromise to avoid difficulties arising from the ambiguous locations of such items.) 3) `carried`. The strongest level of restriction. The actor must be directly carrying the thing in question. However, this strict rule is made less painful by an automatic process called "implicit taking". If an action requires something to be carried, and it isn't, then a silent taking action will be generated first. If this succeeds, then the original action can proceed after all, after some text like ``(first taking the top hat)`` is printed. If an action involves two things, they need not have the same requirement as each other. If we set this up: Waving it at is an action applying to one carried thing and one visible thing. then trigger an action with the command ``WAVE MAGIC WAND AT BANYAN TREE``, the player must be holding the wand, but need only be able to see the tree. ## Changing reachability {var_person_reaching} ^^{rules: reaching inside / outside} ^^{rules: access to things referred to in actions} ^^{actions: reaching inside / outside rules} ^^{reaching inside / outside+rb+} ^^{actions: requirements for actions} ^^{(touchable thing), in defining actions+sourcepart+} ^^{understanding: requirements for objects in actions} ^^{Inform 6 equivalent: scope rules} ^^{person reaching (- object)+glob+} ^^{container in question (- object)+glob+} ^^{supporter in question (- object)+glob+} ^^{+toout+deny access (reaching inside / outside)} ^^{+toout+allow access (reaching inside / outside)} ^^{+toout+access, deny / allow access (reaching inside / outside)} The question of what the player can, and cannot, reach to touch is important in interactive fiction. It contains some of the subtlest ideas in the model world, though they often go unnoticed. For instance, if a key is on a shelf which is part of a closed box, can we reach for the key? This comes down to whether the shelf, described only as `part of` the box, is on the inside or the outside: and in fact, because it cannot know which is the case, Inform allows either. So in general it is best to regard `parts` as being exterior parts, but to avoid having parts on containers that might in the course of play be closed up with the player inside. We can, if we wish, change the principles of what can be touched by writing new reaching inside or reaching outside rules. Returning to the example of the conical flask: A rule for reaching inside the flask: say "Your hand passes through the glass as if it were not there, chilling you to the bone."; allow access. (Or this could equally be called `a reaching inside rule for the flask`.) More generally, we could give the usual flexible description of what the rule applies to: A rule for reaching inside open containers: say "Your hands seem enigmatically too large for [the container in question]."; deny access. The `container in question` is the one to which the rule is being applied. Note that a reaching inside rule can `deny access` (stopping with failure), or `allow access` (stopping with success), or neither, in which case the decision is left up to any subsequent rules in the rulebook to make. If none of them decide, access is allowed. If it seems possible that these rules will be employed by people other than the player, then we need to write them a little more carefully, and in particular we need to ensure that they print nothing for other people. In the first case below, anybody can reach through the glass; in the second case, only the player cannot reach into open containers. A rule for reaching inside the flask: if the person reaching is the player, say "Your hand passes through the glass as if it were not there, chilling you to the bone."; allow access. A rule for reaching inside open containers: if the person reaching is the player: say "Your hands seem enigmatically too large for [the container in question]."; deny access. The `person reaching` is, as its name suggests, the person trying to reach through the barrier in question. ## Changing visibility {visibility} ^^{actions: requirements for actions} ^^{visibility+rel+: requirement in defining actions} ^^{visibility+rel+: rules for determining darkness} ^^{visibility+rb+} ^^{rules: for visibility} ^^{+toout+there is sufficient / insufficient light (visibility rules)} ^^{+toout+sufficient / insufficient light, there is sufficient / insufficient light (visibility rules)} ^^{+toout+insufficient / sufficient light, there is insufficient / sufficient light (visibility rules)} ^^{darkness: rules to change perception of} ^^{light: rules to override sufficiency of} ^^{Inform 6 equivalent: darkness} ^^{looking+action+} Ordinarily, Inform has a simple model for visibility: it is either fully light or it is fully dark, and certain actions are impossible in the dark, such as examining something. We first need to remember that darkness affects what actions are even tried, as far as the player's typed commands go. If the player is in a dark room, and there is a screwdriver on the floor, the command ``EXAMINE SCREWDRIVER`` will not try any action: the screwdriver is not "in scope", which means that the parser thinks the player does not have any means of knowing it exists. (The rules for scope can be modified – see the chapter on [Activities].) But let's suppose that the player types ``EXAMINE BOOK``, and is holding the book in question. The book is now "in scope", so the action `examining the book` is tried. Some actions require light to be present, and `examining` is one of those. So Inform consults the visibility rules to see if it can go ahead. By default, there is only one visibility rule, which says `yes` in the light and `no` in darkness. Here, though, we create another one: Visibility rule when in darkness: if examining the book: say "You have to squint. Still..."; there is sufficient light; there is insufficient light. A visibility rule must always conclude `there is sufficient light`, or `there is insufficient light`, or else do nothing and leave it to other rules to decide. It is a possibly unexpected fact that `looking` does not require light, but instead behaves differently in darkness – it prints a pseudo-room-description such as ``` transcript **Darkness** It is pitch dark, and you can't see a thing. ``` instead of printing the description of the player's current room. This means that the `looking` action is unaffected by visibility rules. All the same, what `looking` does in the dark can be changed by using the two activities `printing the name of a dark room` and `printing the description of a dark room` (see the chapter on [Activities] for details). ## Stored actions {kind_storedaction} ^^{actions: stored actions} ^^{stored actions} ^^{actions: as values} ^^{values: actions as values} ^^{|action name} As we have seen, to describe an action fully takes a complicated little bundle of information – we need to know what is to be done, who will do it, and what it will be done to. There are times when we would like to remember an action and look back on it later (perhaps many turns later, after many other actions have taken effect) – but this is not easy to do with only the techniques we have seen so far. There are quite a few cases to get right, and it would be easy to not store quite enough of the details. Fortunately, Inform provides a kind of value called `action` which can do all of this automatically. (In older versions of Inform this was called `stored action`, but the word `stored` is now unnecessary, and makes no difference.) As with most other kinds of value, actions can be held in variables, `let` values, properties or table columns. For example: The best idea yet is an action that varies. creates a variable called `the best idea yet` which holds an action. This will normally be created holding the default value – the player waiting. We really only have two ways to make more interesting actions. One is by typing them out explicitly, like so: now the best idea yet is pushing the button; Here `pushing the button` is a constant of the kind `action`, so it goes into happily into `best idea yet` in the same way that a number like 3 could go into a number that varies. The action must be specific in every respect, so `taking something` or `doing something` will not work – `taking something` is really a general description of many possible actions, not an action in its own right. The other way to produce a useful action is: > phrase: {ph_currentaction} current action ... action > > This phrase produces the action currently being processed as a value – it literally stores the action, and remembers, if necessary, the exact wording of the player's command at the time it was stored – so that even actions arising from commands like ``LOOK UP X100 IN THE CODE BOOK`` can be stored faithfully. Examples: > > let the present whim be the current action; > say "How you would like to be [current action]."; > > This only makes sense if an action is currently going on, so it shouldn't be used in `every turn` rules, for instance. So much for making actions: now for making use of them. The first obvious idea is to store up an action for several turns and then have it take effect later. That's easily done: just as we can `try` any action written out explicitly, so we can also try a stored one. The phrase to do this has exactly the same wording either way, since it does the same thing either way. But actions can still be useful even if we never intend to try them. For one thing, we can say them, and this produces a fairly natural description of what the action is: Before doing something in the presence of the bearded psychiatrist: say "'Zo, the subject vishes to engage in [the current action]. Zis is very interesting.'" will produce text such as: ``` transcript "Zo, the subject vishes to engage in rubbing the fireman's pole. Zis is very interesting." ``` One of Inform's most convenient features is its ability to test if the action being processed matches vague or complicated descriptions of whole classes of actions. For example, if the best idea yet is taking something, ... works even though `taking something` is not a single action; it's a description which could apply to many different actions (taking a box, taking a ball, and so on). What Inform tests is whether the `best idea yet` value, a single action, fits this description or not. We can be even vaguer: if the best idea yet is doing something to the lever, ... Just occasionally, this can lead to ambiguities. For instance, if the current action is wearing something, ... fails because Inform thinks `wearing` is meant in the sense of the current action having clothes on, so it produces a problem message. To avoid this, simply write: if the current action is trying wearing something, ... which can't be misunderstood. Something else to be aware of is that the terms `actor`, `noun` and so on will refer to that action: for instance, in if the best idea yet is taking the noun, ... `noun` here refers to the noun in `best idea yet`, not to its meaning outside of this phrase (if indeed it has such a meaning). When dealing with actions, we sometimes want to know what they are dealing with. We can extract this information using the following phrases: > phrase: {ph_actionpart} action name part of (action) ... action name > > This phrase produces the action name part of an action. Example: suppose the current actor is Algy, who is throwing the brick at Biggles. Then > > action name part of the current action = throwing it at action > phrase: {ph_nounpart} noun part of (action) ... object > > This phrase produces the (first) noun of an action. Example: suppose the current actor is Algy, who is throwing the brick at Biggles. Then > > noun part of the current action = the brick > > If the noun is something other than an object, this produces just `nothing`, the non-object. > phrase: {ph_secondpart} second noun part of (action) ... object > > This phrase produces the second noun of an action. Example: suppose the current actor is Algy, who is throwing the brick at Biggles. Then > > second noun part of the current action = Biggles > > If the second noun is something other than an object (for instance for the command ``SET DIAL TO 3417`` it would be the number 3417), this produces just `nothing`, the non-object. > phrase: {ph_actorpart} actor part of (action) ... object > > This phrase produces the person who would be carrying out the action if it were being tried. Example: suppose the current actor is Algy, who is throwing the brick at Biggles. Then > > actor part of the current action = Algy The following phrase is a convenient shorthand form: > phrase: {ph_involves} if (action) involves (object): > > This condition is true if the object appears as any of the actor, the noun or the second noun in the action. Example: > > if the current action involves Algy > > would be true for `give revolver to Algy`, `Algy trying flying the Sopwith Camel`, `examine Algy` and so on, but false for `asking Raymond about secret airfield`. > phrase: {ph_actionof} action of (an action) ... action > > This phrase is now seldom needed. It produces a literally typed action as a value. Example: > > now the best idea yet is the action of pushing the button; > > Nowadays in most contexts we can just type `pushing the button` as a value, and that will work fine, so this phrase is retained only to keep old code working. ## Guidelines on how to write rules about actions ^^{actions} ^^{actions: guidelines for action rules} ^^{rules: guidelines for action rules} ^^{|out of world} ^^{actions: |out of world} ^^{before (action)+rb+: guidelines for use} ^^{instead of (action)+rb+: guidelines for use} ^^{after (action)+rb+: guidelines for use} ^^{check (action)+rb+: guidelines for use} ^^{carry out (action)+rb+: guidelines for use} ^^{report (action)+rb+: guidelines for use} ^^{Actions page of Index panel+ui+} ^^{user interface: Index panel: Actions page} ^^{Index panel+ui+: Actions page} Looking at the action-processing diagram, there seem to be a bewildering number of ways to intervene. For instance, suppose it must be fatal to pick up a land mine. All six of the following rules would do the business: Before taking the land mine: end the story saying "Bang!". Instead of taking the land mine: end the story saying "Bang!". Check taking the land mine: end the story saying "Bang!". Carry out taking the land mine: end the story saying "Bang!". After taking the land mine: end the story saying "Bang!". Report taking the land mine: end the story saying "Bang!". So which should we use? Of course, we could decide that it really doesn't matter: what works, works. But it is a good idea to play along with the conventions used by Inform, if only because that will make our rules interact better with each other and with rules by other people which we may someday want to borrow. So this chapter ends by offering a few guidelines. Let us suppose that we have some effect which we want to achieve. **1. Are we just trying to correct the player's typing?** For instance, responding to the command ``STEAL GOLDEN EAGLE`` with a reply like ``To steal something, just try to TAKE IT.`` It is bad style to make a special action for this, which does nothing except to print up this text: better is to use the `Understand ... as a mistake` technique, which will come up in the chapter on [Understanding]. **2. Does the effect apply only to a particular situation, or is it a general phenomenon?** In other words, does the effect apply only to particular people, things or places, or is it a generic rule of play? In the case of the land mine, this is an easy question to answer: it is a unique situation. On the other hand, stopping the player from carrying unduly heavy weights would be a generic rule of play. Rules like the one saying that photography is only possible if one holds the camera are, by convention, also counted as generic rules of play: they are not really special rules about the camera, but apply to all possible acts of photography anywhere, so are actually generic. Sometimes we can choose our own answer to this question, and go either way. Suppose we want a certain place to be muddy-floored, affecting things that happen there. One way would be to write exceptional rules applying to that one room. But we could alternatively create a general definition of muddiness (`A room can be clean or muddy. A room is usually clean.`) and then regard the new behaviour as being a set of generic rules applying in muddy rooms. We could then, of course, create a second muddy room with much greater ease, or transplant these rules to other works and have muddy rooms in those too. **3. Particular situations: use Instead or After (or sometimes Before).** The next question is: does the effect kick in after the hoped-for action has taken place, or not? In the case of the land mine, to answer that means deciding whether we think the detonator is sensitive to the slightest touch – in which case the explosion would happen at the first touch, and should be in an `Instead` rule – or whether one must actually pick up and disturb the mine – in which case an `After` should be used. That leaves us a choice of two rulebooks if the effect takes place when the merest impulse towards the action is felt: `Before` and `Instead`. Which to use? In cases of doubt, choose `Instead`. But if the effect is intended to absolutely suppress all such impulses – for instance, in a silent examination room there must be no talking – then `Before` might be more appropriate. We could imagine that someone about to say something first has a mental impulse to speak, then opens their mouth so that it becomes visible to others that some talking is about to go on, and finally utters words. Here are three possible responses: - ``You cannot contemplate breaking this smothering silence.`` (*Before*) - ``The invigilator stares you down through her horn-rimmed glasses.`` (*Instead*) - ``Everyone turns, appalled, as the silence is broken like the surface of a swimming pool by a falling elephant.`` (*After*) **4. Generic situations: work with action rules (or sometimes Before).** (a) If the effect takes place only when an action is definitely being tried, then we should use one of the action's three rulebooks: `check`, `carry out` or `report`. Check rules should do nothing, and should say nothing either unless they block the action (in which case, they should say why). Carry out rules must not block the action – it is too late for that – and should not say anything – that hasn't happened yet. (There are a few exceptions: if the action is to look at something, then carrying it out is in a sense the same thing as reporting it. But in all cases of doubt, a carry out rule should say nothing.) Adding a carry out rule to an existing action can make it do something extra. Report rules must neither block the action nor do anything. Working with new report rules is a way to make more natural-seeming, or more informative, messages appear. For instance, an effect where we want to be able to see through a door when it is first opened (``You open the panelled door, through which is the Board Room.``) would be a case for a report rule. In all cases, it is good style to write check, carry out or report rules in such a way that they could be used in other works too, or in situations that could conceivably have happened in this one (even if in fact it never does). We may one day want to put our new rules into an extension to be used by other people or in other projects, after all. In this chapter, we have only seen the addition of new rules. We could add a new `check taking` rule, for instance, with the techniques seen so far. But what if the effect we want is not a matter of adding a rule but taking away, or restricting the applicability, of an existing one? In that case, we will need to say that the rule `does nothing` under certain circumstances (see the chapter on [Rulebooks]). The check, carry out and report rules for all of the built-in actions are named, and they appear in the Actions index. (b) If the effect takes place to divert or supplement an action, before that action actually takes place, then this should be done with a `Before` rule. This is the biggest practical use of `Before` rules: to try other actions, either instead or as well as the one just getting under way. For example, if we want an automatic mechanism to try opening a container before taking something inside it, that would be a classic case for `Before`. Indeed, that is the only way it could work – `Before` rules have a chance to get in before the touchability conditions are tested. If we wanted a special `stealing` action for the act of taking another person's possessions, we might want to divert any taking action for such items into our new `stealing` action – that too would be a `Before`. This would ensure that any `Instead` rules to do with taking do not apply. **5. Changing the behaviour of out-of-world actions.** Remember that `Instead`, `Before` and `After` do not apply: so use `check` rules to forbid certain out-of-world activities, or specify that their rules do nothing (see the chapter on [Rulebooks]). **Finally...** These are only guidelines. The system is designed to be flexible in order to give the author the widest possible range of options, and nobody should feel ashamed of making use of them. # Relations ## Sentence verbs {VERBS} {PM_PropForBadKOV} {PM_RelationWithBadProperty} {PM_RelationWithEitherOrProperty} {PM_BadRelation} {PM_EveryWrongSide} {PM_KindRelatedToValue} ^^{sentence verbs <-- verbs: sentence verbs} ^^{|is} ^^{relations: used in sentences} Descriptions of things – `open door`, `people in the Drawing Room` – have already had a whole chapter to themselves. But descriptions are only half of the story of Inform's highly flexible language for talking about places, things and circumstances, using adjectives and nouns: this chapter is the other half, and brings in verbs. Consider the following pieces of source text: The mouse is in the teapot. Every turn when the mouse is in the teapot, say "A tail hangs out of the spout." Instead of taking the mouse: say "The mouse slips from your hand and disappears into the teapot!"; now the mouse is in the teapot. What these three extracts have in common is the sentence `the mouse is in the teapot`. Such a sentence can be used in three different ways: to declare the original state of the world, to ask during play if the world currently has that state, or to change things during play so that it does. Actually, though, only definite sentences about the present can be used in all three ways. A vague instruction like now Mr Darcy can see the mouse; will fail, because there are so many ways in which Darcy might be able to see the mouse that Inform has no way to know how to arrange matters. And this by contrast is not merely difficult but impossible: now Mr Darcy has never seen the mouse; Which cannot be arranged because the past cannot be changed. Verbs also turn up inside the more complicated descriptions. For instance, - `things which are in the teapot` - `people who can see the mouse` are both descriptions, not sentences, but they contain "to be" and "to be able to see" respectively. This chapter is about the verbs which can be used in sentences and descriptions. Inform involves many other features which use verbs – the action `taking the mouse` and the phrase `end the story` both use forms of verbs (to take and to end) – but this chapter has nothing to do with them: so for the sake of clarity, we will call verbs that occur in sentences _sentence verbs_. ## What sentences are made up from ^^{sentence verbs} ^^{|is} A sentence consists of two nouns with a verb between them. Usually, the two nouns are descriptions, as in: Mr Collins is in a lighted room. Here `Mr Collins` and `a lighted room` are descriptions. But there are sentences where one or both of the nouns is a value of some other kind. For instance, in if the score is greater than 10, ... the sentence `the score is greater than 10` consists of two number values (`the score` and `10`) connected by a verb part (`is greater than`). This chapter is about getting the most out of sentences by defining new verbs to express ideas not already built in to Inform. Before we can define a new sentence verb, however, we must first look at the meanings of verbs: which Inform calls _relations_. ## What are relations? {RELATIONS} ^^{relations} ^^{sentence verbs: difference from relations} ^^{relations: difference from sentence verbs} Relations are what sentences express. They are yes/no questions about pairs of things: for example, to say that the coin is in the purse is to say that a particular relation (containment) is true about a specific pair of things (the purse, the coin). It is neither a fact about the coin nor about the purse, but about the two together. Inform comes with a number of relations built in, almost all of which have been used in previous chapters already. The following table names some of the more useful ones, giving examples of sentences to bring them about: Relation | Example --------------- | --------------- `containment` | `The coin is in the purse.` `support` | `The coin is on the table.` `incorporation` | `The coin is part of the sculpture.` `carrying` | `The coin is carried by Peter.` `wearing` | `The jacket is worn by Peter.` `possession` | `if Mr Darcy has a rapier...` `adjacency` | `The Study is east of the Hallway.` `visibility` | `if Darcy can see Elizabeth...` `touchability` | `if Darcy can touch Elizabeth...` These relation names do not trip off the tongue, but they relatively seldom need to be referred to. The same meaning can often be expressed by using several different verbs, or using the same verb in several different ways, as in the following examples: The coin is in the purse. The purse contains the coin. The coin is contained by the purse. all of which boil down to saying that the coin and purse satisfy the containment relation. Because of that, *relations are not the same as verbs*. To create a new idea, we will need first to create a new relation, and only then can we set up a verb which allows us to talk about that relation. ## To carry, to wear, to have ^^{containment+rel+ <-- containment+relcat+ <-- in+relverb+} ^^{containment+relcat+} ^^{support+rel+} ^^{support+relcat+} ^^{incorporation+rel+ <-- incorporation+relcat+} ^^{incorporation+relcat+} ^^{carrying+rel+ <-- carrying+relcat+} ^^{carrying+relcat+} ^^{wearing+rel+ <-- worn+relverb+} ^^{wearing+relcat+} ^^{possession+rel+ <-- has+relverb+} ^^{possession+relcat+} ^^{concealment+rel+ <-- concealment+relcat+} ^^{concealment+relcat+}^^^{containment+rel+ <-- containers+kind+: containment relation}^^^{support+rel+ <-- supporters+kind+: support relation}^^^{incorporation+rel+ <-- components: incorporation relation}^^^{supporters+kind+ <-- support+relcat+}^^^{containment+rel+ <-- inside+relverb+ <-- within+relverb+}^^^{containment+rel+ <-- held in+relverb+}^^^{containers+kind+ <-- containment+relcat+}^^^{components <-- incorporation+relcat+}^^^{support+rel+ <-- on+relverb+ <-- on top of+relverb+} Inform has altogether five mutually exclusive ways in which one thing can be physically joined to another one: - **containment** relation - `The coin is in the purse.` - **support** relation - `The coin is on the table.` - **incorporation** relation - `The coin is part of the sculpture.` - **carrying** relation - `The coin is carried by Peter.` - **wearing** relation - `The jacket is worn by Peter.` This is why we cannot have The coin is on the table. The coin is part of the table. simultaneously, and it is a rare exception to the general rule that having one relation does not affect having another. But there is also a sixth relation used in Inform for these meanings: the possession relation, which is the meaning of the verb "to have". At first sight this looks the same as the carrying relation, but in fact it is a convenient shorthand for `carrying or wearing`, provided for conditions rather than assertions: if Mr Darcy has a wet shirt ... will be true during play if he is either carrying or wearing the shirt. Still another relation exists which can be tested, but not declared to be true or false: the concealment relation, which is the meaning of the verb "to conceal". So we can ask: if Mr Darcy conceals a fob watch ... ## Making new relations {PM_RelationExists} {PM_FRFUnavailable} {PM_OneOrVariousWithWhen} {PM_BothOneAndMany} {PM_CantCallLeft} {PM_CantCallRight} {PM_CantCallBoth} {PM_OneToOneMiscalled} {PM_RelatedKindsUnknown} {PM_BadKOVForRelationProperty} ^^{relations: defining} ^^{defining: relations} ^^{(relation) relates...+assert+ --> relates} ^^{(various), in defining relations+sourcepart+} ^^{|called: in defining relations} We can create new relations like so: Loving relates various people to one person. Every relation has a name which ends with the word `relation`, and in this case the name is `loving relation`. While the name is often just two words long, as here, it doesn't have to be: Adept sensitivity relates one person to one vehicle. makes the `adept sensitivity relation`. (The limit is 32 words.) In such a definition, we have to say what kind of thing appears on the left and right of any relation, and also whether `one` or `various` possibilities can exist. In the example Loving relates various people to one person. what we are saying is that only people love; that they only love people; and that each person loves only one other person (at any given moment). Suppose, just in this discussion, we write "X ❤️ Y" to mean that X is related by the loving relation to Y. (This isn't Inform syntax: that comes later. It's just to explain relationships.) The `various` part comes in because, for instance, we might have: - Verenka ❤️ Stankevich - Liubov ❤️ Stankevich so that various people (Verenka and Liubov, to name but two) love one person (Stankevich). But we are forbidding anyone to love two other people at the same time: Stankevich must decide which of them to love, or pick someone else, or no-one at all. Similarly, we would not allow - Liubov ❤️ Belinsky It is sometimes convenient to give a name to the other side of a relationship, so to speak. We might imagine: Pet-ownership relates various animals to one person (called the owner). It would then make sense to talk about `the owner of Loulou`, and we could have phrases like `now Flaubert is the owner of Loulou` or `if the owner of Loulou is a woman...` and so forth. This, however, would not be allowed: Pet-ownership relates various animals (called the pet) to one person. because `the pet of Flaubert` would be ambiguous: he might have owned dozens. ## Making symmetric relations ^^{symmetric relations} ^^{relations: symmetric relations} ^^{(each other), in defining relations+sourcepart+} ^^{(another), in defining relations+sourcepart+} ^^{|called: in defining relations} The relationships described in this chapter so far are by no means always reciprocated. For instance, if a stone is on a table, then it is never true that the table is also on the stone. And the question may not even be meaningful to ask. If Peter wears a jacket, the jacket does not even have the possibility of wearing Peter. But sometimes we do want a so-called symmetric relation, one which automatically works both ways. These are simple to set up: Knowing relates people to each other. The effect is that various people know various other people, and this always goes both ways at once. If Daisy knows Sophie then, automatically, Sophie knows Daisy. This even-handedness is maintained throughout play, so that whatever changes are made it is always true that if A knows B then B knows A. And similarly for a reciprocal relation between one and `another`, where each person can be related either to nobody or to just one significant other: Marriage relates one person to another. In this case, we can again give a name to the partner under a relation: Marriage relates one person to another (called the spouse). and now, for instance, if the spouse of John is Yoko then the spouse of Yoko is automatically John, and they have no other spouses. Since many of these examples have involved people, it might be worth mentioning again that any kind can be involved, not just the `person` kind. ## Relations in groups ^^{relations: group relations} ^^{(in groups), in defining relations+sourcepart+} ^^{group relations} ^^{(each other), in defining relations+sourcepart+} ^^{RELATIONS+testcmd+} ^^{testing commands: >RELATIONS} ^^{testing phrases: show relation (relation of values to values)+phr+} Finally, there is a kind of relation which binds even more strongly. Nationality relates people to each other in groups. This is a kind of relation which divides people up: we might wish to have all the Icelandic people related to each other, all the Peruvians to each other, and so on. If there were a Pacific island called Informia with one inhabitant, then that person would be related only to himself. As time goes by, we could imagine people emigrating, and so on, so that these groupings would switch: perhaps everyone would leave Belgium and, for a while, there would be no Belgian nationals at all. The testing command ``RELATIONS`` prints out the current state of all the relations created in the source code. For instance: > RELATIONS Overlooking relates various rooms to various rooms: The Pub >=> the Garden The Garden >=> the Shrubbery The Shrubbery >=> the Sundial Plot Friendship relates people to each other: Mr Wickham <=> Sophie Charlotte <=> Sophie Marriage relates one person to another: Mr Wickham == Sophie That can produce a lot of output. To see only a single relation, or to see it at some intermediate point in a calculation, there's also a testing phrase: > phrase: {ph_showrelation} show relation (relation of values to values) > > This phrase is for testing purposes only. It shows the current state of the named relation, that is, it shows which values relate to which other ones, where it's possible to do this in any sensible way. But this is a phrase – not a typed command. ## The built-in verbs and their meanings ^^{relations: relationship to sentence verbs} ^^{sentence verbs: predefined} ^^{|is} ^^{equality+rel+ <-- |is: equality relation <-- comparisons: equality} ^^{equality+relcat+} ^^{provision+rel+ <-- |provides: provision relation} ^^{adjacency+rel+} ^^{adjacency+relcat+} ^^{rooms+kind+: adjacent} Inform uses relations to give meaning to verbs. For example, this sentence appears in the Standard Rules which are automatically included in every story: The verb to wear means the wearing relation. Because of this sentence, sentences like `Watson is wearing a brown Army greatcoat.`, conditions like `if Holmes has not worn the deerstalker hat`, and changes like `now Mrs Hudson wears the apron`, are all understood by Inform to be talking about the wearing relation. Inform stories begin with a fairly small stock of verbs, allowing more to be added by authors as needed: see [Defining new assertion verbs]. This discussion, which can safely be skimmed or skipped altogether on a first reading, covers what is built in. ### Why some built-in verbs and relations are special cases The closer we get to the core of English, the more irregular, ambiguous and expressive it becomes. The verb "to be" is right at the centre, so it is easy to see why Inform has to give it special treatment. In principle it means the `equality relation`, which is true if two values are equal. And that is just what it does mean in usages like `The time of day is 5:12 pm.`; `if the score is 10`; `now the score is 20`. But Inform also has to overload "to be" with other meanings, too. For example, `The Ballroom is dark.` is not trying to say that the Ballroom is equal to the property of darkness. The `equality relation`, too, has special abilities: it can be used more flexibly than a new relation created by an Inform author can be. Equality can be applied to any two values with compatible kinds, for example, which is a much broader range of applicability than can be declared with a sentence like `Knowing relates people to each other.` "To be" is an extreme case, but there are several other built-in verbs which are special, or which mean relations which are special, or both. These special cases fall into two sets. One set, defined in the Basic Inform rules common to all stories, provides fundamentals of the English language like "to be", "to have", and "to mean". The other set is defined in the Standard Rules for interactive fiction, and provides some basics needed for story-telling. "To wear" is built in because clothing is commonly needed in stories, not because it is somehow a difficult English verb. Inform does provide special support for the `wearing relation` in that, for example, it won't allow both `Holmes wears the deerstalker` and `The deerstalker is on the table` to be true at the same time. But the actual verb "to wear" is not special at all. ### To be Basic Inform declares 15 different meanings for "to be", though some are very rarely used. The first 14 of these are all special sentence meanings hard-wired into the language by the compiler: they apply only when the syntax is just so, and they apply only to whole sentences, not to `if` conditions or uses of `now`. The 15th is the regular meaning, equality. verb | meaning | example ------- | ------- | ------- `to be` | `built-in new-verb meaning` | `To achieve is a verb.` `to be` | `built-in new-plural meaning` | `The plural of cherub is cherubim.` `to be` | `built-in new-activity meaning` | `Printing a parser error is an activity.` `to be` | `built-in new-action meaning` | `Taking is an action applying to one thing.` `to be` | `built-in new-adjective meaning` | `In French petit is an adjective meaning...` `to be` | `built-in new-either-or meaning` | `A thing is either edible or inedible.` `to be` | `built-in accessible-to-inter meaning` | `The time advancing rule is accessible to Inter as "TIME_ADV_RULE".` `to be` | `built-in defined-by-inter meaning` | `The seed random number generator rule is defined by Inter as "SEED_RANDOM_NUMBER_GENERATOR_R".` `to be` | `built-in defined-by-table meaning` | `Some doors are defined by the Table of Portals.` `to be` | `built-in rule-listed-in meaning` | `The time passes rule is listed in the turn sequence rulebook.` `to be` | `built-in new-figure meaning` | `Figure 2 is the file "Butterfly.png".` `to be` | `built-in new-sound meaning` | `Sound of rustling leaves is the file "Rustling leaves.ogg".` `to be` | `built-in new-file meaning` | `The File of Glaciers is called "ice".` `to be` | `built-in episode meaning` | `This is episode 2 of "When in Rome".` `to be` | `equality relation` | `if N is 10` And is this the whole story for "to be"? It is not. Firstly, as noted above, the `equality relation` is not like other relations. `X is Y` will be treated as equality of two values if `X` and `Y` both refer to values of the same kind, but as asserting that `X` has some property `Y` if `X` is a value and `Y` is a property it can have (example: `The box is transparent.`) or similarly that `X` has the kind `Y` (example: `The box is a container.`). There are also two sorts of sentence used in Inform which look like usages of "to be" but which, from Inform's point of view at least, are not. 1) A grammar book would say that "to be in" is the verb "to be" used in conjunction with a preposition "in". Inform thinks of `to be in` as a different verb from `to be`, with a different relation as its meaning. Indeed, the Standard Rules contain the line: The verb to be in means the reversed containment relation. And this is why `The insufflator is in the Gladstone bag.` means that the bag contains the insufflator: this sentence is not an attempt to apply the `equality relation`. Because of a quirk of English called subject-verb inversion, we also sometimes write `In the Gladstone bag is the insufflator.` This flips the meaning back from being the `reversed containment relation` to just the regular `containment relation`, so once again it says that the bag contains the insufflator. Inverted or not, Inform thinks of the "verb" as `to be in`, not `to be`. And the same goes for other prepositional phrases. 2) "to be" serves as a form of auxiliary verb in the conjugation of other verbs. When Inform defines `to support`, that automatically enables sentences like `X is supporting Y`, or `Y is supported by X`. But again, Inform considers the verb in both sentences as `to support`, not `to be`. ### Other built-in verbs from Basic Inform As with "to be", many of these — the ones described as built-in meanings rather than as relations — apply only to assertion sentences, and only if special syntaxes are used. Some are quite obscure and very seldom seen. If a verb does not have a meaning as a relation, it's still free to be given one by authors. verb | meaning | example ---- | ------- | ------- `to mean` | `built-in verb-means meaning` (1) | `The verb to mean means the meaning relation.` `to mean` | `meaning relation` | `The verb to wear means the wearing relation.` `to imply` | `built-in verb-means meaning` (1) | synonym for `to mean` `to imply` | `meaning relation` | synonym for `to mean` `to be able to be` | `built-in can-be meaning` | `A supporter can be enterable.` `to have` (2) | `possession relation` (3) | `The box has carrying capacity 10.` `to specify` | `built-in specifies-notation meaning` | `A length times a length specifies an area.` `to relate` | `built-in new-relation meaning` (4) | `Loving relates various people to one person.` `to relate` | `universal relation` (5) | `if the box relates to the coin by containment` `to substitute for` | `built-in rule-substitutes-for meaning` | `The time passes slowly rule substitutes for the time passes rule.` `to do` | `built-in rule-does-nothing meaning` | `The time passes rule does nothing.` (6) `to translate into ... as` | `built-in translates-into-unicode meaning` | `Black king chess piece translates into Unicode as 9818.` (7) `to translate into ... as` | `built-in translates-into-i6 meaning` | `The taking inventory action translates into Inter as "Inv".` `to translate into ... as` | `built-in translates-into-language meaning` | `Thing translates into French as chose.` `to translate as` | `built-in use-translates meaning` | `Use American dialect translates as the configuration flag AMERICAN_DIALECT in BasicInformKit.` `to provide` | `provision relation` (8) | `if the noun provides carrying capacity` `to be greater than` | `numerically-greater-than relation` (9) | `if X is greater than 5` `to be less than` | `numerically-less-than relation` (9) | `if X is less than 5` `to be at least` | `numerically-greater-than-or-equal-to relation` (9) | `if X is at least 5` `to be at most` | `numerically-less-than-or-equal-to relation` (9) | `if X is at most 5` In addition, there are four so-called "operators", which are like verbs except that they just have a single form and do not conjugate: operator | meaning | example -------- | ------- | ------- `>` | `numerically-greater-than relation` (9) | `if X > 2` `<` | `numerically-less-than relation` (9) | `if X < 2` `>=` | `numerically-greater-than-or-equal-to relation` (9) | `if X >= 2` `<=` | `numerically-less-than-or-equal-to relation` (9) | `if X <= 2` Some footnotes: 1) "To mean" and its synonym "to imply" are special in that they both create a new verb, and then give it a meaning. 2) "To have" also turns up in the past tenses of other verbs: for example, in `if Holmes has worn the deerstalker`. But Inform regards that as a use of the verb `to wear`, not `to have`. 3) The `possession relation` can also be used to talk about people carrying or wearing things: see below. The meaning here is in sentences like `The box has carrying capacity 10.` which assert that something has a given property value. 4) As with "to mean", "to relate" has a special meaning which creates a new relation. 5) The `universal relation` is awesomely powerful, in that it contains all other relations. Uniquely, it relates three things, not two: thus `X relates to Y by Z` expresses that the relation `Z` applies between `X` and `Y`. 6) This can also occur with `if...`, `when...` or `unless...` caveats attached. 7) Now withdrawn from the language: throws a problem message. 8) The `provision relation` is special in that it applies to any value and any property, even when this seems absurd. For example, `if 20 provides carrying capacity` is perfectly legal. (The answer is no.) But it is intended for coping with objects, where it often happens that a variable contains some object, but where the exact kind is not known in advance. In principle the `provision relation` can be tested on any property, but because either/or properties behave adjectivally in Inform, it's difficult actually to write such tests. `if 20 provides lit` is interpreted as meaning `if 20 provides something lit`, which then throws a problem message. So in practice `provides` can only be used with value properties. 9) These size comparison relations can be applied to a wide range of number-like quantities, not just numbers, but they can only be tested, not asserted by `now`. ### Built-in verbs from the Standard Rules These verbs mostly concern the spatial world of the story: how things fit together in space, whether they are near or far away, and so on. The table below does not list regular forms like `to be concealed by`, because those exist automatically because the verb `to conceal` exists: `X is concealed by Y` means the same thing as writing `Y conceals X`. Note in particular that `X is held by Y` means that `Y` holds `X`, as defined by the `holding relation`; whereas `X is held in Y` has a subtly different meaning, the `containment relation`. verb | meaning | example ---- | ------- | ------- `to have` | `possession relation` (1) | `if Watson has the army revolver` `to be in` | `reversed containment relation` (2) | `The coin is in the box.` `to be inside` | `reversed containment relation` (2) | `The coin is inside the box.` `to be within` | `reversed containment relation` (2) | `The coin is within the box.` `to be held in` | `reversed containment relation` (2) | `The coin is held in the box.` `to be held inside` | `reversed containment relation` (2) | `The coin is held inside the box.` `to contain` | `containment relation` (2) | `The box contains the coin.` `to be contained in` | `reversed containment relation` (2) | `The coin is contained in the box.` `to be on top of` | `reversed support relation` (3) | `The box is on top of the table.` `to be on` | `reversed support relation` (3) | `The box is on the table.` `to support` | `support relation` (3) | `The table supports the box.` `to be supported on` | `reversed support relation` (3) | `The box is supported on the table.` `to incorporate` | `incorporation relation` (4) | `The coin incorporates the head.` `to be part of` | `reversed incorporation relation` (4) | `The head is part of the coin.` `to be a part of` | `reversed incorporation relation` (4) | `The head is a part of the coin.` `to be parts of` | `reversed incorporation relation` (4) | `The head and the inscription are parts of the coin.` `to carry` | `carrying relation` (5) | `Henry carries the food.` `to wear` | `wearing relation` (6) | `Henry wears a hat.` `to hold` | `holding relation` (7) | `Henry holds the food.` `to enclose` | `enclosure relation` (8) | `The box encloses the coin.` `to be able to see` | `visibility relation` (9) | `if Amanda can see the soldier` `to be able to hear` | `audibility relation` (10) | `if Amanda can hear Flavia` `to be able to touch` | `touchability relation` (11) | `if Amanda can touch the coin` `to conceal` | `concealment relation` (12) | `if Flavia conceals the knife` `to be adjacent to` | `reversed adjacency relation` (13) | `if the location is adjancent to the Atrium` `to be regionally in` | `reversed regional-containment relation` (14) | `if the location is regionally in Gaul` `to be above` | `mapping up relation` (15) | `The Terrace is above the Atrium.` `to be mapped above` | `mapping up relation` (15) | `The Triclinium is mapped above the Atrium.` `to be below` | `mapping down relation` (15) | `The Hypocaust is below the Atrium.` `to be mapped below` | `mapping down relation` (15) | `The Well is mapped below the Atrium.` `to be through` | `leading-through relation` (16) | `if the Atrium is through the green door` `to unlock` | `lock-fitting relation` (17) | `The brass key unlocks the green door.` `to be about` | `topicality relation` (18) | `if B is about philosophy` `to be performable to` | `performability relation` (19) | `if B is performable to the actor` `to begin when` | `built-in scene-begins-when meaning` | `Train Stop begins when Train Wait ends.` `to end when` | `built-in scene-ends-when meaning` | `Train Stop ends when the turn count is 10.` `to end ... when` | `built-in scene-ends-when meaning` | `Train Stop ends unhappily when the turn count is 10.` So then we have to say what these relations apply to, and what they mean. We will call the two related objects `X` and `Y`. Some basic ground rules first: * Objects are sometimes "spatial" — belonging to the kinds `thing`, `room`, `region`, or `direction` — or not — belonging to the kind `abstract object`. * Spatial objects can sometimes be contained in other spatial objects, can be supported by them, or carried by them, or worn by them, or can be part of them, but any given spatial object cannot do two of these at the same time, and need not do any. * Abstract objects can be "in" other abstract objects. What that might mean is up to the author making use of them. 1) The `possession relation` can also be used to talk about properties: see the Basic Inform table above. If `X` or `Y` are both objects, then the relation is true if either the `carrying relation` or the `wearing relation` holds; note that in either case, `X` has to be a person and `Y` has to be a thing. Asserting possession with `now` is equivalent to asserting the `carrying relation`. Thus, `now Watson has the revolver` causes him to be carrying it. If Inform reads an assertion sentence like `Holmes has the deerstalker.`, it has to choose whether this means the deerstalker is carried or worn by Holmes. In general Inform always tries to make the simplest choice of meaning, and here it reads `has` as `carries`. 2) The `containment relation` is converted automatically to `regional-containment relation` (see below) if `X` is a region. Otherwise `X` must be either a room or a container, and `Y` must be a thing. `X` must immediately contain `Y`: if a coin is in a box which is in a crate, then the crate contains the box but does not contain the coin. Beware that a backdrop, or a two-sided door, is only contained in a single room at a time, even though it is conceptually present in other places. Behind the scenes, these objects are moved as needed to preserve the illusion that they are in two places at once, but they are not. However, see the note on enclosure below. 3) The `support relation` holds if `X` is a supporter, `Y` is a thing, and `Y` is immediately on top of `X`. 4) The `incorporation relation` holds if `X` and `Y` are things, and `X` is (immediately) a part of `Y`. 5) The `carrying relation` holds if `X` is a person and `Y` is a thing, and `X` is immediately holding `Y`. `Y` cannot at the same time be worn by `X`, so `now Holmes carries the deerstalker` will make it cease to be worn if Holmes was already wearing it. `now X does not carry Y` is permitted in all cases. If `X carries Y` then `Y` is moved to the `holder of X`; if not, nothing happens. Note that if `X` is currently out of play (so that `holder of X` is `nothing`) then `Y` is made separately out of play. 6) The `wearing relation` holds if `X` is a person and `Y` is a thing, and `X` is dressed in `Y`. `now Holmes does not wear the deerstalker` would cause him to be carrying it instead of wearing it. 7) The `holding relation` holds for spatial objects if any of: * the `containment relation` holds, i.e., `X` contains `Y`; * the `support relation` holds, i.e., `X` supports `Y`; * the `carrying relation` holds, i.e., `X` carries `Y`; * the `wearing relation` holds, i.e., `X` wears `Y`; * the `incorporation relation` holds, i.e., `Y` is part of `X`; * `Y` is a region which is immediately inside another region `X`. Note, however, that if a room is in a region, then it is _not_ held by that region. Thus containment, support, carrying, wearing and reverse incorporation all imply holding, but regional containment does not. `now X holds Y` is permitted only if `Y` is a thing, and `X` is a room, container, supporter, or person; or if both are regions. If Inform reads an assertion sentence like `Maureen holds the rabbit.`, it has to choose which of the above six relationships is intended. Having nothing to go on, it chooses the `carrying relation`, so that this is equivalent to `Maureen carries the rabbit`. `Maureen` is then deduced to be a `person`, and the `rabbit` is deduced to be a `thing`. The `holding relation` holds for abstract objects if `Y` is in `X` and `now X holds Y` is permitted in all cases. `now X does not hold Y` is never permitted. At any given time, an object can be held by only one other object, and Inform provides a convenient phrase `holder of Y` to mean either `nothing` (if `Y` is not held at the moment) or this unique other object. 8) The `enclosure relation` can only be tested, not asserted or changed with `now`. It holds if there is a sequence `X1`, `X2`, ..., `Xn`, which begins with `X` and finishes with `Y`, and such that for each pair of adjacent terms `A` and `B` in this sequence, _either_ * `A` and `B` are both abstract objects and `B` is in `A`, _or_ * `A` and `B` are both spatial objects and `A` is holding `B` (see above), _or_ * `B` is a two-sided door and `A` is one of the two rooms it joins, _or_ * `B` is a backdrop and `A` is one of the rooms it is currently present in. Note that holding implies enclosure, and therefore containment, support, carrying, wearing and reverse incorporation also imply enclosure. And since possession means carrying or wearing, possession implies enclosure, too. Again, though, regional containment does not. Enclosure is the only one of the spatial relations to be "transitive": that is, if `A` encloses `B`, and `B` encloses `C`, then `A` encloses `C`. All eight of the spatial relations so far are "anti-symmetric": for example, if `A` contains `B` then it cannot simultaneously be true that `B` contains `A`. In particular, in the case when `A` and `B` are the same, no object can possess, contain, support, incorporate, carry, wear, hold, or enclose itself. Inform goes to some trouble to prevent any object from ever enclosing itself, and authors should cooperate with that. It is possible to write low-level code which would violate this principle, but it is really _not_ a good idea. 9) The `visibility relation` holds if _all_ of the following are true: * `X` and `Y` are both things, _and_ * light is available in the current situation of `X`, _and_ * `Y` is in scope from the point of view of `X`. Note that rooms, regions and directions are not things, so `if the player can see north` or `if the player can see the Great Hall of Mirrors` are always false, which may be unexpected to authors. Visibility is used mainly to determine whether certain actions are possible, and actions do not act on rooms. 10) The `audibility relation` holds if _both_ of the following are true: * `X` and `Y` are both things, _and_ * `Y` is in scope from the point of view of `X`. Thus audibility implies visibility, but not vice versa. In the dark, something can be be audible but not visible. Audibility is used mainly to manage when dialogue beats are performed. 11) The `touchability relation` holds if _all_ of the following are true: * `X` and `Y` are both things, _and_ * the accessibility rulebook allows `Y` to be touched by `X`, _and_ * `Y` is in scope from the point of view of `X`. When reckoning touchability, two-sided doors are considered to be in the room which is their front side, and backdrops in the first room they are said by the source to be in. 12) The `concealment relation` holds if if _all_ of the following are true: * `X` and `Y` are both things, _and_ * `X` encloses `Y`, _and_ * the `deciding the concealed possessions activity` says that `Y` is concealed. Although this is most often used when `X` is a person, it works fine for containers and supporters too (though not for rooms, which are not things). Note too that `X` may be unaware of the concealed item, in the sense of being unable to touch or see it. 13) The `adjacency relation` holds if between two rooms if there is a direct map connection between them; a connection through a door does not count. Note that regions are never adjacent to anything, not being rooms. 14) The `regional-containment relation` provides a meaning for `if X is regionally in Y`, but this is not a verb used very much. This relation more often arises because Inform silently reads `if X is in Y` as `if X is regionally in Y`, whenever `Y` is a region. The relation is then true if _either_ * `X` is a room found in the region `Y`, _or_ * `X` is a region which is a sub-region of `Y`. 15) The `mapping up relation` and `mapping down relation` are nothing very special. Every direction automatically creates a relation like this: the existence of `north` means that there is a `mapping north relation`, for example. This then supplies the meaning of `The Ballroom is north of the Lobby.` Because we also want to make the words `above` and `below` refer to `up` and `down`, a very small amount of extra compiler support is given to these two relations. 16) The `leading-through relation` is not intended for authors to make use of, but is a device used internally by the Standard Rules to make it possible to ask what the other side of a two-sided door is. 17) The `lock-fitting relation` holds if a given thing is the key to unlock a given door or container. 18) The `topicality relation` holds if a given dialogue beat is about a given topic (which can be an abstract object, or can be something like a thing or person). 19) The `performability relation` holds if a given dialogue beat can currently be performed to a given person. ### Imperative verbs For the sake of completeness, Inform also has chapter (and other) headings, `Include ...` instructions which add extensions, and a handful of sentences which are written as imperatives. Imperatives are command-like sentences where the verb comes first. They direct the compiler to do something, rather than tell the compiler that something is true. None of these forms can be used in `if ...` or `now ...` conditions, or negated, and they do not prevent the same verbs (e.g. "to omit") from being given regular meanings too. imperative verb | meaning | example --------------- | ------- | ------- `to use` | `built-in use meaning` | `Use serial comma.` `to include ... in` | `built-in include-in meaning` | `Include predicate calculus in the debugging log.` `to omit ... from` | `built-in omit-from meaning` | `Omit predicate calculus from the debugging log.` `to test ... with` | `built-in test-with meaning` | `Test me with "look / east".` `to understand ... as` | `built-in understand-as meaning` | `Understand "herring" as the red fish.` `to release along with` | `built-in release-along-with meaning` | `Release along with a website.` `to index map with` | `built-in index-map-with meaning` | `Index map with Chamber mapped north of Cave.` ## Defining new assertion verbs {PM_VerbRelationVague} {PM_VerbUnknownMeaning} {PM_VerbRelationUnknown} {PM_PresentPluralTwice} {PM_VerbMalformed} {PM_DuplicateVerbs1} {PM_PrepositionConjugated} {PM_PrepositionLong} ^^{relations: defining sentence verbs for relations} ^^{defining: sentence verbs for relations} ^^{the verb (V) means (relation)+assert+ --> verb means} ^^{(means), defining sentence verbs+sourcepart+: the verb (V) means (relation)+assert+} ^^{sentence verbs: defining for relations} ^^{English: forms for sentence verbs} ^^{English: irregular verbs} Creating a new verb is easy: To admire is a verb. But this is of limited use because it doesn't give `to admire` a meaning. Better is to write something like this: The verb to sport means the wearing relation. That creates the verb `to sport`, if it doesn't exist already, and gives it a meaning, all in one sentence. Inform can now use sentences like `Mr Wickham sports a Tory rosette.`, whereas it remains helpless to act on `Mr Darcy admires Miss Elizabeth.`, because it doesn't know what `admires` means. Occasionally it's convenient to have the relation the other way around. For instance: The verb to grace means the reversed wearing relation. Reversed in this sense means that the things related – the subject and object of the verb – are the other way round. So these two sentences have identical meanings: Mr Wickham sports a Tory rosette. A Tory rosette graces Mr Wickham. Inform uses the regular rules of English grammar to work out the many forms it can take in sentences (though see the notes below on multi-word verbs). This is how it knew that `sports` was a usage of `sport`, even though those are different spellings. It can read this verb in singular and plural, and in four different tenses. It also recognises `to be sporting` and `to be sported by`, as in these examples: if Wickham was sporting the rosette, ... if the rosette had been sported by Wickham, ... Inform's system of "adaptive text" allows a still wider range of linguistic tricks with verbs, which is why people sometimes create verbs without giving them meanings, just to be able to print them back in interesting ways (though, again, see the notes below on multi-word verbs). See [More on adapting verbs] for more. 1) Only a single-word verb like `to sport` can be used for adaptive text, in texts like `"[The noun] [sport] the rosette."`. If we create the verb `to run amok in`, then `"[The noun] [run amok in] the Spice Bazaar."` will not be allowed. The trick would be to create `To run is a verb.`, and then use `"[The noun] [run] amok in the Spice Bazaar."` 2) Multiple-word verbs do not pick up the two `to be ...` forms mentioned above. So whereas `to sport` allowed `to be sporting` and `to be sported by`, `to run amok in` does not allow `to be running amok in` and `to be run amok in by`. Inform takes the view that multiple-word "verbs" may be grammatically complicated already (often having a preposition — in this case, `in`) and that it runs some risk of producing nonsense. Of course, if we do want them, they can still be created manually: The verb to run amok in means the territory relation. The verb to be running amok in means the territory relation. The verb to be run amok in by means the reversed territory relation. 3) But with that said, multiple-word verbs are still often useful: The verb to cover up with means the wearing relation. Peter is covering up with a tent-like raincoat. Here there are three words in the verb: the limit is 29. As this example suggests, conjugation is performed on the first word, which is assumed to be the actual verb. So it is not a good idea to write: The verb to air dry means the air-drying relation. because this will generate `airs dry`, not `air dries`. Better to use a hyphen and squash this into being a single-word verb after all: The verb to air-dry means the air-drying relation. 4) In general, Inform does not like to have verbs which look like symbols. Still, these work (though the emoji one requires the Glulx setting): The verb to >---> means the wearing relation. The verb to ❤️ means the loving relation. Bingley ❤️ Jane. Be warned that Inform will stubbornly try to treat this symbol as if it were a regular English verb, though, so it will also allow `Jane is ❤️ed by Bingley`, for example, turning `❤️` into `❤️ed` in the same way that it would turn `cover` into `covered`. 5) Inform has a fairly comprehensive knowledge of English verb conjugations, so it is rare to need to spell things out, but we can: `The verb to sport (she sports, they sport, he sported, it is sported) implies the wearing relation.` This is very much a last resort. ## Defining new prepositions ^^{prepositions, for sentence verbs} ^^{relations: defining prepositions for relations} ^^{defining: prepositions for relations} ^^{the verb to be (P) means (relation)+assert+ --> verb to be} ^^{(means), defining sentence verbs+sourcepart+: the verb to be (P) means (relation)+assert+} ^^{sentence verbs: defining for relations with prepositions} ^^{English: forms of (to be)+sourcepart+} The term preposition is used here, a little loosely, to mean anything which we add to the verb *to be* in order to talk about some relation or other. We have seen many examples already, such as: To be in - The ball is in the box. To be part of - The lever is part of the slot machine. These are defined just the way verbs are. Compare the following: Suspicion relates various people to one person. The verb to suspect means the suspicion relation. The verb to be suspicious of means the suspicion relation. The result of this is that Hercule Poirot suspects Colonel Hotchkiss. Hercule Poirot is suspicious of Colonel Hotchkiss. are exactly equivalent, and so are these two descriptions: somebody who suspects Colonel Hotchkiss somebody suspicious of Colonel Hotchkiss While most prepositions are short (`in`, `part of`, `suspicious of`), they're free to be longer if need be (`inordinately far away from`): the limit is 30 words, which should be ample. We can also define verbs as auxiliaries, like so: The verb to be able to approach means the approachability relation. Now we can ask if Poirot `can approach` Hotchkiss, and so on. ## Verbs which mean properties ^^{properties: defining sentence verbs for properties} ^^{defining: sentence verbs for properties} ^^{the verb (V) means (property)+assert+} ^^{(means), defining sentence verbs+sourcepart+: the verb (V) means (property)+assert+} ^^{sentence verbs: defining for properties} So far `The verb ... means ...` has always had a relation as its meaning. But here is an alternative: A person has a number called age. The verb to be aged means the age property. And then, for example: Alice and Bethany are people. Alice is aged 43. Bethany is aged 16. So is this a completely new sort of meaning for a verb? In fact not: under the surface, it's another kind of relation in disguise. `Alice is aged 43` says that a relation we might call "age property being equal to" holds between `Alice` and the number `43`. This is a nice way to make descriptions and conditions more expressive. We could write, say, `if three people are aged 20`. Developing this example further, and using an adjective as well: Definition: A person is young if their age is 18 or less. Instead of examining a young person (called the kid): say "Oh, round about [age of the kid in words]." Instead of examining somebody aged 16: say "Supposedly sweet." The magic wand is here. After waving the magic wand in the presence of a young person (called the kid): now the kid is aged 32; say "Shazam! [The kid] is now a realtor from Des Moines." ## Indirect relations ^^{relations: indirect} ^^{relations: paths through} ^^{relations: distance through} ^^{pathfinding: arbitrary relations} ^^{route-finding, fast/slow} ^^{fast route-finding+useopt+: for particular relations} ^^{slow route-finding+useopt+: for particular relations} ^^{distance: measuring with (number of steps)+sourcepart+} ^^{counting: steps in an indirect relation} We have already seen, in the chapter on [Descriptions] which is a forerunner of this one, that Inform provides not only `adjacent` as a way of seeing if one room is directly connected to another, but also `the best route from A to B`, which allows us to see if any sequence of moves connects them. Something similar – in fact, simpler – is allowed for any relation between objects. Suppose we would like to go sledging: we can go downhill, but not up. Some quite distant places may be reachable, while others close by may not be, even if lower than us, because they would involve climbing again at some point. The following would implement this: {*}Overlooking relates various rooms to various rooms. The verb to overlook means the overlooking relation. The Garden overlooks the Shrubbery. The Folly overlooks the Garden. The Shrubbery overlooks the Sundial Plot. The Old Ice House overlooks the Garden. After looking: say "This wintry vantage point overlooks [the list of rooms overlooked by the location]."; let the way be the next step via the overlooking relation from the location to the Sundial Plot; if the way is a room, say "To sledge downhill to the Sundial, aim for [the way]."; otherwise say "It is not possible to sledge downhill to the Sundial." Here we're making use of: > phrase: {ph_nextstep} next step via (relation of values to values) from (object) to (object) ... object > > This phrase tries to find a shortest route between the two given endpoints, using the given relation of objects to determine single steps. Example: > > next step via the overlooking relation from the Folly to the Chinese Lake > > The result is the special object value `nothing` if the two endpoints are the same or if no route exists. > phrase: {ph_numbersteps} number of steps via (relation of values to values) from (object) to (object) ... number > > This phrase tries to find the length of a shortest route between the two given endpoints, using the given relation of objects to determine single steps. Example: > > number of steps via the overlooking relation from the Folly to the Chinese Lake > > The result is 0 if the two endpoints are the same, or -1 if no route exists. Another example would be the "six degrees of separation" game, which can be tried out in many walks of life. Suppose we have: {*}An astronaut is a kind of person. Joint-crewing relates astronauts to each other. To connect (First - astronaut) with (Second - astronaut): say "[First]"; let crew member be First; while crew member is not Second: let the next crew member be the next step via the joint-crewing relation from the crew member to Second; if crew member is not an astronaut: say " cannot be connected to [Second]."; stop; say "[line break] "; if the crew member is not First, say "who "; now the crew member is the next crew member; say "flew with [crew member]"; say "."; So this now needs some data about the pioneers of astronautics, with a long table like the following (but with many more named astros, and many more missions): {**}Boris Volynov, Alexei Yeliseyev, Yevgeni Khrunov, Thomas Stafford, John Young, Eugene Cernan, Neil Armstrong, Buzz Aldrin, and Michael Collins are astronauts. Table of Crew Rosters Mission Crew "Soyuz 5" { Boris Volynov, Alexei Yeliseyev, Yevgeni Khrunov } "Apollo 10" { Thomas Stafford, John Young, Eugene Cernan } "Apollo 11" { Neil Armstrong, Buzz Aldrin, Michael Collins } We then need to use this data to populate the relation: {**}The verb to fly with means the joint-crewing relation. When play begins: repeat through the Table of Crew Rosters: repeat with First running through the crew entry: repeat with Second running through the crew entry: if First is not Second: now First flies with Second. And with all this done, we can find some routes. `number of steps via the joint-crewing relation from Armstrong to Leonov` evaluates to 4. `next step via the joint-crewing relation from Armstrong to Leonov` evaluates to Michael Collins. And `connect Armstrong with Leonov` produces the output: ``` transcript Neil Armstrong flew with Michael Collins who flew with John Young who flew with Thomas Stafford who flew with Alexei Leonov. ``` The longest path between any two pre-1990 astronauts who do connect is: ``` transcript Vitaly Zholobov flew with Boris Volynov who flew with Alexei Yeliseyev who flew with Nikolai Rukavishnikov who flew with Vladimir Lyakhov who flew with Valery Polyakov who flew with Ulf Merbold who flew with John Young who flew with Michael Collins who flew with Neil Armstrong who flew with David Scott who flew with James McDivitt who flew with Edward White. ``` As with route-finding through the map, finding `the next step via` a relation can be slow. Once again there is a choice of algorithms: `fast` and `slow`, where `fast` needs much more memory. To make route-finding for a given relation `fast`, we have to declare it that way: Joint-crewing relates various astronauts to various astronauts with fast route-finding. Otherwise, the `slow` method will be used. This `with fast route-finding` note can only be added to various-to-various relations. (Although route-finding through various-to-one and one-to-various relations is fully supported, it exploits the relative simplicity of these problems to use a more efficient algorithm than either `fast` or `slow`.) ### See Also - [Adjacent rooms and routes through the map] for route-finding through the map rather than a relation. ## Relations which express conditions {PM_Unassertable2} {PM_BadRelationCondition} ^^{defining: relations expressing conditions} ^^{conditions: expressed as relations} ^^{relations: expressing conditions} ^^{|called: in defining relations} ^^{(relation) relates...+assert+ --> relates} One last way to create a new relation and, in many ways, the easiest of all. If we write: Contact relates a thing (called X) to a thing (called Y) when X is part of Y or Y is part of X. The verb to be joined to means the contact relation. then we would be able to talk about a handle being joined to a door, and a door being joined to a handle, and so on. We are not allowed to declare: The hook is joined to the line. because the question of whether they are joined is not for us to decide: that will be for the condition to determine, whenever we test it. Similarly, we cannot meaningfully write now the hook is joined to the line; (and Inform will not let us) because this relation is not something we can force either way: we can make it come true by other means, maybe, but we cannot simply make it true by saying so. Lastly, this kind of relation is restricted in that we are not allowed to find paths or calculate numbers of steps through it. So this way to define relations is, on the face of it, just a sort of verbal trick to write conditions in a more attractive way. The more flexible, changeable relations in previous sections have much greater expressive power. All the same, it is nice to be able to write – Nearness relates a room (called A) to a room (called B) when the number of moves from B to A is less than 3. The verb to be near means the nearness relation. and then to be able to write rules like: Instead of listening when the location is near the Sundial: say "You hear a splashing of water." As with other relations, there's no reason why we have to use objects. For example: Material is a kind of value. The materials are wood and metal. A thing has a material. Materiality relates a thing (called X) to a material (called Y) when Y is the material of X. The verb to be made of means the materiality relation. which enables us to write: if the cube is made of wood, say "The carpenter looks at [the list of things which are made of wood]."; And here is a mathematical one: Divisibility relates a number (called N) to a number (called M) when the remainder after dividing M by N is 0. The verb to divide means the divisibility relation. The verb to be a factor of means the divisibility relation. We now find that `2 divides 12`, `5 is not a factor of 12` and `12 is divisible by 3` are all true. Again, we are only really gaining a nice form of words, but improving the clarity of the source text is never a bad thing. ## Relations involving values ^^{relations: defining} ^^{defining: relations} ^^{(relation) relates...+assert+ --> relates} ^^{relations: involving values} ^^{values: in relations} ^^{lists} ^^{(relates), for finding related values+sourcepart+}^^^{+to+(name of kind) that/which/who relates to (value) by (relation of values to values) --> that/which/who relates to}^^^{+to+(name of kind) that/which/whom (value) relates to by (relation of values to values) --> that/which/whom relates to by}^^^{+to+(name of kind) to which/whom (value) relates by (relation of values to values) --> to which/whom relates by} Although most of the examples in this chapter have involved objects, relations can connect almost any values together. We can create relations in groups, one to various relations, various to one relations, one to one relations, and various to various relations for any combination of kinds. For example: Partnership relates various texts to various texts. The verb to belong with means the partnership relation. "cheese" belongs with "crackers". "clam" belongs with "chowder". How might we make use of this? Clearly it would be impractical to keep trying: if "caviar" belongs with "aardvarks", ... if "caviar" belongs with "abacuses", ... ... to find out what `"caviar"` belongs with. It's still harder to find out if it belongs with anything at all – in theory we would have to try every possibility, which of course is impossible. Instead we have these phrases: > phrase: {ph_ifleft} if (value) relates to (name of kind) by (relation of values to values): > > This condition is true if the value V is such that V relates to something by the given relation. Example: suppose partnership relates various texts to various texts. Then we can test > > if "chalk" relates to a text by the partnership relation, ... > phrase: {ph_ifright} if (name of kind) relates to (value) by (relation of values to values): > > This condition is true if the value V is such that something relates to V by the given relation. Example: suppose partnership relates various texts to various texts. Then we can test > > if a text relates to "cheese" by the partnership relation, ... If a partner does exist, then we can find it with: > phrase: {ph_rightlookup} (name of kind) to which/whom (value) relates by (relation of values to values) ... value & (name of kind) that/which/whom (value) relates to by (relation of values to values) ... value > > This phrase produces an Y such that the given value V relates to Y by the given relation. Example: suppose partnership relates various texts to various texts. Then we can obtain > > the text to which "chalk" relates by the partnership relation > > which might be, say, `"cheese"`. It's a run-time problem to use this if no such Y exists. > phrase: {ph_leftlookup} (name of kind) that/which/who relates to (value) by (relation of values to values) ... value > > This phrase produces an X such that X relates to the given value V by the given relation. Example: suppose partnership relates various texts to various texts. Then we can obtain > > the text which relates to "cheese" by the partnership relation > > which might be, say, `"chalk"`. It's a run-time problem to use this if no such X exists. Of course, there might be many answers to this question, so perhaps these are neater: > phrase: {ph_leftlookuplist} list of (name of kind) that/which/who relate to (value) by (relation of values to values) ... list of values > > This phrase produces a list of all the X such that X relates to the given value V by the given relation. Example: suppose partnership relates various texts to various texts. Then we can obtain > > list of texts which relate to "cheese" by the partnership relation > > which might be, say, `{ "chalk", "grapes", "macaroni" }`. The answer might be the empty set, but that's not a problem. > phrase: {ph_rightlookuplist} list of (name of kind) to which/whom (value) relates by (relation of values to values) ... value & list of (name of kind) that/which/whom (value) relates to by (relation of values to values) ... list of values > > This phrase produces a list of all Y such that the given value V relates to Y by the given relation. Example: suppose partnership relates various texts to various texts. Then we can obtain > > list of texts to which "chalk" relates by the partnership relation > > which might be, say, `{ "cheese", "blackboard", "cliffs" }`. The answer might be the empty set, but that's not a problem. Finally, it's sometimes useful to get at the list of all values which can appear on the left or right hand side of a relation. We need tongue-twister like wording to do it, but: > phrase: {ph_leftdomain} list of (name of kind) that/which/whom (relation of values to values) relates ... list of values > > This phrase produces a list of all X which relate to anything under the given relation. Example: suppose partnership relates various texts to various texts. Then we can obtain > > list of texts which the partnership relation relates > phrase: {ph_rightdomain} list of (name of kind) to which/whom (relation of values to values) relates ... value & list of (name of kind) that/which/whom (relation of values to values) relates to ... list of values > > This phrase produces a list of all Y which anything relates to under the given relation. Example: suppose partnership relates various texts to various texts. Then we can obtain > > list of texts which the partnership relation relates to For efficiency reasons, there are no guarantees about what order these lists have – but they can of course always be sorted when found. ## Relations as values in their own right ^^{kinds: of relation} ^^{relations: kinds of relation} ^^{relations: used as values} ^^{values: relations as values} ^^{type-checking: of relation types} ^^{(relates), for arbitrary relation conditions+sourcepart+} ^^{empty / non-empty+adj+: for relations} ^^{non-empty / empty+adj+: for relations} ^^{relations: empty / non-empty+adj+} ^^{symmetric (relation)+adj+} ^^{equivalence (relation)+adj+} ^^{one-to-one (relation)+adj+} ^^{one-to-various (relation)+adj+} ^^{various-to-one (relation)+adj+} ^^{various-to-various (relation)+adj+} As we've seen, most relations have names – `containment relation`, for instance. These are themselves values in Inform, though those values are not all of the same kind, because there is no single `relation` kind. Consider these two examples: Parity relates a number (called N) to a number (called M) when N minus M is even. Joint magnitude relates a number (called N) to a number (called M) when N plus M is greater than 7. Here `parity relation` and `joint magnitude relation` are both values of the same kind: `relation of numbers to numbers`. In general, every relation is a value of kind `relation of K to L`, for the appropriate kinds K and L. So the parity relation doesn't have the same kind as the containment relation, for example. Because it often happens that K and L are the same, we can just say `relation of K` in this case, so we could equally say that the kind of the parity relation is `relation of numbers`. This is useful to know when writing phrases like so: To chart (R - a relation of numbers): repeat with N running from 1 to 5: repeat with M running from 1 to 5: if R relates N to M, say "[N] <=> [M] "; say "[line break]"; and now `chart parity relation` will work nicely, but `chart visibility relation` will be rejected (as it should be, because it relates things, not numbers). That last example used a powerful trick: if `R` is any relation, we can write if R relates X to Y, ... now R relates X to Y; now R does not relate X to Y; to test, set and unset a relation R between two values. (Inform checks that the values X and Y have the right kind and produces a problem message if not.) As we have seen, a relation can be supplied as a parameter of a phrase. It can also be the value of a variable or, as in this example, a property: {*}"The Trojan Wars Lounge & Electronics Club, Inc." The Cocktail Bar is a room. Troilus and Cressida are here. A detector is a kind of device. A detector has a relation of people called the relation detected. Loving relates various people to various people. The verb to love means the loving relation. Troilus loves Cressida. The Love-o-meter is a detector in the Bar. The relation detected is the loving relation. Instead of examining a detector (called the gadget): let the arrow count be 0; let R be the relation detected of the gadget; repeat with X running through people in the location: repeat with Y running through people in the location: if R relates X to Y: say "A mauve arrow momentarily forms in mid-air from [X] to [Y]."; increment the arrow count; if the arrow count is 0, say "Disappointingly little happens." Test me with "x love-o-meter". Several useful adjectives can be applied to relations. Most of these test how the relation was set up: - `one-to-one` if it relates one K to one L - `one-to-various` if it relates one K to various L - `various-to-one` if it relates various K to one L - `various-to-various` if it relates various K to various L - `equivalence` if a relation `in groups` - `symmetric` if a relation `in groups` or `to each other`, so that X relates to Y if and only if Y relates to X So for example it's possible to ask `if R is a symmetric one-to-one relation of texts`. A surprisingly useful adjective for relations is `empty`, which means that in the current state of the relation, nothing relates to anything else. With some relations, it's possible to clear them out by writing: now R is empty; The exceptions where `empty` can't be used are those which can't be changed at all, like the parity relation above, and a few built-in cases such as the support, containment and incorporation relations, where emptying would dissolve the model world in a disastrous way. With temporary relations (see the next section), it's even possible to change their valencies (one-to-one vs. one-to-various, etc.) using `now`, but only when they are `empty`. ## Temporary relations ^^{relations: temporary relations} ^^{(relates), for arbitrary relation conditions+sourcepart+} So far in this chapter, we've only seen relations which exist permanently during play. The relationships might change – sometimes Red Riding Hood would be in the Woodcutter's Cottage, sometimes not – but the relations themselves were eternal. In fact, though, we can also create relations to be dynamic data structures, like lists: > phrase: {ph_letrelation} let (a name not so far used) be (description of relations of values to values) > > This phrase creates a new temporary variable, and sets its value to the identity of a newly created and equally temporary relation. These last only for the present block of phrases, which certainly means that they exist only in the current rule. Example: > > let the password dictionary be a relation of texts; > > This makes a purely temporary various-to-various relation between texts, which lasts as long as the temporary value `password dictionary` lasts. By default, relations are various-to-various, but we could instead write, say: > > let the nicknames catalogue be a various-to-one relation of texts; Such a relation exists only in the current phrase, and is destroyed when the phrase finishes, like any other `let`. Of course there's no verb whose meaning is this relation, but that's no obstacle, because we can manipulate it using `relates`: now the nicknames catalogue relates "Trudy" to "Snake-eyes"; (At present such a relation cannot be used outside its own phrase.) ## What are relations for? ^^{relations: guidelines for use} It is easy to say what verbs are for: they are to express relations. But what are relations for? The ones we've seen so far are mostly about how things are arranged in space: things being inside or on top of each other, or one room being mapped north of another. In some ways these are the only relationships that inanimate objects ever have. A stone can be on top of a table, and if so then that expresses their entire association. This is because the stone, and the table, have no opinions, emotions, knowledge or memory. If the stone is taken away and then put back, nothing has changed. People, on the other hand, tend to remember having met each other before; they like being in some places, but not others; their behaviour depends on who, or what, is nearby. Being conscious, they have internal states, unlike the stone. Relations are a simple but powerful way to express and talk about such connections, and although they have numerous uses in physical contexts too, they are at their most powerful when helping to make the characters of interactive fiction come alive. # Adaptive Text and Responses ## Tense and narrative viewpoint ^^{tense: of standard responses} ^^{English: tense: of standard responses} ^^{narrative viewpoint, of standard responses} ^^{English: narrative viewpoint, of standard responses} ^^{story viewpoint (- narrative viewpoint)+glob+} ^^{story tense (- tense)+glob+} ^^{|first person singular / plural} ^^{|second person singular / plural} ^^{|third person singular / plural} ^^{|past / present / future tense} ^^{|present / past / future tense} ^^{|future / present / past tense} A conspicuous difference between interactive fiction and a traditional novel is the point of view from which it's told. Inform usually produces text like: You can see a grey cat in the basket. where a novel would usually write: He saw a grey cat in the basket. Standard interactive fiction (IF) is second person singular, and present tense; most novels are told in the third person singular, and past tense. But these are just conventions – a few novels, for example, use the so-called present historic ("Napoleon looks up at the sky and sighs. Must Ney always be so doubting?"), and plenty are told in the first person singular ("I always get the shakes before a drop."). Inform allows some of this flexibility, too. The two values: story viewpoint story tense control the style of the text produced. The story viewpoint has to be one of the values: first person singular second person singular third person singular first person plural second person plural third person plural (which are actually the six possible values of a kind called `narrative viewpoint`), while the story tense must be one of: past tense present tense future tense perfect tense past perfect tense (from a kind called `grammatical tense`). Combining these gives 30 possibilities in all, though only a few are at all commonly used. It's important to make a very large caveat here: Inform uses these settings in producing the replies ("responses") by the built-in actions, but the only way for all of our own text to have a particular tense or narrative viewpoint is to write it that way. If we write: The Taj Mahal is a room. "You stand and admire the Taj Mahal." When play begins: now the story viewpoint is first person plural; now the story tense is past tense. then we're likely to see the following peculiar transcript: ``` transcript Taj Mahal You stand and admire the Taj Mahal. > E We couldn't go that way. ``` That's because the response (``We couldn't go that way.``) was constructed to follow the settings for viewpoint and tense, but the fixed text of the room description wasn't. In fact there are ways to write the room description so that it would adapt itself automatically, as we'll see, but it takes a fair amount of work. More simply: The Taj Mahal is a room. "I stood and admired the Taj Mahal." When play begins: now the story viewpoint is first person plural; now the story tense is past tense. In short, tense and viewpoint switching is neat, but it isn't magic. If we want to write text which will work in whatever the current tense is, the following turn out to be useful little conveniences: > phrase: {phs_here} say "[here]" > > Produces ``here`` if the story tense is the present tense, and ``there`` otherwise. > phrase: {phs_now} say "[now]" > > Produces ``now`` if the story tense is the present tense, and ``then`` otherwise. ## Adaptive text ^^{+to+say "[are]"} ^^{+tosay+"[are]" --> are} ^^{+to+say "[can]"} ^^{+tosay+"[can]" --> can} ^^{+to+say "[have]"} ^^{+tosay+"[have]" --> have} ^^{+to+say "[carry]"} ^^{+tosay+"[carry]" --> carry} ^^{+to+say "[wear]"} ^^{+tosay+"[wear]" --> wear} ^^{+to+say "[can touch]"} ^^{+tosay+"[can touch]" --> can touch} ^^{+to+say "[can see]"} ^^{+tosay+"[can see]" --> can see} ^^{+to+say "[they]"} ^^{+tosay+"[they]" --> they} ^^{adaptive displayed text} ^^{pronouns: adaptive pronouns in displayed text} ^^{adaptive displayed text: pronouns} ^^{verbs: adaptive verbs in displayed text} ^^{adaptive displayed text: verbs} Paying attention to the tense and viewpoint is one reason why text might need to adapt. Another is that it might need to adapt according to whether nouns are singular or plural, or whether it talks about the player or some third party. For example, the following rule isn't ideal: Instead of taking: say "[The noun] is pinned down by Dr Zarkov's force field." Most of the time it's fine (``The V-ray is pinned down by Dr Zarkov's force field``), but then: > GET ME You is pinned down by Dr Zarkov's force field. > GET CONDENSERS The condensers is pinned down by Dr Zarkov's force field. Which is a little unfortunate. But the correction is very easy: Instead of taking: say "[The noun] [are] pinned down by Dr Zarkov's force field." The result is much better: ``The V-ray is pinned down...``; ``You are...``; ``The condensers are...``. In fact, it's also convenient because it adapts to the story viewpoint and story tense: ``The condensers will be pinned down...``; ``He was pinned down...``. How does Inform do this? The answer is not that `"[are]"` is a specially-written text substitution. In fact Inform can do this with any verb that it has a definition of. For example, "[The noun] [carry] too much static charge." would also adapt itself – ``The V-ray carries too much static charge``, and so on. There aren't many verbs built in to Inform, but `"[have]"` and `"[carry]"` and `"[wear]"` and `"[can]"` may be useful, and `"[can see]"` and `"[can touch]"`. Negative forms like `"[are not]"` are also available: "[The noun] [cannot touch] the ionizer terminal." might produce ``The V-ray will not be able to touch the ionizer terminal.``, for example. As these examples hint, the verb adapts itself to the most recently printed object name. All of this only works if the previous object's name is printed from a substitution. So: "[The condensers] [are] working." will work – correctly forming ``The condensers are working.``, ``The condensers will be working.`` or ``The condensers were working.``, according to the story tense – but "The condensers [are] working." probably won't work. Inform doesn't have any way to understand the raw text outside of the text substitution marks `"[" and "]"`, and it doesn't recognise `The condensers` as being something's name. Something else to be careful with is the use of lists. If we write this: "[The condensers] and [the V-ray] [are] smashed by Voltan's birdmen." then Inform is likely to print: ``` transcript The condensers and the V-ray is smashed by Voltan's birdmen. ``` because it looks at the most recently named object – the V-ray, singular – to decide whether to use ``is`` or ``are``. On the other hand, Inform gets this right: "[The list of things on the bench] [are] smashed by Voltan's birdmen." Because Inform constructs the list itself, it's able to appreciate that the things listed are jointly the subject of the verb, and it uses that information to decide on ``is`` or ``are``. So: ``` transcript The condensers and the V-ray are smashed by Voltan's birdmen. The Atomic Furnace shovel is smashed by Voltan's birdmen. ``` ## More on adapting verbs ^^{verbs: defining adaptive displayable verbs} ^^{adaptive displayed text: verbs} ^^{defining: adaptive displayable verbs} ^^{+to+say "[put]"} ^^{+tosay+"[put]" --> put} ^^{to (V) is a verb+assert+} If we need an adaptive message with a verb which doesn't belong to Inform's built-in set, all we need do is define it. In the previous chapter, [Relations] we defined verbs by giving them meanings, but in fact that's optional. For example: To retrofit is a verb. defines a verb without telling Inform what it means. Inform will throw a Problem message if we try to write text like: Flash retrofits the meteor beam. because, after all, it doesn't know what `retrofit` means. But it does still know how to print it, so this works: "[The actor] [retrofit] the Mecha-Mole." which might come out as ``Dale retrofits the Mecha-Mole``, or ``Barin's archers retrofitted the Mecha-Mole``, and so on. This is especially neat for writing a single response to an action which works regardless of who the actor was. For example, the Standard Rules include: say "[The actor] [put] [the noun] on [the second noun]." And this can make either: ``` transcript You put the Bill-signing pen on the table. President Obama puts the Bill-signing pen on the table. ``` Only a single-word verb can be used for adaptive text. If we create the verb `to run amok in`, then `"[The noun] [run amok in] the Furnace Room."` will not be allowed. The trick would be to create `To run is a verb.`, and then use `"[The noun] [run] amok in the Furnace Room."` ## Adapting text about the player ^^{+to+say "[we]"} ^^{+tosay+"[we]" --> we} ^^{+to+say "[us]"} ^^{+tosay+"[us]" --> us} ^^{+to+say "[our]"} ^^{+tosay+"[our]" --> our} ^^{case sensitivity: in text substitutions with pronouns} ^^{plurals: plural convention for adaptive pronouns} ^^{pronouns: adaptive pronouns in displayed text} ^^{adaptive displayed text: pronouns} ^^{you, adaptive pronouns in displayed text} ^^{actor (- person)+actvar+} In second-person-singular IF, the player is always ``you``. Many messages look like so: ``You have twenty minutes remaining.`` The subject, or the object, of the sentence is ``you``. But what if we want to have this text adapt itself to different narrative viewpoints? The solution is to use the following: - `"[We]"` or `"[we]"` - `"[Us]"` or `"[us]"` - `"[Our]"` or `"[our]"` - `"[Ours]"` or `"[ours]"` - `"[Ourselves]"` or `"[ourselves]"` The capitalised and uncapitalised versions are identical except, of course, that the initial letter of the resulting text is upper case in one but not the other. As examples of these: "[We] [carry] the Queen's warrant." "The birds drop pebbles on [us]. Right on [our] heads!" "[Ours] are the burdens of office, which [we] take on [ourselves]." Notice that all five of these forms are differently worded, in English. That's the reason why we use the plural to write them – the traditional second person plural forms would be "you", "you", "your", "yours" and "yourself", so we wouldn't know if `"[you]"` was supposed to be the subject or the object of the verb. So the convention with all of these adaptive forms is that we use "we" and its variations. (That's also why the verbs are written in the plural – `"[carry]"`, not `"[carries]"`.) ## Adapting text referring to other things ^^{+to+say "[they]"} ^^{+tosay+"[they]" --> they} ^^{+to+say "[their]"} ^^{+tosay+"[their]" --> their} ^^{+to+say "[there]"} ^^{+tosay+"[there]" --> there} ^^{+to+say "[it]"} ^^{+tosay+"[it]" --> it} ^^{+to+say "[regarding (thing)]"} ^^{+tosay+"[regarding (thing)]" --> regarding (thing)} ^^{+to+say "[regarding (number)]"} ^^{+tosay+"[regarding (number)]" --> regarding (number)} ^^{case sensitivity: in text substitutions with pronouns} ^^{pronouns: adaptive pronouns in displayed text} ^^{adaptive displayed text: pronouns} The family in the previous section – `"[we]"`, `"[us]"`, `"[our]"`, `"[ours]"`, `"[ourselves]"` – always referred to the player. But we also sometimes want to refer to other things without naming them. For example, how should we adapt this? > EXAMINE TREE It has no clear outline in this misty netherworld. We can easily make the verb adapt – change the "has" to `"[have]"` – but the trick here is to make the ``It`` adapt to cases where what's examined is plural, or animate. What we want is: Instead of examining in the Netherworld: say "[regarding the noun][They] [have] no clear outline in this misty netherworld." For example, this produces: > EXAMINE ME You have no clear outline in this misty netherworld. > EXAMINE MARK He has no clear outline in this misty netherworld. > EXAMINE DRUMS They have no clear outline in this misty netherworld. Note that we have to say `"[regarding the noun]"`, not just start in with `"[They]"`, because nothing has been named so far in the sentence – so Inform doesn't know what object it refers to. `"[regarding the noun]"` prints nothing, and simply tells the printing part of Inform that the subject has changed. This isn't always needed: "[We] [have] a look at [the noun], but [they] [are] just too big." works fine, because printing `"[the noun]"` changes the subject to that, and then `"[they]"` agrees with it automatically. The text might come out, for example, as: ``` transcript I had a look at Peter Rabbit, but he was just too big. You have a look at the chessmen, but they are just too big. We have a look at ourselves, but we are just too big. ``` We have a family of five text substitutions here, matching those in the previous section: - `"[They]"` or `"[they]"` - `"[Them]"` or `"[them]"` - `"[Their]"` or `"[their]"` - `"[Theirs]"` or `"[theirs]"` - `"[Themselves]"` or `"[themselves]"` There's also the peculiar impersonal non-object for English sentences like "It is raining" or "There are books": - `"[It]"` or `"[it]"` - `"[There]"` or `"[there]"` These look pointless – but consider the two texts "[We] [take] [the noun]. It [rain] harder." "[We] [take] [the noun]. [It] [rain] harder." The first one risks printing ``We took the scissors. It rain harder.``, because it makes `"[rain]"` agree with "scissors", which are plural. But the second text makes `"[rain]"` agree with `"[it]"`. And, as a convenience: - `"[It's]"` or `"[it's]"` - `"[There's]"` or `"[there's]"` do the obvious thing using the current story tense. Finally, we occasionally want to agree with a number: "Honestly, [dud count][regarding the dud count] of these [are] broken." As a convenience, `[regarding...]` also affects `[s]`, the text substitution which adds an "s" if the last thing(s) discussed are plural: "the [regarding the number of animals in the crate]animal[s] in the crate" Which prints "animals" if the number is 0 or at least 2, and "animal" if there's just one in the crate. ## Adapting demonstratives and possessives ^^{+to+say "[those]"} ^^{+tosay+"[those]" --> those} ^^{+to+say "[possessive]"} ^^{+tosay+"[possessive]" --> possessive} ^^{+to+say "[regarding (thing)]"} ^^{+tosay+"[regarding (thing)]" --> regarding (thing)} ^^{case sensitivity: in text substitutions with pronouns} ^^{pronouns: adaptive pronouns in displayed text} ^^{adaptive displayed text: pronouns} ^^{that, adaptive pronouns in displayed text} Consider the following message: how might we make this adaptive? > MEASURE TOP SHELF You really are not tall enough to reach that. The verbal part is easy enough, but ``that`` needs a new feature. "[We] really [are not] tall enough to reach [regarding the noun][those]." This could then adapt to, say, > MEASURE JAM TARTS He really was not tall enough to reach those. Notice that it's "[regarding the noun][those]", not just `"[those]"`. If we wrote `"[those]"`, Inform would make it agree with the player, who was printed earlier in the sentence by the `"[We]"`. Lastly, how about: > PUT TEAPOT IN MOUSEHOLE The teapot's height is just too great. This time we want: "[regarding the noun][Possessive] height [are] just too great." which might adapt to, say, ``` transcript Our height is just too great. Alice's height will be just too great. ``` Actually, `"[regarding ...]"` can be used for a description of possibly many items, too. For example: Every turn when the player carries something: say "Every possession is a worry. I wonder if [regarding things carried by the player][they] still [look] okay in your pocket?" So if the player carries just a single coin, say, this automatically becomes: ``` transcript Every possession is a worry. I wonder if it still looks okay in your pocket? ``` but if the player carries a pair of scissors (a single plural-named item) or a coin and an iPhone, it becomes: ``` transcript Every possession is a worry. I wonder if they still look okay in your pocket? ``` Once again these text substitutions are available in capitalised and uncapitalised forms: - `"[Those]"` or `"[those]"` - `"[Possessive]"` or `"[possessive]"` In fact `"[Those]"` and `"[those]"` do subtly different things, besides the capital letter, because `"[Those]"` expects to be the subject of the sentence and `"[those]"` the object, and this makes a difference if the noun in question is a person. If the noun is an odious person called Tilly then "[regarding the noun][Those] is unacceptable." "You've never liked [regarding the noun][those]." would come out as ``She is unacceptable`` – so `"[Those]"` becomes ``She`` – but ``You've never liked her`` – so `"[those]"` becomes ``her``. If we need these in different cases, we can explicitly ask for that: - `"[those in the nominative]"` - `"[Those in the accusative]"` ## Can, could, may, might, must, should, would ^^{+to+say "[can]"} ^^{+tosay+"[can]" --> can} ^^{+to+say "[might]"} ^^{+tosay+"[might]" --> might} ^^{+to+say "[may]"} ^^{+tosay+"[may]" --> may} ^^{+to+say "[could]"} ^^{+tosay+"[could]" --> could} ^^{+to+say "[would]"} ^^{+tosay+"[would]" --> would} ^^{+to+say "[must]"} ^^{+tosay+"[must]" --> must} ^^{+to+say "[should]"} ^^{+tosay+"[should]" --> should} ^^{+to+say "[can't]"} ^^{+tosay+"[can't]" --> can't} ^^{+to+say "[mightn't]"} ^^{+tosay+"[mightn't]" --> mightn't} ^^{+to+say "[mayn't]"} ^^{+tosay+"[mayn't]" --> mayn't} ^^{+to+say "[couldn't]"} ^^{+tosay+"[couldn't]" --> couldn't} ^^{+to+say "[wouldn't]"} ^^{+tosay+"[wouldn't]" --> wouldn't} ^^{+to+say "[mustn't]"} ^^{+tosay+"[mustn't]" --> mustn't} ^^{+to+say "[shouldn't]"} ^^{+tosay+"[shouldn't]" --> shouldn't} ^^{contractions, adaptive contractions in displayed text} ^^{adaptive displayed text: contractions} ^^{verbs: modal / non-modal+adj+} ^^{modal / non-modal (verb)+adj+} ^^{to (V) is a verb+assert+} English uses so-called "modal verbs" to change a sentence so that it talks about something only possibly happening. For example, the sentence "Fred goes to school" can be modified to "Fred must go to school", "Fred should go to school" or even "Fred might go to school". Inform supports the use of modal verbs in text substitutions. For example, "[Fred] [might go] to school." would in the present tense come out as ``Fred might go to school.``, but could alternatively be ``Fred might have gone to school.`` As this example shows, all that's needed is to take a verb we'll call V – this case, "go" – and we can write any of these: `"[can V]"` or `"[cannot V]"` or `"[can't V]"` `"[could V]"` or `"[could not V]"` or `"[couldn't V]"` `"[may V]"` or `"[may not V]"` or `"[mayn't V]"` `"[might V]"` or `"[might not V]"` or `"[mightn't V]"` `"[must V]"` or `"[must not V]"` or `"[mustn't V]"` `"[should V]"` or `"[should not V]"` or `"[shouldn't V]"` `"[would V]"` or `"[would not V]"` or `"[wouldn't V]"` That helps us to handle informal usages like ``You can't go that way.``. To make this message adaptive, we write: "[We] [can't go] that way." which can adapt in surprising ways – ``They won't be able to go that way.``, for example. Note that the verb V has to be one that Inform knows. But that's easy: To discombobulate is a verb. and then "[Fred] [might not discombobulate] so easily." could produce ``Fred might not have discombobulated so easily``, for example. ## Adapting contractions ^^{+to+say "['re]" --> say "[re} ^^{+tosay+"['re]" --> re} ^^{+to+say "['ve]" --> say "[ve} ^^{+tosay+"['ve]" --> ve} ^^{+to+say "[aren't]"} ^^{+tosay+"[aren't]" --> aren't} ^^{+to+say "[don't]"} ^^{+tosay+"[don't]" --> don't} ^^{+to+say "[won't]"} ^^{+tosay+"[won't]" --> won't} ^^{+to+say "[haven't]"} ^^{+tosay+"[haven't]" --> haven't} ^^{pronouns: adaptive contractions in displayed text} ^^{adaptive displayed text: pronouns} ^^{contractions, adaptive contractions in displayed text} ^^{adaptive displayed text: contractions} Contractions usually take the form of part of a word being missed out and replaced by an apostrophe. We've already seen `"[can't]"`, `"[couldn't]"`, `"[mayn't]"`, `"[mightn't]"`, `"[mustn't]"`, `"[shouldn't]"` and `"[wouldn't]"`, for example. But Inform supports other contractions, too, as follows. The English verbs "to be" and "to have" are unique in having contracted forms, which we can write `"['re]"` and `"['ve]"`, like this: "[We]['ve] got rhythm. [We]['re] cool." which might produce, say, ``I've got rhythm. I'm cool.``, or ``He'll have rhythm. He'll be cool.``, or ``You had got rhythm. You were cool.`` (The contractions don't appear in the past tense; but the spacing fixes itself automatically.) The Standard Rules often use a special text substitution for responses like this one: "[They're] hardly portable." This is exactly like `"[Those]['re] hardly portable"` except that if the plural is needed, Inform prints ``They're hardly portable`` rather than the correct, but not quite idiomatic, ``Those're hardly portable``. (If we wrote `"[They]['re] ..."`, that would get the plural form right, but then the singular would be ``It's hardly portable`` not ``That's hardly portable``.) Only a few English verbs have contracted negative forms, beyond those already mentioned. Inform knows these informal forms: - `"[aren't]"` - `"[don't]"` - `"[haven't]"` - `"[won't]"` For example, Instead of taking something: say "[The noun] [are] pinned down by Dr Zarkov's force field. [They] [aren't] free to move. [They] [can't] move. [They] [won't] move. [They] [haven't] a chance to move. Anyhow, [they] [don't] move." can produce variations like these: ``` transcript The condensers are pinned down by Dr Zarkov's force field. They aren't free to move. They can't move. They won't move. They haven't a chance to move. Anyhow, they don't move. You were pinned down by Dr Zarkov's force field. You weren't free to move. You couldn't move. You wouldn't move. You hadn't a chance to move. Anyhow, you didn't move. ``` ## Verbs as values {kind_verb} ^^{sentence verbs: as values} ^^{verbs: as values} ^^{verbs: meaningful / meaningless+adj+} ^^{verbs: modal / non-modal+adj+} ^^{modal / non-modal (verb)+adj+} ^^{non-modal / modal (verb)+adj+} ^^{meaningful / meaningless (verb)+adj+} ^^{meaning+rel+} ^^{meaning+relcat+} Each verb known to Inform is actually a value of the kind `verb`. To refer to this value, we put the word `verb` in front of its first-person plural. So for example: - `the verb contain` - `the verb might` - `the verb provoke` For irregular verbs this might be different from the infinitive form, but to avoid confusion Inform accepts either. Thus `the verb are` and `the verb be` are both ways to write the same value — the verb "to be" in value form. Two adjectives are provided for use with verbs: `modal` (or `non-modal`) to pick out verbs like might, could, should, and so on; and `meaningful` (or `meaningless`) to pick out verbs which have a defined meaning as an Inform relation. For example, in the Standard Rules, the verb contain is meaningful, the verb might is modal, and the verb provoke is meaningless. If V has a meaning as a relation of objects, then `meaning of V` produces that relation. For example, showme the meaning of the verb contain; showme the meaning of the verb provoke; produces: ``` transcript "meaning of the verb contain" = relation of objects: containment relation "meaning of the verb provoke" = relation of objects: never-holding relation ``` As this demonstrates, if a verb has no meaning, or its meaning doesn't relate to objects, we get just the `never-holding relation`. This is a relation which, as the name suggests, never holds, and can't be made to hold, between any two values. In fact, Inform even defines a verb `to mean`: it's meaningful, and its meaning is the meaning relation. Thus: if the verb mean means the meaning relation... is true. More usefully, we can search our vocabulary like this: the list of verbs meaning the containment relation which, unless any non-Standard Rules definitions have been added, produces: ``` transcript list of verbs: {verb contain} ``` Note that the meaning relation can't be changed at run-time: it is not clear what it would even mean to do something like – now the verb contain means the wearing relation; with the story already started, so this will produce a problem message. > phrase: {phs_adapt} say "[adapt (verb)]" > > Adapts the given verb to the current story tense and story viewpoint. For example, `"you [adapt the verb provoke]"` might produce ``you provoke``. > phrase: {phs_adaptv} say "[adapt (verb) from (narrative viewpoint)]" > > Adapts the given verb to the current story tense but the given viewpoint. For example, "he [adapt the verb provoke from the third person singular]" might produce "he provokes". > phrase: {phs_adaptt} say "[adapt (verb) in (grammatical tense)]" > > Adapts the given verb to the given tense but the current story viewpoint. For example, `"you [adapt the verb provoke in the past tense]"` might produce ``you provoked``. > phrase: {phs_adaptvt} say "[adapt (verb) in (grammatical tense) from (narrative viewpoint)]" > > Adapts the given verb to the given tense and viewpoint. For example, `"we [adapt the verb provoke in the future tense from the first person plural]"` might produce ``we will provoke``. > phrase: {phs_negate} say "[negate (verb)]" > > Adapts the given verb to the current story tense and story viewpoint, giving it a negative sense. For example, `"you [negate the verb provoke]"` might produce ``you do not provoke``. > phrase: {phs_negatev} say "[negate (verb) from (narrative viewpoint)]" > > Adapts the given verb to the current story tense but the given viewpoint, giving it a negative sense. For example, `"she [negate the verb provoke from the third person singular]"` might produce ``she does not provoke``. > phrase: {phs_negatet} say "[negate (verb) in (grammatical tense)]" > > Adapts the given verb to the given tense but the current story viewpoint, giving it a negative sense. For example, `"you [negate the verb provoke in the past tense]"` might produce ``you did not provoke``. > phrase: {phs_negatevt} say "[negate (verb) in (grammatical tense) from (narrative viewpoint)]" > > Adapts the given verb to the given tense and viewpoint, giving it a negative sense. For example, `"we [negate the verb provoke in the future tense from the first person plural]"` might produce ``we will not provoke``. Note that the verb doesn't have to be named explicitly for use by the adapt or negate phrases, so for example: To decide which text is the rendering of (V - verb) (this is my rendering): decide on "[negate V in the past perfect tense]". When play begins: showme my rendering applied to the list of meaningful verbs. produces: ``` transcript "my rendering applied to the list of meaningful verbs" = list of texts: {"had not had", "had not related", "had not meant", "had not provided", "had not contained", "had not supported", "had not incorporated", "had not enclosed", "had not carried", "had not held", "had not worn", "had not been able to see", "had not been able to touch", "had not concealed", "had not unlocked"} ``` Lastly, we can get at three other useful parts of a verb, too. These aren't adaptive, of course: a verb only has one infinitive form. > phrase: {phs_infinitive} say "[infinitive of (verb)]" > > Produces the infinitive of the given verb. Note that this is without a ``to``: for example, `"[infinitive of the verb carry]"` is ``carry``, not ``to carry``. > phrase: {phs_pastpart} say "[past participle of (verb)]" > > Produces the past participle of the given verb. For example, `"[past participle of the verb carry]"` is ``carried``. Warning: because modal verbs like "should" or "might" are defective in English, this will produce odd results on them – ``shoulded`` and ``mighted``, for example. > phrase: {phs_prespart} say "[present participle of (verb)]" > > Produces the present participle of the given verb. For example, `"[present participle of the verb carry]"` is ``carrying``. Warning: because modal verbs like "should" or "might" are defective in English, this will produce odd results on them – ``shoulding`` and ``mighting``, for example. ## Responses ^^{responses (library messages)}^^^{punctuation: brackets <-- brackets <-- parentheses} ^^{punctuation: brackets: in response names} ^^{|( ): in response names} Most of the text which the player sees is drawn from the source, but mixed in with this are messages apparently added by Inform itself – usually in the form of short sentences saying that something has been done, or that something can't be done. Such pieces of text are called "responses", because they are almost always replies to commands. For example: > EAST You can't go that way. > JUMP You jump on the spot. Responses like this, which don't appear anywhere in the source text, come from one of the extensions being used; most often from the Standard Rules, the "extension" which is automatically included in every project. The SR contain many small rules, and almost all of these are capable of producing one or two standard responses. These are labelled with the rule's name and then a bracketed letter – `(A)`, `(B)`, `(C)`, ... as needed so that every response has its own unique name. There's nothing very mysterious about how this is done. For example, here is a rule with one response: Carry out taking inventory (this is the print empty inventory rule): if the first thing held by the player is nothing, say "[We] [are] carrying nothing." (A) instead. which makes the familiar text ``You are carrying nothing.`` a response named: print empty inventory rule response (A) These names are actually values, belonging to the kind `response`. Because of that, if we try this: say "Hmm: [print empty inventory rule response (A)]" Inform will produce ``` transcript Hmm: print empty inventory rule response (A) ``` since we gave Inform a value to print, and that's just what it then did. As an alternative: > phrase: {phs_response} say "[text of (response)]" > > This text substitution writes out the current text of the given response. Thus, say "Hmm: [text of print empty inventory rule response (A)]" produces ``Hmm: You are carrying nothing.`` ## Changing the text of responses ^^{responses (library messages): changing} These responses are named so that they can be changed. Most IF authors dislike one or two of the existing responses, and some would like to change almost all of them to give the text a different style; and extensions for IF in languages other than English change literally every response, of course. It's very easy to change responses: The print empty inventory rule response (A) is "Your hands are, like, totally empty. Loser." and we can even do this dynamically during play: now the print empty inventory rule response (A) is "Your hands ..."; just as if we were setting a variable. ## The ``RESPONSES`` testing command ^^{responses (library messages): listing during development} ^^{RESPONSES+testcmd+} ^^{testing commands: >RESPONSES} In practice we can't change these responses unless we know what they're called. One way to find out is just to read through the extensions we're using, but that's a laborious process. A more practical answer is to type ``RESPONSES``, which replies by listing the sets of responses currently available; for example, it says that ``RESPONSES 1`` is the set of responses for the Standard Rules. We can then type exactly that: > RESPONSES 1 Standard Rules: block vaguely going rule response (A): "You'll have to say which compass direction to go in." print the final prompt rule response (A): "> [run paragraph on]" ... and so on. This lists all of the responses, rule by rule, along with their current texts. # Quantities and Equations ## How do we measure things? ^^{numbers} ^^{units of measure} In a poem, or in a novel, exact scientific measurements are not the point. So a writer who wants to set up ways to describe the sky at different times might go for something like this: The sky can be cadmium, mackerel, overcast or cornflower. And nobody is interested in the sun angle, the percentage of cloud cover, or any of the other numbers behind all of this. Similarly, if we walk into a familiar office which has been disturbed, we might well say "Look! The filing cabinet is in the middle of the floor." We are not likely to exclaim "Look! The filing cabinet is 1.2m from the east wall and 2.1m from the north wall." But some writers of interactive fiction do like to make use of physical realism. For instance, it's easier to forbid a bulky object being taken through a narrow doorway if there is a way to measure and compare sizes. Most computer programs write numbers in the same way, whatever they're used for. But human beings don't. If someone says "How far is Duluth?", we're more likely to say "100 miles" than just "100". This is a useful feature of natural language, because it means we always know how to translate that number into reality – it's 100 miles, not 100 km, or 100 inches; and it's definitely a distance, not 100 apples or 100 kilograms. Inform lets us use plain numbers if we want to, but it also allows us to create numerical kinds of value: A distance is a kind of value. 5 miles specifies a distance. That kind of definition, and the consequences, will be the subject of this chapter. But we will first look a little harder at the two numerical kinds of value we get for free: `number` and `real number`. ## Numbers, ranges, overflows, and number bases {kind_number} {PM_ZMachineOverflow} {PM_ElementOverflow} {PM_LiteralOverflow} ^^{numbers} ^^{limits: of numeric values} ^^{numbers: limits of numeric values} ^^{Z-machine: numeric limits} ^^{Glulx: numeric limits} ^^{virtual machine: numeric limits} ^^{numbers: hexadecimal and other bases <-- binary numbers <-- hexadecimal numbers <-- octal numbers} ^^{numbers: asking the player for} ^^{querying the player: for a number} ^^{asking the player: for a number} What Inform calls a `number` is a whole number, positive, negative or zero. Numbers from `zero` to `twelve` may also be written out in words, but all others must be written as numerals. So `twelve` or `12`, but `13` only. For efficiency reasons, only a limited range of whole numbers close to 0 can be stored as a `number`, but in practice that range is large enough for all everyday purposes: -2147483648, -2147483647, ..., -3, -2, -1, 0, 1, 2, 3, ..., 2147483647 If the Settings for a project make it use the very memory-constrained Z-machine format, this number range is very much smaller, which is one reason Z should only be used when absolutely necessary: -32768, -32767, ..., -3, -2, -1, 0, 1, 2, 3, ..., 32767 By default, all projects use Glulx, though, and the examples of numbers below assume that. This limited range raises the question: what happens if we take the theoretical maximum, `2147483647`, and add `1` to it? This is _not_ a run-time problem: "overflows" like this are entirely legal. The result is in fact `-2147483648`. So, for example, the condition `N is less than N plus 1` is true for every number `N` _except_ `2147483647`. What is going on here is that the number line described above is really more of a circle, and this is the point where we loop back to the beginning. This strange-looking phenomenon has to do with the standard way numbers are stored inside computers: see, for example, the Wikipedia page on _two's complement_ for an explanation of why this is done. It is also possible to print back a `number` in _unsigned form_, using this phrase: > phrase: {phs_inunsigneddecimal} say "[(number) in unsigned decimal]" > > This text substitution writes out the number in unsigned decimal, following the two's complement system, so that negative numbers close to zero appear large. Examples: > > value | as said in unsigned decimal > ------------- | --------------------------- > `-2147483648` | ``2147483648`` > ... | ... > `-2` | ``4294967284`` > `-1` | ``4294967285`` > `0` | ``0`` > `1` | ``1`` > ... | ... > `2147483647` | ``2147483647`` These notations so far are all in base 10, that is, they use the decimal digits `0`, `1`, ..., `9`, sometimes with a minus sign `-` in front. But Inform allows us to type numbers in the source text which use three other bases as alternatives. For example: hexadecimal 4EF12C binary 001110101101 octal 077 all produce `number` values, and are exactly equivalent to writing `5173548`, `941` and `63` respectively. Hexadecimal is base 16, using the letters `A` to `F` for the six further digits past `9`; octal is base 8, using only the digits `0` to `7`; and binary is base 2, using only `0` and `1`. Three notes to bear in mind: 1) Negative numbers cannot be written in these bases, so `hexadecimal -4EF12C` throws a problem message. 2) Numbers in binary, octal or hexadecimal are read as _unsigned_. So `hexadecimal FFFFFFFF` is allowed, but produces the same number as `-1`; `hexadecimal FFFFFFFE` is equivalent to `-2`; and so on. In hexadecimal notation, our extreme `number` values of -2147483648 and 2147483647 are `hexadecimal 80000000` and `hexadecimal 7FFFFFFF`, respectively. 3) Leading zeros are allowed in binary, octal or hexadecimal, so that `hexadecimal 01FF` is legal, even though the same trick in decimal (`0004`, say) is not. We can also print back numbers in other number bases: > phrase: {phs_inbase} say "[(number) in (base)]" > > This text substitution writes out the number in the given number base, which must be between 2 and 36. Bases can be written as `base 2`, ..., `base 36`, or as `binary` (equivalent to `base 2`), `octal` (equals `base 8`), `decimal` (equals `base 10`) or `hexadecimal` (equals `base 16`). The number is printed unsigned _unless the base is 10_, in which case it is signed. If the digits 10 to 35 are needed, they are printed as upper-case letters. > > For example, `"[14302 in binary]."` produces ``11011111011110`` and `"[14302 in hexadecimal]."` produces ``37DE``. > > The extreme example is the number `-1` which, provided the default Glulx setting is used for a project, prints as ``FFFFFFFF`` in hexadecimal, ``-1`` in decimal, ``37777777777`` in octal, ``11111111111111111111111111111111`` in binary, ``102002022201221111200`` in base 3 and ``1Z141Y3`` in base 36. > > If a project uses the Glulx setting, as is the default, then all numbers fit exactly into 8 hexadecimal digits, or 32 binary ones; with the Z-machine setting, numbers fit into 4 hexadecimal digits, or 16 binary ones. These too can be padded with zeros: > phrase: {phs_inbaseindigits} say "[(number) in (number) (base) digit/digits]" > > This text substitution writes out the number in the given number base, which must be between 2 and 36, padding with initial zeros to ensure that the result is at least the given number of digits in length. The number is printed unsigned, whatever the number base. > > For example, `"[232 in 4 decimal digits]."` produces ``0232`` and `"[232 in 4 hexadecimal digits]."` produces ``00E8``. Lastly, for completeness, we also provide: > phrase: {phs_inunsigneddecimaldigits} say "[(number) in (number) unsigned decimal digit/digits]" > > This text substitution writes out the number in unsigned decimal, in such a way that numbers normally considered decimal appear large, padding with initial zeros to ensure that the result is at least the given number of digits in length. One more phrase about `number` values is occasionally handy: > phrase: {ph_numberchosen} a/-- number chosen by the player from 1 to (number) ... number > > This prints an `>` prompt and then waits for the player to type a number (and press RETURN), and keeps asking until the player enters something in the range allowed. If the maximum value supplied is negative or zero, the phrase does not ask for player input, and simply returns 1. To reiterate, though: all these different notations for typing in, and for saying back, whole numbers are all to do with a single kind, `number`. Unlike some programming languages, Inform has no kind for "unsigned integer", nor for "integer which should always be written in binary". But it does also provide a `real number` kind, and that's where we go next. Those are always written in a signed way, and always use decimal digits. ## Real numbers {kind_real_number} {PM_InequalityFailed} {PM_CantEquateValues} {PM_EvenOverflow-G} ^^{numbers <-- integers} ^^{real numbers <-- floating-point <-- decimals} ^^{numbers: real numbers} ^^{Z-machine: real numbers not available} ^^{Glulx: real numbers available} ^^{limits: of numeric values} ^^{numbers: limits of numeric values} ^^{Z-machine: numeric limits} ^^{Glulx: numeric limits} ^^{virtual machine: numeric limits} ^^{real numbers: limits of numeric values} ^^{scientific notation} ^^{pi (- real number)+const+} ^^{e (- real number)+const+} ^^{case sensitivity: in real number constants} ^^{use options: catalogue: |engineering notation} ^^{engineering notation+useopt+} Inform uses two different kinds of numerical quantity: `number` and `real number`. Neither is better than the other: they're different approaches, each good for a different purpose. (Note that `real numbers` are _not_ available on the Z-machine, so a project needs to use the default Glulx setting to use them. In this section, we'll assume that.) `real numbers` beat `numbers` in two ways: they can hold values which lie between two integers, like `2.1718`, or `-1633.9`; and they can hold truly huge or tiny values, using "scientific notation" (see below). On the other hand, `real number` values are approximate, in a way which sometimes has to be delicately worried about. Only about the six to nine most significant decimal digits can be relied on. For example, showme 1.2345654321; showme 1.2345667890; produces ``` transcript real number: 1.23457 real number: 1.23457 ``` because these two numbers are so close together that Inform can't tell them apart. All `real number` values are a little fuzzy, and this fuzziness will lead to increasing numerical inaccuracy if enough calculations are done. Looked at with a careful eye, there is something treacherous about floating-point arithmetic on computers: and yet in practice, for all everyday purposes, `real numbers` work just fine. Inform recognises `4` as a `number` because of the lack of a decimal point `.`; the _approximate_ equivalent as a `real number` can be written as `4.0`. Scientific notation in Inform looks like so: let Avogadro's number be 6.022141 x 10^23; which is equivalent to typing let Avogadro's number be 602214100000000000000000.0; The `x 10^23` part tells Inform that the decimal point belongs 23 places to the left of where it's written. (In scientific papers, the 23 would be printed as a superscript – it's 10 raised to the power 23 – but that's not convenient to type in to the source text, so we use the `^` symbol to indicate superscript.) The range that a `real number` can hold is roughly: 1.18 x 10^−38, ..., 3.4 x 10^38 It's hard to convey just how enormously different these two numbers are. If we used them to measure widths in meters, one would be a hundred trillion trillion times smaller than an atom, the other a billion times larger than the entire visible universe. Scientific notation is the ultimate adjustable spanner. ^^{@Leonhard Euler} Inform also allows the two most famous real numbers in mathematics to be given by their names, `pi` and `e`, which are close to `3.14159265` and `2.7182818` respectively. (Lower case letters must be used: these can't be written `Pi` or `E`. Euler's constant gamma, always in the bronze medal position, will have to be written out longhand as `0.5772156649`.) Most computer programming languages traditionally write floating-point numbers using the E notation, like so: 6.022141E+23; Inform will follow suit if the use option `Use engineering notation.` is active, but by default it isn't. ## Real number conversions ^^{numbers: conversion to/from real numbers} ^^{real numbers: conversion to/from numbers} ^^{numbers: real numbers: conversion to/from numbers} ^^{whole number: (real number) to the nearest whole number+phr+} ^^{nearest whole number: (real number) to the nearest whole number+phr+}^^^{+to+(real number) to the nearest whole number --> to the nearest whole number} ^^{calculation: conversion during calculations} ^^{calculation: rounding to the nearest whole number} ^^{plus infinity (- real number)+const+} ^^{minus infinity (- real number)+const+} ^^{finite / infinite (real number)+adj+} ^^{infinite / finite (real number)+adj+} ^^{existent / nonexistent (real number)+adj+} ^^{nonexistent / existent (real number)+adj+ <-- NaN (not a number)} ^^{real numbers: infinite and nonexistent} ^^{numbers: real numbers: infinite and nonexistent} This section notes down some technicalities about real numbers which need to be put down in writing somewhere, but won't affect most people most of the time. Inform allows us to use numbers whenever real numbers are expected, and converts them automatically. For example, cosine of 2 is read as if it were cosine of 2.0 and produces -0.41615 either way. This conversion goes from exactness to approximation, so we may lose a little accuracy: real numbers measure to an accuracy of about 1 part in 16000000, so they'll have trouble telling the difference between 16000000 and 16000001. But this is unlikely to matter, since real numbers are used only for approximate calculations anyway. The ordinary arithmetic operations work on both numbers and real numbers, so the meaning of `N plus M` depends on the kinds of N and M. In general the rule is that if either is a real number then the other one is automatically converted, and real arithmetic is used. So: 3 divided by 2 = 1 3 divided by 2.0 = 1.5 3.0 divided by 2 = 1.5 3.0 divided by 2.0 = 1.5 In general we can't do the reverse, that is, we can't silently use a real number where a number is expected. For example, word number 1.6 in "The Great Wall of China" makes no sense. But we can explicitly convert them: > phrase: {ph_nearestwholenumber} (real number) to the/-- nearest whole number ... number > > This phrase performs signed addition on the given values, whose kinds must agree, and produces the result. Examples: > > 1.4 to the nearest whole number = 1 > 1.6 to the nearest whole number = 2 > -1.6 to the nearest whole number = -2 > > We probably ought to bear in mind that the limited range of `number` means that the nearest whole number might not be all that near. For example: > > 6 x 10^23 to the nearest whole number = 2147483647 > > because 2147483647 is the highest value a `number` can have. Finally, real number can also store two interesting not-really-number sorts of value. First, we have `plus infinity` and `minus infinity`, which are used to keep track of what happens when we divide by really small quantities. It's mathematically impossible to divide by 0, but this can be hard to avoid when we're using real numbers, because they're only approximately stored – so it's not always possible to say whether they're exactly 0 or not. So in real number arithmetic, showme 1.0 divided by 0.0; doesn't throw a run-time problem the way that showme 1 divided by 0; does. Instead, it produces `plus infinity`. Infinity behaves roughly the way we might expect — for example, `2 divided by plus infinity` produces 0.0 – but once it comes into a calculation the result probably lies on some extreme and won't be very useful. Amusingly, the following is correct Inform syntax: plus infinity to the nearest whole number and evaluates of course to 2147483647. We can use the adjectives `infinite` and `finite` to talk about these numbers: `plus infinity` and `minus infinity` are `infinite`, everything else is `finite`. The same problem occurs for calculations like square roots. It's impossible to take the square root of a negative number, but we don't want to throw a run-time problem, because approximation means we can't always guarantee to stay the right side of 0. So for a few calculations like this, Inform generates what's called a `nonexistent` real number. We can use the adjectives nonexistent or existent to talk about this. Every number mentioned on this page so far is `existent`, including the infinities. The only way to get a nonexistent number is to carry out an impossible mathematical operation such as logarithm of -10 (The design of `real number` here follows well established trade-offs for scientific computing. Inform follows the IEEE-754 binary32 standard for floating-point arithmetic, so Inform's `real number` behaves very like the ```float``` type in C, C++, Java and similar programming languages. A `nonexistent` number is what's often called a NaN – a Not-a-Number.) ## Printing real numbers ^^{text substitutions: real numbers} ^^{real numbers: displaying} ^^{numbers: real numbers: displaying} ^^{scientific notation} ^^{decimals: +to+say "[(real number) to (number) decimal places]"} ^^{decimals: +to+say "[(real number) in decimal notation]"} > phrase: {phs_realplaces} say "[(real number) to (number) decimal places]" > > This text substitution writes out the number to the given number of decimal places. Examples: > > "The semicircle is roughly [pi to 3 decimal places] paces around." > > produces ``The semicircle is roughly 3.142 paces around.`` The number of places can only usefully be from 1 to 8. Note that, for example, `"[1.235 x 10^-7 to 3 decimal places]"` produces ``0.0``; `"[1.235678 x 10^8 to 3 decimal places]"` produces ``1.236 x 10^8``. > phrase: {phs_decimal} say "[(real number) in decimal notation]" > > This text substitution writes out the number in decimal form, that is, avoiding ``x 10^n`` even for very large or very small quantities. For example, > > "[1.23457 x 10^8 in decimal notation]" > > produces ``123457000.0`` rather than ``1.23457 x 10^8``. This can look pretty extreme: for example, `"[1.8983 x 10^27 in decimal notation]"`, the mass of the planet Jupiter in kilograms, produces ``1898296960000000000000000000.0``. > phrase: {phs_decimalplaces} say "[(real number) to (number) decimal places in decimal notation]" > > This text substitution writes out the number in decimal form, but rounding to the accuracy given. > phrase: {phs_scientific} say "[(real number) in scientific notation]" > > This text substitution writes out the number in scientific form, that is, using ``x 10^n`` even for easy-to-judge quantities. For example, > > "[the reciprocal of 137 in scientific notation]" > > produces ``7.29927 x 10^-3`` rather than ``0.0073``. This can look odd: for example, `"[pi in scientific notation]"` comes out as ``3.14159 x 10^0`` rather than ``3.14159``. > phrase: {phs_scientificplaces} say "[(real number) to (number) decimal places in scientific notation]" > > This text substitution writes out the number in scientific form, but rounding to the accuracy given. ## Arithmetic ^^{numbers: arithmetic} ^^{real numbers: arithmetic} ^^{calculation: arithmetic} ^^{calculation: rounding to the nearest multiple} ^^{comparisons: of numbers} ^^{greater than+relverb+} ^^{less than+relverb+} ^^{at least+relverb+} ^^{at most+relverb+} ^^{roots, of numbers}^^^{+to+(arithmetic value) plus (arithmetic value) --> plus}^^^{+to+(arithmetic value) + (arithmetic value) --> +}^^^{+to+(arithmetic value) minus (arithmetic value) --> minus}^^^{+to+(arithmetic value) - (arithmetic value) --> -}^^^{+to+(arithmetic value) multiplied by (arithmetic value) --> multiplied by}^^^{+to+(arithmetic value) times (arithmetic value) --> times}^^^{+to+(arithmetic value) * (arithmetic value) --> *}^^^{+to+(arithmetic value) divided by (arithmetic value) --> divided by}^^^{+to+(arithmetic value) / (arithmetic value) --> /}^^^{+to+(arithmetic value) to the nearest (arithmetic value) --> to the nearest} ^^{nearest: (arithmetic value) to the nearest (arithmetic value)+phr+} We are allowed to perform about the same operations on numbers as are provided by a simple office calculator, starting with addition, subtraction, multiplication and division. We can use the traditional typewriter symbols for these, `+`, `-`, `*` and `/`, or can spell them out in words as `plus`, `minus`, `times` (or `multiplied by`), and `divided by`. English sentences are not a great way to write complex formulae: [Equations] are provided for that. But simple calculations do work, and Inform does have a basic idea that multiplication and division take precedence over addition and subtraction: ``` transcript "1 plus 2 times 4" = number: 9 "1 times 2 plus 4" = number: 6 "2 minus 3 minus 1" = number: 0 ``` Brackets can be used to clarify: `2 minus 3 minus 1` produces `2 minus (3 minus 1)`, not `(2 minus 3) minus 1`, but the bracketed version is clearer in both cases. > phrase: {ph_plus} (arithmetic value) + (arithmetic value) ... value & (arithmetic value) plus (arithmetic value) ... value > > This phrase performs signed addition on the given values, whose kinds must agree, and produces the result. Examples: > > 200 + 1 = 201 > 10:04 AM + two minutes = 10:06 AM > phrase: {ph_minus} (arithmetic value) - (arithmetic value) ... value & (arithmetic value) minus (arithmetic value) ... value > > This phrase performs signed subtraction on the given values, whose kinds must agree, and produces the result. Examples: > > 200 - 1 = 199 > 10:04 AM - two minutes = 10:02 AM > 10:04 AM - 10:02 AM = two minutes > phrase: {ph_times} (arithmetic value) \* (arithmetic value) ... value & (arithmetic value) times (arithmetic value) ... value & (arithmetic value) multiplied by (arithmetic value) ... value > > This phrase performs signed multiplication on the given values, whose kinds must be dimensionally compatible, and produces the result. Examples: > > 201 times 3 = 603 > two minutes times 4 = eight minutes > phrase: {ph_divide} (arithmetic value) / (arithmetic value) ... value & (arithmetic value) divided by (arithmetic value) ... value > > This phrase performs signed division on the given values, whose kinds must be dimensionally compatible, and produces the result. Examples: > > 201 divided by 3 = 67 > 202 divided by 3 = 67 > 202.0 divided by 3 = 67.33334 > twenty minutes divided by 4 = five minutes > twenty minutes divided by five minutes = 4 > > Division rounds whole-number values down to the nearest whole number. An attempt to divide a number by 0 will cause a run-time problem message; but an attempt to divide a real number by 0 will instead produce plus infinity or minus infinity. > phrase: {ph_remainder} remainder after dividing (arithmetic value) by (arithmetic value) ... value > > This phrase performs signed division on the given values, whose kinds must be dimensionally compatible, and then produces the remainder. Examples: > > remainder after dividing 201 by 5 = 1 > remainder after dividing twenty minutes by 7 = six minutes > > It is mathematically impossible to divide by 0, so any attempt to find the remainder after dividing a number by 0 will cause a run-time problem message. For a real number this won't arise and the remainder will usually be 0.0. The verbal and symbolic forms of these phrases are equivalent: the score + 10 the score plus 10 It's probably better style to spell them out in full when writing text, and keep the symbols for writing equations, as we'll see later on in the chapter. (If we do use the symbols, then spaces around them are obligatory: to Inform, they are words which just happen to be spelt with symbols instead of letters.) Arithmetic often produces fussily exact answers which seem inappropriate in a conversation. Nobody says "Steeple Barton is 7.655 miles down the road", but "Steeple Barton is eight miles down the road" sounds perfectly normal. In order to make that sort of report easier to make, Inform provides another arithmetic operation, one that's not found in most computer programming languages: > phrase: {ph_nearest} (arithmetic value) to the nearest (arithmetic value) ... value > > This phrase rounds the given value off, rounding upward in boundary cases. Examples: > > 201 to the nearest 5 = 200 > 205 to the nearest 10 = 210 > 10:27 AM to the nearest five minutes = 10:25 AM Inform has very few mathematical functions built in as phrases, because these aren't very often needed in story-telling. But it does provide these: > phrase: {ph_squareroot} square root of (arithmetic value) ... value > > This phrase produces an approximate square root, to the nearest integer, of the given value, which must be of a kind which has square roots. Example: > > square root of 16 = 4 > > Trying to take the square root of a negative number will cause a run-time problem, because then we can't even nearly solve it. > > (Warning: this is slow to compute if the Z-machine setting is used. For best performance, use Glulx.) > phrase: {ph_realsquareroot} real square root of (arithmetic value) ... value > > This phrase produces a square root, as accurately as a real number can hold it, of the given value, which must be of a kind which has square roots. Example: > > real square root of 2 = 1.41421 > > The real square root of a negative number is nonexistent. > phrase: {ph_cuberoot} cube root of (arithmetic value) ... value > > This phrase produces an approximate cube root, to the nearest integer, of the given value, which must be of a kind which has cube roots. Example: > > cube root of 27 = 3 > cube root of -27 = -3 > > (Warning: this is not very accurate if the Z-machine setting is used. For best performance, use Glulx.) We can compare numbers using either the traditional computer-programming symbols, or using words: if the score is less than 10 if the score < 10 and similarly for `greater than`, `at least` and `at most`, with the symbols `>`, `>=` and `<=`. But we are not allowed the equals sign: for that we need only use `is` – if the score is 10 ## Powers and logarithms ^^{calculation: rounding to the nearest whole number} ^^{calculation: logarithms} ^^{calculation: exponential functions} ^^{real numbers: exponential functions} ^^{numbers: real numbers: exponential functions} ^^{powers, of numbers}^^^{+to+(real number) to the power (real number) --> to the power} If the last section provided a basic office calculator, this section and the next provide the more exotic rows of buttons found on a scientific calculator. All of these are done using real number arithmetic. To start with some dull ones, here are two ways to round off numbers: > phrase: {ph_ceiling} ceiling of (real number) ... real number > > Produces the smallest integer value greater than or equal to the one given. Examples: > > ceiling of pi = 4.0 > ceiling of -16.315 = -16.0 > > (Note that the result is still a real number; it simply has no fractional part any more.) > phrase: {ph_floor} floor of (real number) ... real number > > Produces the largest integer value less than or equal to the one given. Examples: > > floor of pi = 3.0 > floor of -16.315 = -17.0 > > (Note that the result is still a real number; it simply has no fractional part any more.) Two more easy functions: > phrase: {ph_absolutevalue} absolute value of (real number) ... real number > > Removes the sign from a value, leaving positive numbers alone but making negative ones positive. Examples: > > absolute value of 62.1 = 62.1 > absolute value of 0 = 0.0 > absolute value of -62.1 = 62.1 > absolute value of minus infinity = plus infinity > phrase: {ph_reciprocal} reciprocal of (real number) ... real number > > Calculates 1/x, that is, divides up 1 into this many pieces. Examples: > > reciprocal of -2 = -0.5 > reciprocal of 0.1 = 10.0 > reciprocal of 7 = 0.14286 > reciprocal of plus infinity = 0.0 Now for taking powers. In general we have: > phrase: {ph_power} (real number) to the power (real number) ... real number > > Computes x to the power y. Examples: > > 2 to the power 4 = 16.0 > 100 to the power 0.5 = 10.0 > 7 to the power -1 = 0.14286 > pi to the power 0 = 1.0 > > In the words of the Glulx specification document (section 2.12), "the special cases are breathtaking": if you need to know exactly what, say, `minus infinity to the power Y` will do for different cases of Y, refer to the details of the ```pow``` opcode. To compute square roots, it's more efficient to use `real square root of X` function than `X to the power 0.5`, though both work. To obtain the Nth root of X, we might use: X to the power (reciprocal of N) being careful to use `reciprocal of N` rather than `1 divided by N` to make sure we're using real and not integer arithmetic. Similarly, the following is more efficient than `e to the power ...`, but equivalent to it: > phrase: {ph_exp} exponential of (real number) ... real number > > Computes e to the given power, where e is the base of natural logarithms. Examples: > > exponential of 0 = 1.0 > exponential of 1 = e = 2.7182818 > exponential of -10 = 4.53999 x 10^-5 > exponential of 10 = 22026.46484 > exponential of logarithm of 7.12 = 7.12 The reverse of taking powers is taking logarithms. > phrase: {ph_logarithmto} logarithm to base (number) of (real number) ... real number > > Finds what power the base would have to be raised to in order to get this value. Examples: > > logarithm to base 10 of 1000000 = 6.0 > logarithm to base 10 of 350 = 2.54407 > logarithm to base 2 of 256 = 8.0 > > Logarithms of zero or negative numbers are nonexistent. Note that `logarithm to base 10 of ...` is what most calculators call simply "log", but Inform doesn't: it uses "log" for natural logarithms. > phrase: {ph_logarithm} natural/-- logarithm of (real number) ... real number > > Finds what power e would have to be raised to in order to get this value. Examples: > > logarithm of e = 1.0 > logarithm of 1 = 0.0 > logarithm of 1000 = 6.90776 > logarithm of exponential of 7.12 = 7.12 > > Logarithms of zero or negative numbers are nonexistent. This is the function which most calculators label as "ln", for "log natural", but in mathematical and scientific papers it's more often written "log", and Inform follows that convention. ## Trigonometry ^^{calculation: trigonometric functions} ^^{real numbers: trigonometric functions} ^^{numbers: real numbers: trigonometric functions}^^^{+to+(real number) degrees --> degrees} We have twelve functions left to cover, though they are all closely related. > phrase: {ph_degrees} (real number) degrees ... real number > > Inform measures angles in radians, a convention in which the angle for a half circle is pi, and a right angle is pi divided by 2. This is better from a mathematical point of view, but in practice most people think about angles using degrees, where 180 degrees is a half-circle and a right angle is 90 degrees. This phrase helps with that by converting from degrees to radians: in other words, it multiplies by 0.0174532925, since that's roughly 1/180th of pi. Examples: > > sine of 90 degrees = 0.0 > cosine of 60 degrees = 0.5 > phrase: {ph_sine} sine of (real number) ... real number > > The length of the upright of a right-angled triangle with this angle and a hypotenuse of length 1, where angle is measured in radians. Examples: > > sine of 0 = 0 > sine of 45 degrees = 0.70711 > sine of (pi divided by 4) = 0.70711 > sine of (pi divided by 2) = 1.0 > sine of pi = 0 > phrase: {ph_cosine} cosine of (real number) ... real number > > The length of the base of a right-angled triangle with this angle and a hypotenuse of length 1, where angle is measured in radians. Examples: > > cosine of 0 = 1.0 > cosine of 45 degrees = 0.70711 > cosine of (pi divided by 4) = 0.70711 > cosine of (pi divided by 2) = 0.0 > cosine of pi = -1.0 > phrase: {ph_tangent} tangent of (real number) ... real number > > The ratio of the upright length to the base length in a right-angled triangle with this angle and a hypotenuse of length 1, where angle is measured in radians. Examples: > > tangent of 0 = 0.0 > tangent of 45 degrees = 1.0 > tangent of (pi divided by 4) = 1.0 > tangent of (pi divided by 2) = plus infinity > phrase: {ph_arcsine} arcsine of (real number) ... real number > > The inverse of the sine function. > phrase: {ph_arccosine} arccosine of (real number) ... real number > > The inverse of the cosine function. > phrase: {ph_arctangent} arctangent of (real number) ... real number > > The inverse of the tangent function. > phrase: {ph_hyperbolicsine} hyperbolic sine of (real number) ... real number > > The hyperbolic sine function, often written "sinh" but pronounced "shine". > phrase: {ph_hyperboliccosine} hyperbolic cosine of (real number) ... real number > > The hyperbolic cosine function, often written "cosh". > phrase: {ph_hyperbolictangent} hyperbolic tangent of (real number) ... real number > > The hyperbolic tangent function, often written "tanh". > phrase: {ph_hyperbolicarcsine} hyperbolic arcsine of (real number) ... real number > > The inverse of the hyperbolic sine function. > phrase: {ph_hyperbolicarccosine} hyperbolic arccosine of (real number) ... real number > > The inverse of the hyperbolic cosine function. > phrase: {ph_hyperbolicarctangent} hyperbolic arctangent of (real number) ... real number > > The inverse of the hyperbolic tangent function. ## Units {PM_LPNotKOV} {PM_LPBuiltInKOV} {PM_LPEnumeration} {PM_NegationInternal} {PM_NegationForbidden} ^^^{units of measure <-- numbers: units of measure <-- real numbers: units of measure} ^^{units of measure: defining} ^^{defining: units of measure} ^^{text substitutions: units of measure} ^^{units of measure: displaying} ^^{kinds: of values with units of measure} ^^{(spec) specifies (a unit)+assert+ --> specifies} ^^{type-checking: of units of measure} Suppose we want to talk about how tall people are. We could just create a `number` property, like this: A person has a number called height. But then we would have to write lines like `Isabella has height 68`, which nobody would naturally say. What we want is to be able to write `Isabella is 5 foot 8.` Perhaps the computer will need to store that measurement as the number 68 in some register or other, but we don't want to know about that. `5 foot 8` is a complicated notation in a way – it involves both feet and inches – so let's start with a simpler example: A weight is a kind of value. 10kg specifies a weight. This is a little different to the kinds of value seen so far, which were all created like so: A colour is a kind of value. The colours are red, green and blue. We can't mix the two styles: a new kind of value will either be numerical at heart (`10kg`) or verbal at heart (`blue`). The effect of `10kg specifies a weight` is to tell Inform that this is the notation for writing a constant `weight`. So, for instance, The maximum load is a weight that varies. The maximum load is 8000kg. if the maximum load is greater than 8000kg, ... Inform is then careful not to allow weights to be mixed up with other numerical values. For instance, it won't allow `if the maximum load is 400`, because 400 is a number, not a weight. More or less anything we can do with numbers, we can now do with weights. For instance, we can write: The Weighbridge is a room. "A sign declares that the maximum load is [maximum load]." ...which will produce the text ``A sign declares that the maximum load is 8000kg.`` Numerical kinds of value are sometimes called "units", because one of their main uses is to allow us to write quantities using scientific units such as kilograms. But they have other uses too. We have a great deal of freedom in creating notations like `10kg`, or `4 foot 10` – the main thing is that new notations must not already mean a value. So `10 specifies a weight` will not be allowed, because 10 specifies a number already. **By default we can only write whole-number values.** As we've seen, Inform can handle both integer (whole-number) and real arithmetic, and they each have their advantages. The default here is to use whole numbers, so 10 kg specifies a weight. will store only whole numbers of kilograms (unless clever scaling tricks are used: see the next section). That may be fine, but if we need to handle a wider range of weights, or do scientific calculations that need to be more accurate, this is better: 1.0 kg specifies a weight. Here Inform can see from the `.0` in the prototype number that real numbers will be involved. (It needs to be `.0` not, say, `.5` because that could be read as a different sort of notation.) We can still write `8000kg`, but we can now also write `1.9885 x 10^30 kg` (the mass of the Sun) or `9.109383 x 10^−31 kg` (the mass of an electron). On the other hand, any calculations we do will be limited in accuracy to about 6 to 9 decimal places, exactly as for real numbers. **By default we can only write positive values when whole numbers are used.** Sometimes it is unnatural to write negative values, and so Inform will issue a Problem message if this is tried – for instance, Inform would not allow us to write a weight of -4 kg. (This doesn't mean that arithmetic on units is forbidden to get a negative result: we may want to work out the difference between two weights. Inform's Problem message is simply to try to prevent the accidental writing of incorrect values.) If we do want the ability to write negative values in the source text, we signal that in the notation itself: -10 kg specifies a weight. That alerts Inform that both positive and negative values for this unit make sense. If we set up a spread of multiple notations (see the next section) then this is automatically enabled, because then we're clearly dealing with proper physics, where negative values are common; and similarly if we use real numbers (as above). ## Multiple notations {PM_DuplicateUnitSpec} ^^{units of measure: multiple notations for a unit} ^^{units of measure: defining} ^^{defining: units of measure} ^^{|scaled up / down by} ^^{plurals: of units of measure} Going back to our weight example: A weight is a kind of value. 10kg specifies a weight. The notation here is a single word, even if it contains digits as well as letters – `10kg`. But it doesn't have to be one word. These would have worked, too: 10kg net specifies a weight. 10 kg specifies a weight. In fact, we are allowed to have all three at once, as alternatives: A weight is a kind of value. 10kg specifies a weight. 10kg net specifies a weight. 10 kg specifies a weight. If we often have to deal with large weights, it becomes a little cumbersome to keep on writing something like `80000kg`. An engineer would write `80 tonnes` for this. Similarly, we wouldn't like road maps to use light years, or speed limit signs to use furlongs per fortnight. So it's sometimes useful to provide a spread of different notations, at different scale factors, for the same kind of value. Here's one way of setting up the tonne, that is, the metric ton: 1 tonne specifies a weight scaled up by 1000. This really is an alternative way to write the same thing: for instance, Inform will allow `25kg plus 3 tonne`, the result being `3.025 tonne`. That's all very well, but a value like "3 tonne" reads a little oddly, even if it's correct in theory. Outside of scientific journals with old-school copy editing, most people would write "3 tonnes", not "3 tonne". Here's a better try: 1 tonne (singular) specifies a weight scaled up by 1000. 2 tonnes (plural) specifies a weight scaled up by 1000. Now Inform will not only recognise both forms, but also use the right one when printing back. ## Scaling and equivalents {PM_LPCantScaleYet} {PM_LPCantScaleTwice} {PM_LPTooLittleAccuracy} ^^{units of measure: multiple notations for a unit} ^^{units of measure: defining} ^^{defining: units of measure} ^^{|scaled up / down by} ^^{|scaled at} ^^{equivalent to (unit)+sourcearg+} ^^{limits: of numeric values of units} ^^{numbers: limits of numeric values of units} ^^{Z-machine: numeric limits} ^^{Glulx: numeric limits} ^^{virtual machine: numeric limits} ^^{real numbers: limits of numeric values of units} As we've seen, there are two ways to store values like lengths or weights: as whole numbers, or as real numbers. If we prefer to use whole numbers, or if real numbers aren't available (for example if we're using the Z-machine setting), then we might run into an awkward problem: when we write 1 kg specifies a weight. we make this correspond to the whole number `1`, and that means Inform can never handle weights smaller than `1 kg`. But as we've seen, we can provide differently scaled notations for the same unit: A length is a kind of value. 1m specifies a length. 1km specifies a length scaled up by 1000. And this allows us to write `0.45km` instead of `450m`, if we want to, both having the same effect. `0.45km` doesn't make a real number, despite the decimal point – it's simply another way to write `450m`, stored internally as the whole number 450. Just as we can scale up, so we can also scale down: 1cm specifies a length scaled down by 100. Now we have a spread of three notations, so `3cm`, `0.03m` and `0.00003km` all mean the same thing. But something quite interesting happened at the same time: Inform realised that we want to know lengths to a greater accuracy than just a whole number of meters. If we're using whole numbers, and we want to resolve down to very small values, that reduces the size of the largest value we can have. For instance, with the Glulx format setting, writing just A length is a kind of value. 1m specifies a length. gives us a range of 1m up to 2147483647m, which is plenty – it's about six times the distance from the Earth to the Moon. Going down to centimeters: A length is a kind of value. 1m specifies a length. 1cm specifies a length scaled down by 100. gives us instead 1cm up to 21474836.47m, which is still enough to represent any possible distance on the Earth's surface. For instance, London to Sydney is about 17000000m. Left to itself, Inform chooses the scaling for a unit so that it can represent exactly 1 of the smallest notation – so in our example Inform resolves down to 0.01m, not 1m, in order that it can represent 1cm accurately. But we can also fix the scaling ourselves: A length is a kind of value. 1m specifies a length scaled at 10000. Notice `scaled at`, not `scaled down` or `scaled up` – this is now the first notation for length, so there's no existing notation which it could scale up or down. Anyway, now the range is 0.0001m, the width of a human hair, up to 214748.3647m, which is about 130 miles. (The Kinds index automatically keeps track of the range of values represented exactly.) The `scaled at` feature is meaningless if we're using real numbers, so it throws a Problem message. Finally, for a really deluxe kind of value, we can also provide `equivalent` notations. The idea here is that we might want both miles and kilometers to work, even though they aren't direct scalings of each other. We can only do this approximately, but: 1 mile specifies a length equivalent to 1609m. Equivalent notations are never normally used in printing values back (but see the next section) – we wouldn't want Inform to print a sequence of values such as ``1.6km``, ``1.65km``, ``1.056 miles``, ... in an effort to be helpful. ## Named notations ^^{text substitutions: units of measure} ^^{units of measure: displaying} ^^{units of measure: multiple notations for a unit} When it has a variety of notations to choose from, Inform will normally use the neatest one given the size of the value it is printing. Suppose we've set up `weight`, with three notations: A weight is a kind of value. 10kg specifies a weight. 1 tonne (singular) specifies a weight scaled up by 1000. 2 tonnes (plural) specifies a weight scaled up by 1000. Inform will then print back values like so: - `45kg` -> ``45kg`` - `1000kg` -> ``1 tonne`` - `2500kg` -> ``2.5 tonnes`` - `80000kg` -> ``80 tonnes`` Note the way Inform goes into decimal places in order to talk about 2500kg in terms of tonnes rather than kilograms – it is minimising the integer part of the unit, but trying to keep it non-zero. So Inform prefers ``45kg`` to ``0.045 tonnes``. Although Inform's habit of choosing the best notation available is usually just what we want, we sometimes want to make the choice ourselves. For instance, if we were printing out a table of different weights, we might want to give all of them in kilograms, whatever their size. In that case we can, if we want, give names to our different notations: 1 tonne (singular, in tonnes) specifies a weight scaled up by 1000. 2 tonnes (plural, in tonnes) specifies a weight scaled up by 1000. Now we could write, for instance: "The weighbridge warns you not to exceed [the maximum load in tonnes]." And the figure will always use tonnes now, even if Inform would normally think it odd: ``The weighbridge warns you not to exceed 0.001 tonnes.`` But it will still correctly use ``tonne`` or ``tonnes`` as appropriate – what has changed is that instead of choosing from all of the weight notations, Inform now chooses from the notations labelled as ``in tonnes``. ## Making the verb "to weigh" ^^{properties: defining sentence verbs for properties} ^^{defining: sentence verbs for properties} ^^{the verb (V) means (property)+assert+ --> verb means} ^^{(means), defining sentence verbs+sourcepart+: the verb (V) means (property)+assert+} ^^{sentence verbs: defining for properties} ^^{adjectives: for numeric quantities with units} ^^{defining: adjectives: for numeric quantities with units} ^^{comparisons: of numbers with units using adjectives} ^^{superlatives: of numbers with units using adjectives} ^^{properties: numeric comparatives, adjectives for} ^^{value properties: numeric comparatives, adjectives for} ^^{properties: numeric superlatives, adjectives for} ^^{value properties: numeric superlatives, adjectives for} So now we can invent notations for weight. We could, for instance, write: Weight is a kind of value. 1kg specifies a weight. Every thing has a weight. And that allows us to write: The lead pig is in the Salt Mine. The weight of the lead pig is 45kg. But nobody would say it that way: they'd say "The lead pig weighs 45kg." So what we really need to complete our setup is a verb `to weigh`. We have already created new verbs, but none of those methods are quite convenient for this. We want to relate something tangible (the lead pig) to something intangible (45kg), and there's no convenient relation to express this; if we set it up as a condition, we'd get something we couldn't assert, only test. Instead, we'll do something different this time: The verb to weigh means the weight property. Previous definitions like this ended `means the ... relation`, rather than `means the ... property`, but the idea is the same. The meaning of `X weighs Y` is that the weight property of X is equal to Y. So we can now write: A thing usually weighs 1kg. The lead pig weighs 45kg. something weighing 20kg if three things weigh 5kg, ... And as we saw in the chapter on [Descriptions], we can also set up adjectives, comparatives and superlatives: Definition: A thing is heavy if its weight is 20kg or more. which creates `heavy`, `heavier` and `heaviest`. ## The Metric Units extension ^^{units of measure: Metric Units+ext+} ^^{Metric Units+ext+} ^^{extensions: specific extensions: Metric Units} ^^{Approximate Metric Units+ext+} ^^{extensions: specific extensions: Approximate Metric Units} To sum all of this up, what started out as a simple business of setting a notation for lengths becomes something quite elaborate when we try to match the actual notations used by scientists and engineers. It's all optional, of course, but as we want more and more of this, we might find ourselves with a spread of notations like this: > 1mm ... 1cm ... 1m ... 1km In addition we might want equivalents for the inch, the yard and the mile; and verbal forms like the meter and the millimeter, and then alternate spellings like the kilometre; and then both singular and plural forms. And that's just length – what about density, area, pressure, velocity and a dozen other physical quantities? After a while these declarations start to look as vastly fussy as a box of presentation cutlery. Fortunately the whole set is indeed available in a presentation box, and at no extra charge. (a) The extension `Metric Units by Graham Nelson` sets up a whole range of scientific units, with all the notations we are likely to want. Real numbers are used throughout, so large and small-scale calculations can be carried out quite accurately. Like the other built-in extensions, it has its own documentation and examples. (b) The extension `Approximate Metric Units by Graham Nelson` does the same but using whole numbers, scaled about right for human situations. This won't be much use for extensive calculations, and won't be as accurate, but it will work reasonably well if real arithmetic isn't available. ## Totals {PM_TotalEitherOr} {PM_TotalTableColumn} ^^{units of measure: totals} ^^{units of measure: averages} ^^{calculation: total of a numeric property} ^^{calculation: average of a numeric property} This chapter began by mentioning arithmetic, and then went on a long diversion to create scientific units, everyday weights and measures, and other notational conveniences. Putting all of that together, it's time now to calculate something with all of these numerical quantities. Suppose we invent the idea of weight, and give everything a weight of its own. Most items will have a nominal weight of 1kg, but people will be heavier. Going on actuarial tables, we might say: A weight is a kind of value. 10kg specifies a weight. Everything has a weight. A thing usually has weight 1kg. A man usually has weight 80kg. A woman usually has weight 67kg. Definition: A thing is light if its weight is 3kg or less. Definition: A thing is heavy if its weight is 10kg or more. and this provides us with `lighter`, `lightest`, `heavier` and `heaviest` as before. Now we could say `if Peter is heavier than Paul`, or even `if Peter is heavier than 75kg`, and so forth. We need one more tool: > phrase: {ph_total} total (arithmetic values valued property) of (description of values) ... value > > This phrase produces the total of some property held by all of the values matching the description. A problem message is produced if the values in question can't have that property (`the total carrying capacity of scenes`), or if it holds a kind of value which can't meaningfully be added up (`the total description of open doors`). Example: > > total carrying capacity of people in the Deep Pool That gives us everything we need for a working balance platform: The balance platform is a supporter in the Weighbridge. "The balance platform is currently weighing [the list of things on the platform]. The scale alongside reads: [total weight of things on the platform]." Note that this only works because we said that `everything has a weight`: otherwise it would make no sense to add up the weights of things. This enables us to get the average weight of a group of things, too: the total weight of things on the platform divided by the number of things on the platform But we should be careful that this does not accidentally divide by zero, which it will if the platform has nothing on it! As well as the average, we could find the maximum and minimum weights: the weight of the heaviest thing on the platform the weight of the lightest thing on the platform We should remember that `the heaviest thing on the platform` may be ambiguous, because there may be several equally heavy things there. That means if the lead pig is the heaviest thing on the platform will only reliably work if there is no possibility of a tie. A safer bet is: if the lead pig is the weight of the heaviest thing on the platform ## Equations {EQUATIONS} {PM_EquationMisnumbered} {PM_EquationMisnamed} {PM_EquationSymbolMisdeclared} {PM_EquationSymbolMalformed} {PM_EquationSymbolVague} {PM_EquationSymbolNonValue} {PM_EquationSymbolEqualsKOV} {PM_EquationSymbolNonNumeric} {PM_EquationSymbolBadSub} {PM_EquationSymbolSpurious} {PM_EquationTokenUnrecognised} {PM_EquationLeadingZero} {PM_EquationOperatorUnrecognised} {PM_EquationTooComplex} {PM_EquationMispunctuated} {PM_EquationDoesntEquate} {PM_EquationEquatesBadly} {PM_EquationEquatesMultiply} {PM_EquationIncomparable} {PM_EquationDimensionPower} {PM_EquationBadArithmetic} {PM_EquationBadTarget} {PM_EquationInsoluble} {PM_EquationSymbolMissing} {PM_EquationSymbolWrongKOV} ^^{equations, for values with units} ^^{defining: equations for values with units} ^^{numbers: given by equations} ^^{real numbers: given by equations} ^^{calculation: given by equations} ^^{(given), in calculations with equations+sourcepart+} ^^{units of measure: Metric Units+ext+} ^^{Metric Units+ext+} ^^{extensions: specific extensions: Metric Units} ^^{punctuation: brackets: for implicit multiplication} ^^{|( ): for implicit multiplication} Forming totals is all very interesting in its way, but it's book-keeping rather than physics. As a glance at any school science textbook shows, the way to apply physics is to work out an unknown quantity – say, the time taken for a dropped ball to hit the ground – by combining known quantities into an equation – the height it is dropped from, and the strength of gravity. It's a convention centuries old now that textbooks and research papers never describe these equations in running text. Even for simple formulae, we like to write "F=ma", not "let the force be the mass times the acceleration". And the standard way to print this is to break off and display an equation, not to squeeze it into the text as if it were ordinary verbiage. Just as Inform's Tables imitate those in printed books (see the next chapter, [Tables]), so its Equations do. In this section, we'll use a combination of three equations to work out how soon and how hard an object pushed off a table will hit the floor. First, we'll include Metric Units, to define all of the kinds of value and notations we need. {*}Include Metric Units by Graham Nelson. Now we'll give everything a mass (Metric Units likes to talk about mass instead of weight, but on Earth it's the same thing) and also set up a typical strength for gravity – it's a little less at the poles, a little more at the equator, but this is the conventional approximate value to use. {**}The acceleration due to gravity is an acceleration that varies. The acceleration due to gravity is usually 9.807 m/ss. A thing has a mass. The mass of a thing is usually 10g. To a Renaissance scientist, typically living in a walled European town, a cannon ball was a familiar thing, and it often featured in imaginary experiments: {**}Laboratory is a room. The cannon ball is in the Laboratory. "A cannon ball perches delicately on a lab bench." The mass of the cannon ball is 2kg. And now we're ready for the three equations. These will all have names, but we could just as easily have numbered them, calling them (say) `Equation 1`, `Equation 2` and `Equation 3`. {**}Equation - Newton's Second Law F=ma where F is a force, m is a mass, a is an acceleration. Equation - Principle of Conservation of Energy mgh = mv^2/2 where m is a mass, h is a length, v is a velocity, and g is the acceleration due to gravity. Equation - Galilean Equation for a Falling Body v = gt where g is the acceleration due to gravity, v is a velocity, and t is an elapsed time. An equation has to take the form of one formula equals another, where each formula is made up from symbols defined afterwards. The symbols can be defined as definite values (as `g` is defined in the Galilean Equation), or just by telling Inform their kinds of value (as `v` and `t` are defined). Equations are read using standard mathematical conventions. So `x + yz` means that we multiply y and z, then add that to x; `ab/cd` divides the product of a and b by the product of c and d. Multiplication signs can be omitted, just as science books normally do (though we can always write them if we want to, using the asterisk \*, as usual in computing). The need for brackets is minimised, with any luck, but we can use them if we need to: `x(y+ab)` is legal, for instance. One difference between Inform's conventions and mathematical ones, though, is that Inform generally ignores upper-versus-lower-case when reading variable names, so it wouldn't be a good idea to write `F = gMm/r^2` and expect `M` and `m` to be different from each other. Here is the calculation: {**}Instead of pushing the cannon ball: let the falling body be the cannon ball; let m be the mass of the falling body; let h be 1.2m; let F be given by Newton's Second Law where a is the acceleration due to gravity; let v be given by the Principle of Conservation of Energy; let t be given by the Galilean Equation for a Falling Body; say "You push [the falling body] off the bench, at a height of [h], and, subject to a downward force of [F], it falls. [t to the nearest 0.01s] later, this mass of [m] hits the floor at [v]."; now the falling body is in the location. And the result is: You push the cannon ball off the bench, at a height of 1.2m, and, subject to a downward force of 19.614N, it falls. 0.49s later, this mass of 2.0kg hits the floor at 4.85147 m/s. Not all that fast-moving – it's only about 10 mph, ten times slower than one fired by a Renaissance cannon – but half a second wouldn't give you long to get your foot out of the way. How was that done? The crucial lines are the ones in the form `let X be given by E...`, which is a new form of `let`. > phrase: {ph_letequation} let (a name not so far used) be given by (equation name) & let (a temporary named value) be given by (equation name) > > This phrase creates a new temporary variable, starting it with the value found by solving the given equation. The variable lasts only for the present block of phrases, which certainly means that it lasts only for the current rule. Example: > > let F be given by Newton's Second Law where a is the acceleration due to gravity; > > There is also a more compact syntax, giving the equation explicitly: > > let KE be given by KE = mv^2/2 where KE is an energy; When we solve with `let`, then, all of the other symbols should either already have values (because they exist as `let` values already made) or else be specified in the line. For instance, let F be given by Newton's Second Law where a is the acceleration due to gravity; is allowed because `F` is one of the symbols in `F = ma`; of the other two symbols, we have a `let` variable called `m` already – it's the mass of the cannon ball – and we declare exactly what `a` is. The next calculation is more interesting: let v be given by the Principle of Conservation of Energy; Since the equation here is `mgh = mv^2/2`, Inform has to do some algebra to work out `v` in terms of the other unknowns – it's the square root of 2gh, but we don't need to work that out. Inform can't always solve implicit equations – for instance, it can't deduce `m` from this equation – but it's correct on all the easy cases which occur in basic physics, and that enables us to write equations in their most natural form, which is easier to read and understand. The advantage of setting out an equation formally is that it can be used in many places – we could use Newton's Second Law again for something quite different, for example. But it's a little cumbersome for something simple which we only need once, so this is neater: let KE be given by KE = mv^2/2 where KE is an energy; Here the equation is written out explicitly instead of being named, but otherwise everything works in the same way. Equations can also contain many of our standard functions, which are written for this purpose with their standard mathematical abbreviations. For example: let x be given by sin x = 1 where x is a real number; works out x as pi divided by 4, which is to say, 90 degrees. The Phrasebook entries on the mathematical functions give their abbreviations, but here they all are as a list: abs, root, ceiling, floor, int, log, exp, sin, cos, tan, arcsin, arccos, arctan, sinh, cosh, tanh, arcsinh, arccosh, arctanh As an example, here's the definition of arcsinh given in the Standard Rules: To decide which real number is the hyperbolic arcsine of (R - a real number): let x be given by x = log(R + root(R^2 + 1)) where x is a real number; decide on x. Something to be a little cautious of: brackets are used in equations to group terms together, and do not mean function application, as they would in a C-like programming language. For example, `sin(1+x)/2` takes the sine of `(1+x)/2`: if we want to halve the sine of `1+x`, we have to write `(sin(1+x))/2`. ## Arithmetic with units ^^{units of measure: arithmetic} ^^{calculation: arithmetic with units} ^^{type-checking: of units of measure} The example equations in the previous section carried out quite a lot of arithmetic, but they may have given the impression that Inform always allows arithmetic – which is not true. This is actually a good thing, because it keeps us from error. For instance, Inform will not allow: Equation - Newton's Totally Bogus Law F = m^2 where F is a force, m is a mass. because whatever you get when you square a mass, you don't get a force – in the same way that a length times another length makes an area, not another length. Physicists call this "dimensional analysis", and it often provides clues about which equations are right. Just after the Second World War, someone correctly worked out the explosive power of an atomic bomb without any classified information simply by guessing what values would appear in the formula, and then finding the simplest equation they could appear in. In general, Inform will not allow numerical kinds of value to be multiplied or divided by each other (or square or cube rooted) unless we give it instructions that this would make sense. Of course, there's plenty we can still do without any need for such instructions. For instance, going back to weight, {*}The Weighbridge is a room. "A sign declares that the maximum load is [100kg multiplied by 3]." ...will produce the text ``A sign declares that the maximum load is 300kg.`` Here Inform knows that it makes sense to multiply a weight by 3, and that the result will be a weight. Similarly, Inform allows us to add and subtract weights, and several different forms of division are allowed: {*}The blackboard is in the Weighbridge. "A blackboard propped against one wall reads: '122 / 10 is [122 divided by 10] remainder [remainder after dividing 122 by 10]; but 122kg / 10kg is [122kg divided by 10kg] remainder [remainder after dividing 122kg by 10kg]; and 122kg / 10 is [122kg divided by 10] remainder [remainder after dividing 122kg by 10].'" When we visit the Weighbridge, we find: ``` transcript A blackboard propped against one wall reads: "122 / 10 is 12 remainder 2; but 122kg / 10kg is 12 remainder 2kg; and 122kg / 10 is 12kg remainder 2kg." ``` Whereas we are not allowed to divide 122 by 10kg: that would make no sense, since 122 is a number and not made up of kilograms. Inform will produce a problem message if we try. Similarly, Inform won't normally allow us to multiply two weights together – but see the next section. ## Multiplication and subtraction of units {PM_DimensionRedundant} {PM_DimensionNotBaseKOV} {PM_NonDimensional} {PM_UnitSequenceOverflow} {PM_DimensionsInconsistent} {PM_BadLPEquivalent} {PM_BadLPOffset} {PM_MultiplyingNonKOVs} {PM_BadArithmetic} {ARITHMETIC} ^^{units of measure: multiplication of units} ^^{units of measure: subtraction of units} ^^{units of measure: relative units} ^^{calculation: arithmetic with units} ^^{type-checking: of units of measure} ^^{units of measure: Metric Units+ext+} ^^{Metric Units+ext+} ^^{extensions: specific extensions: Metric Units} To recap, then, it is forbidden to multiply 122kg and 10kg, not because it could never make sense (a scientist might occasionally multiply two weights) but because the result is – what? Not a number, and not a weight any more. But we are allowed to tell Inform what the result ought to be, and once we have done so, the multiplication will be allowed: {*}A length is a kind of value. 10m specifies a length. An area is a kind of value. 10 sq m specifies an area. A length times a length specifies an area. The balance platform is in the Weighbridge. "The balance platform is 10m by 8m, giving it an area of [10m multiplied by 8m]." which will turn up as: The balance platform is 10m by 8m, giving it an area of 80 sq m. And having told Inform that lengths multiply to area, we could also divide an area by a length to get a length: no further instructions would be needed. The `Metric Units by Graham Nelson` extension includes all of the standard ways that physical quantities are multiplied, and a good way to see these is to try out one of the Metric Units examples and look at the Kinds index, which includes a table showing how all of this works. An alternative way to set things up is for one kind to represent values along some scale, but where arithmetic as such doesn't entirely make sense, and then a _second_ kind to represent relative values on that scale, where it does. The classic example of this is that it makes no good sense to talk about, say, doubling `2:15 PM`, or dividing it by `1:00 AM`, but where time differences do make sense. The Standard Rules therefore includes the sentence: A time minus a time specifies a time period. And this establishes that, for example, ``` transcript "4:31 pm minus 11:20 am" = time period: 5 hours 11 minutes "5:12 pm to the nearest 20 minutes" = time: 5:20 pm "4:31 pm plus 75 minutes" = time: 5:46 pm "5 minutes plus 6 minutes" = time period: 11 minutes "2 times 10 minutes" = time period: 20 minutes "20 minutes divided by 4 minutes" = number: 5 ``` # Advanced Notations ## Notations with multiple parts {PM_LPWithoutElement} {PM_LPElementTooLarge} {PM_LPTooManyElements} {PM_LPTooComplicated} {PM_LPNotAllNamed} ^^{units of measure: with multiple numeric components} ^^{units of measure: defining} ^^{defining: units of measure with parts} ^^{limits: of numeric values of units} ^^{numbers: limits of numeric values of units} ^^{Z-machine: numeric limits} ^^{Glulx: numeric limits} ^^{virtual machine: numeric limits} ^^{real numbers: limits of numeric values of units} ^^{punctuation: quotation marks: not usable in unit notations} ^^{|": not usable in unit notations} ^^{units of measure: understanding} ^^{understanding: numbers with units} ^^{numbers: hexadecimal and other bases: in units of measure} The chapter on [Quantities and Equations] featured many variations on specifications like this one: A weight is a kind of value. 1.0 kg specifies a weight. Such weights and measures were all ways to give _single_ values a new notation and significance. `12.5 kg` is not the same thing as `12.5` because it's not just an abstract number, it is a weight. All the same, the `weight` kind is really just a nice way to dress up what is basically a `real number` by giving it a particular purpose or meaning. In this chapter, we go into notations which combine _multiple_ values together. Natural language does quite a lot, using mixtures of numbers with wording or punctuation to divide them. For instance, the running time of a piece of music is easier to follow in minutes and seconds than in seconds alone: old-fashioned LP sleeves used to quote running times in the form 4'33. A running time is a kind of value. 3'59 specifies a running time. The choice of `3` here makes no difference, much as the choice of `10` in the weight examples was arbitrary. But the `59` is significant. Numbers after the first one are expected to range from 0 up to the value we quote – so in this case, the number of seconds can be anything from 0 to 59. Or, for instance: A height is a kind of value. 5 foot 11 specifies a height. Once again, kinds like `running time` and `height` can be written as constants: let the clearance be 12 foot 6; let Einstein On The Beach without an interval be 280'20; And they can be said: say "I hope this truck will fit under a [clearance] bridge. [clearance plus 1 foot 4] to be on the safe side."; say "Oh my, this opera runs [Einstein On The Beach without an interval]."; And even understood in typed commands by the player: Height guessing is an action applying to one thing and one height. Understand "guess [someone] is [height]" as height guessing. See the example [America Stands Tall] for a full working-out of this. The different number-like segments of a notation are called its _parts_. In the notation `1.0 kg`, there is just one part, but there are two in each of `3'59` and `5 foot 11`. In principle there can be as many as eight parts, though there are some practical limitations due to Inform's need to store the result efficiently during play. In practice, it's rare to need more than four. In notations like this, only the first-appearing number part is allowed to be negative, and then only if it was declared with a minus sign: A secret sign is a kind of value. -2x17 specifies a secret sign with parts mystery and enigma. Note that the parts of a notation can optionally be given names, and that's what was done here. The `mystery` part can be negative, but not the `enigma` part. Notations must not contain double-quotation marks because, even though people did once use these to denote minutes of arc, they would simply confuse programs like Inform's user interface which have to keep track of what is quoted text and what is not. But other punctuation marks are fine *provided they occur between two digits*. For instance, in A monetary value is a kind of value. $1.99 specifies a monetary value. the full stop between the 1 and the 99 is not interpreted as a division of two sentences; and similarly for colons in examples such as An aspect ratio is a kind of value. 16:9 specifies an aspect ratio. It is also possible to specify a number base to use: CSS colour is a kind of value. #FF_FF_FF specifies a CSS colour in hexadecimal. The base can be `in binary`, `in octal`, `in decimal`, `in hexadecimal` or `in base B` for any value of `B` from 2 to 36. Note that when looking for "parts" in the specification, Inform then looks for digits of that number base. Hexadecimal numbers use the sixteen digits `0`, `1`, ..., `9`, `A`, `B`, `C`, `D`, `E`, `F`, and therefore `FF` is a two-digit number. So Inform reads the notation `#FF_FF_FF` as having three number parts. ### See Also - [Numbers, ranges, overflows, and number bases] for dealing with regular `number` values in number bases other than 10. ## The parts of a notation {PM_LPFirstOptional} {PM_LPMultipleOptional} {PM_BadLPPartOption} {PM_BadLPNameOption} ^^{units of measure: with multiple numeric components} ^^{units of measure: defining} ^^{defining: units of measure with parts} ^^{text substitutions: units of measure} ^^{units of measure: displaying} ^^{(optional), when defining units+sourcepart+} ^^{(preamble optional), when defining units+sourcepart+} ^^{(with / without leading zeros), when defining units+sourcepart+} ^^{(leading zeros), when defining units+sourcepart+} ^^{(part of), for units with multiple components+sourcepart+} ^^{numbers: hexadecimal and other bases: in units of measure} ^^{units of measure: defining: with parts of a kind of value} ^^{|corresponding to: in defining units of measure} ^^{kinds: of value: in defining units of measure} If a value has been constructed out of multiple parts, we will sometimes want to extract those parts. For instance, suppose we want to know the dollars part of `$1.99`? We can do this provided the parts have names: A monetary value is a kind of value. $1.99 specifies a monetary value with parts dollars and cents. We can now find the relevant parts like so. Suppose that `sum` is a monetary value. Then: dollars part of sum cents part of sum are both numbers, so for instance we can say "Looks like around [dollars part of sum in words] dollar[s]." We can also go the other way: monetary value with dollars part 4 cents part 72 produces the monetary value `$4.72`. (Note the lack of commas or `and`s, and that the parts have to be given in the right order.) This is really intended to be useful when we manipulate such values in unusual ways: An aspect ratio is a kind of value. 16:20 specifies an aspect ratio with parts width and height. To decide which aspect ratio is the wider version of (AR - an aspect ratio): let W be the width part of AR multiplied by 2; let H be the height part of AR; let the wider ratio be the aspect ratio with width part W height part H; decide on the wider ratio. Naming the parts is also very useful when we want to apply _options_ to them, which go in brackets after their names. For example: An American map reference is a kind of value. 50° N 100° W specifies an American map reference with parts latitude (7 to 85) and longitude (20 to 179). Here, the two parts are called `latitude` and `longitude`. The option `7 to 85` applied to `latitude` constrains it to lie in that range: so `6° N 100° W` would not be a valid `American map reference`, because 6 is not in the range 7 to 85 inclusive. (For more on this, see [Range and number base of notation parts].) A part can have multiple options, in which case they are listed with commas in between, or none. There's quite a range of these, and some will take a little explaining. Option | Summary | Documentation ------ | ------- | ------------- `optional` | set to 0 if omitted | see [Optional notation parts] `preamble optional` | allow preamble text to be omitted too | see [Optional notation parts] `with leading zeros` | write with zeros up front to pad out the digits | see [Range and number base of notation parts] `without leading zeros` | or not | see [Range and number base of notation parts] `in binary` | write in base 2 | see [Range and number base of notation parts] `in octal` | write in base 8 | see [Range and number base of notation parts] `in decimal` | write in base 10 | see [Range and number base of notation parts] `in hexadecimal` | write in base 16 | see [Range and number base of notation parts] `in base B` | write in base `B`, which must be 2 to 36 | see [Range and number base of notation parts] `N to M` | fix this part to lie in the range `N` to `M` inclusive | see [Range and number base of notation parts] `D digits` | require this to have exactly `D` digits, with leading zeros | see [Range and number base of notation parts] `D BASE digit/digits` | ditto, but in the given number base | see [Range and number base of notation parts] `up to D digit/digits` | require this to have up to `D` digits | see [Range and number base of notation parts] `up to D BASE digit/digits` | ditto, but in the given number base | see [Range and number base of notation parts] `digits "TEXT"` | use these special digit characters | see [Unusual digits] `values "TEXT"` | use these special values | see [Parts which do not look like numbers] `corresponding to KIND` | make this part a `KIND` | see [Parts corresponding to kinds] Most of the time none of these options need to be set, because they are all automatically set to something sensible. For example: $1.99 specifies a monetary value with parts dollars and cents. is equivalent to: $1.99 specifies a monetary value with parts dollars (without leading zeros, in decimal, digits "0123456789") and cents (0 to 99, with leading zeros, in decimal, digits "0123456789"). ## Optional notation parts ^^{units of measure: with multiple numeric components} ^^{units of measure: defining: with optional parts} ^^{defining: units of measure with parts: with multiple numeric components} ^^{defining: units of measure with parts: with optional parts} ^^{(optional), when defining units+sourcepart+} ^^{(preamble optional), when defining units+sourcepart+} If a part of a notation is specified as `optional` then it can be missed out, and the result will be as if 0 had been given. For example, if we want the pre-Euro currency of France: French monetary value is a kind of value. 4F99 specifies a French monetary value with parts francs and centimes (optional). This allows both `12F50` and `14F` to be valid; `14F` is exactly like typing `14F00`. Both forms will be understood correctly in typed commands. Inform will take the hint and prefer the shorter form when printing them back. `preamble optional` further allows the non-numeric "preamble" to this part to omitted as well. For example: A monetary value is a kind of value. $1.99 specifies a monetary value with parts dollars and cents (optional, preamble optional). This declares not only that the `cents` part is optional – it will be 0 if not specified – but also that if it is omitted, the `.` should be left out as well. Thus `$3` is now valid and equivalent to `$3.00`: indeed, it will be the preferred form when Inform prints out a monetary value which is an exact number of dollars. ## Range and number base of notation parts ^^{units of measure: defining: with other bases} ^^{defining: units of measure with parts: with other bases} ^^{numbers: hexadecimal and other bases: in units of measure} ^^{(with / without leading zeros), when defining units+sourcepart+} ^^{(leading zeros), when defining units+sourcepart+} The _range_ of a part is the set of values it can hold. For example: $1.99 specifies a monetary value with parts dollars and cents. The `dollars` part can be 0, 1, 2, ... with no upper limit (except what will fit in the storage available for the data), but `cents` has the narrower range 0 to 99 inclusive. In this notation, `$2.09` is legal but `$02.09` and `$2.9` are not. This is because the `cents` part has to be written with leading zeros so that it occupies exactly two digits. By default, the first part of a notation appears without leading zeros, and all subsequent parts with, but this is controllable. For example: An aspect ratio is a kind of value. 16:20 specifies an aspect ratio with parts width and height (without leading zeros). This ensures that `4:3` is a legal `aspect ratio`, and that `4:03` is not. The option `with leading zeros` is also provided, for completeness. The option `N to M` overrides the default range for a part. The default is for the range to be unlimited on the first part and to be 0 up to whatever number is used to write the part, for the subsequent ones. In the `$1.99` notation, therefore, the `dollars` part is unlimited, but the `cents` part is `0 to 99`. `N` is required to be a whole number which is at least 0, and `M` is required to be a whole number which is greater than `N`. For example: An American map reference is a kind of value. 50° N 100° W specifies an American map reference with parts latitude (7 to 85) and longitude (20 to 179). Note that with these options set, the `50` and `100` in the specification become unimportant — they are just example values now. An alternative way to give the range is to write `D digits` or `up to D digits`. These are really just convenient synonyms for options we already have. `up to 4 digits` is the same thing as `0 to 9999`, while `4 digits` is the same thing as `0 to 9999, with leading zeros`, so that the possible values are `0000` to `9999`. If a part uses both ways to give a range, e.g., `0 to 39, 2 digits`, then the explicit range, in this case 0 to 39, wins out. An impossible combination such as `0 to 199, 2 digits` is rejected with a problem message. The _number base_ of a part is ordinarily 10, that is, it is written in decimal. This can be set with the options `in binary`, `in octal`, `in decimal`, `in hexadecimal` or `in base B`, where `B` can be anything from 2 to 36. Note that only one part is affected: see [Notations with multiple parts] for how to set a number base for all the parts at once. If the base is greater than 10 then digits 10 to 35 are recognised as either `a` to `z` or `A` to `Z`, but print back as `A` to `Z`. So `2af` and `2AF` are both valid hexadecimal numbers to Inform, and are equal, but would be printed back as ``2AF``. And we can combine the range and number base settings with the options `D BASE digit/digits` and `up to D BASE digit/digits`. For example: A DIP switch setting is a kind of value. __ specifies a DIP switch setting with parts bitmap (5 binary digits). is equivalent to: A DIP switch setting is a kind of value. __ specifies a DIP switch setting with parts bitmap (in binary, 0 to 31, with leading zeros). and means that, for example, `_01101_` is a valid `DIP switch setting`. ## Angle-bracketed part names ^^{units of measure: defining: with named parts} ^^{defining: units of measure with parts: with named parts} ^^{(< >), for defining parts of units of measure+sourcepart+} ^^{punctuation: angle brackets, for defining parts of units of measure} ^^{punctuation: quotation marks: not usable in unit notations} ^^{|": not usable in unit notations} In all the notations so far, the "parts" have been written in something resembling numerical form. For example: An American map reference is a kind of value. 50° N 100° W specifies an American map reference with parts latitude (7 to 85) and longitude (20 to 179). (Let's not argue about Semisopochnoi Island and other outliers.) But this could also be written like so: An American map reference is a kind of value. ° N ° W specifies an American map reference with parts latitude (7 to 85) and longitude (20 to 179). This specification `° N ° W` contains two parts, and Inform then requires the rest of the sentence to explain what they are. Angle brackets must _either_ contain a double-quoted piece of text to be taken literally, _or_ the name of one of the parts. For example: An agent is a kind of value. <"00">7 specifies an agent. allows constants like `007` and `0011` to be used and printed back, with the double-0 prefix having no numerical meaning but signalling that this is an agent, not a number. This makes it impossible to have a literal `"` character in a specification, but those are impossible for Inform to read anyway because they would be mistaken for text, so this is no loss. How about literal angle brackets, though? Suppose we want values to look like `<1101>`, `<1102>`, ...; we cannot write A hotel room number is a kind of value. <1109> specifies a hotel room number. ...because the `<` and `>` signs on either side of the `1109` lead Inform to think that what's between them will be the name of a part. Inform then complains, reasonably enough from its point of view, that `1109` _isn't_ the name of a part. Instead: A hotel room number is a kind of value. <"<">1109<">"> specifies a hotel room number. This works nicely, because `<"<">` means "match a literal `<`". And then, say, `showme <1109>` replies: hotel room number: <1109> In other words, that cumbersome escaping needed to be done only when specifying the notation, not when using it. Similarly: A monetary value is a kind of value. $< "." > specifies a monetary value with parts dollars and cents (2 digits, optional, preamble optional). Putting the full stop in quotation marks here prevents Inform from thinking that one sentence has ended and another one has begun; note the little spacing around this to ensure that Inform doesn't misread this. `showme $2.14` and `showme $31` then reply: monetary value: $2.14 monetary value: $31 We can also use the angle-bracket syntax to have two parts of a specification jammed directly next to each other, with nothing in between: CSS colour is a kind of value. # specifies a CSS colour with parts red level (2 hexadecimal digits), green level (2 hexadecimal digits) and blue level (2 hexadecimal digits). This enables `CSS colour` to have values like `#4169E1`, royal blue. The part names in the angle-bracket escapes have to exactly match those given in the tail of the sentence, and in the same order: Inform will throw a problem message if not. ## Unusual digits ^^{units of measure: defining: with non-numeric parts} ^^{defining: units of measure with parts: with non-numeric parts} ^^{numbers: hexadecimal and other bases: in units of measure} ^^{characters (letters): accented and exotic letters and symbols} The parts option `digits "TEXT"` tells Inform to use the supplied digit characters in place of the regular ones. The text must contain exactly the number of characters which equals the number base (2 for binary, 8 for octal, and so on), must have no repeats, and must not use spaces or square brackets. For binary, the default is `digits "01"`, for decimal it is `digits "0123456789"`, for hexadecimal `digits "0123456789ABCDEF"` and so on. For example, suppose we want to print hexadecimal numbers as if they were constants in the programming language C, and using lower-case letters for the digits 10 to 15. This would do it: A C-style hex number is a kind of value. <"0x"> specifies a C-style hex number with parts value (in hexadecimal, digits "0123456789abcdef"). To say (N - a number) C-style: say the C-style hex number with value part N. And then `"15786 = [15786 C-style]"` then substitutes to ``15786 = 0x3daa``. Note that if non-standard digit sets are used, then numbers must be written as unsigned, and are printed accordingly: but see the [Sun Nueng Song Sam] example for how to handle a signed form. Throwing in emoji or other symbols can make some intriguing textual effects: A tomb wall pattern is a kind of value. specifies a tomb wall pattern with parts pattern number (4 base 4 digits, digits "▙▛▜▟"). When play begins: repeat with S running from ▙▙▙▙ to ▟▟▟▟: say "[S] "; say ".... is the full set." prints all 256 possible wall carvings using a row of 4 shapes, each of which can be of 4 types. ## Parts which do not look like numbers ^^{units of measure: defining: with non-numeric parts} ^^{defining: units of measure with parts: with non-numeric parts} So far, all the parts of a specification have been basically numerical, if possibly with unusual digits. But we can break away from that completely with two more options supplied for parts. `values "TEXT"` gives a comma-separated list of the text to use for the values. For example, `values "LF, RF, LH, RH"`, where there are exactly 4 possible values, and this is how they are written. Internally, these will be stored as the numbers 1 to 4 respectively. The individual values must be all different from each other, and must not include spaces, double-quotation marks, square brackets, or commas. At least two values must be provided. If the `values "TEXT"` option is used on a part, then the various other options to do with digits, leading zeros and ranges are all forbidden, since the list we've given already defines the range exactly. To see why this might be useful, let's work through a practical problem. In modern chess, the squares are written a1 to h8, where the letter represents the "file" (or column) and the number represents the "rank" (or row). For example, White's leftmost pawn begins on a2, and is called the a-pawn; and Black's king spends the early game hiding on the 8th rank. So, then, we will try to make an Inform kind whose values are exactly the 64 squares `a1` to `h8`. A devious option would be: A chessboard square is a kind of value. specifies a chessboard square with parts file (1 octal digit, digits "abcdefgh") and rank (1 to 8). But this is not ideal. We would find that `file part of a1` was 0, whereas `rank part of a1` was 1: it seems clumsy to number files from 0 and ranks from 1. The following would fix that, but hardly seems elegant: A chessboard square is a kind of value. specifies a chessboard square with parts file (1 to 8, digits "0abcdefgh9") and rank (1 to 8). where, of course, the digits `0` and `9` can never be needed for the file, because its range is constrained as `1 to 8`. But this is much clearer: A chessboard square is a kind of value. specifies a chessboard square with parts file (values "a, b, c, d, e, f, g, h") and rank (1 to 8). The file part is automatically constrained as 1 to 8 because there are 8 notations in the text `"a, b, c, d, e, f, g, h"`. The following little game works with any of the three definitions above: {*}"Chess Fundamentals" Capablanca's Dining Room is a room. When play begins: showme c4; showme d7; repeat with S running from a1 to h8: say "[S] "; say "...and that's all." Square pressing is an action applying to one chessboard square. Carry out square pressing: say "You press square [chessboard square understood]." Understand "press [chessboard square]" as square pressing. Test chess with "press a1 / press a0 / press h8 / press c3 / press i3". Which all works as expected: ``` transcript chessboard square: c4 chessboard square: d7 a1 a2 a3 a4 a5 a6 a7 a8 b1 b2 b3 b4 b5 b6 b7 b8 c1 c2 c3 c4 c5 c6 c7 c8 d1 d2 d3 d4 d5 d6 d7 d8 e1 e2 e3 e4 e5 e6 e7 e8 f1 f2 f3 f4 f5 f6 f7 f8 g1 g2 g3 g4 g5 g6 g7 g8 h1 h2 h3 h4 h5 h6 h7 h8 ...and that's all. Capablanca's Dining Room > PRESS A1 You press square a1. > PRESS A0 You can't see any such thing. > PRESS H8 You press square h8. > PRESS C3 You press square c3. > PRESS I3 You can't see any such thing. ``` The so-called English notation, which not even the English use any longer, would also be possible: A chessboard square is a kind of value. specifies a chessboard square with parts file (values "QR, QN, QB, Q, K, KB, KN, KR") and rank (1 to 8). The trouble with this is that the square which White calls KB2 is the square Black calls KB7, and we cannot know who is asking. ## Parts corresponding to kinds ^^{units of measure: defining: with parts of a kind of value} ^^{defining: units of measure with parts: with parts of a kind of value} ^^{|corresponding to: in defining units of measure} ^^{kinds: of value: in defining units of measure} One last option available for parts of a specification is `corresponding to KIND`, which says that the part contains a value of the given `KIND`, which must be either numerical or an enumeration, rather than a `number`. Let's return to chess notation. The best specification so far looks like this: A chessboard square is a kind of value. specifies a chessboard square with parts file (values "a, b, c, d, e, f, g, h") and rank (1 to 8). With this specification, the two parts of a `chessboard square` value are each numbers from 1 to 8. For example, `rank part of e7` evaluates to the number 5. That might be fine for performing calculations, but it's not the way chess players actually talk or write. Here is an alternative: A chessboard file is a kind of value. The chessboard files are the a-file, the b-file, the c-file, the d-file, the e-file, the f-file, the g-file and the h-file. A chessboard rank is a kind of value. The chessboard ranks are the first rank, the second rank, the third rank, the fourth rank, the fifth rank, the sixth rank, the seventh rank, the eighth rank. A chessboard square is a kind of value. specifies a chessboard square with parts file (values "a, b, c, d, e, f, g, h", corresponding to chessboard files) and rank (1 to 8, corresponding to chessboard ranks). We now find that, for example: "chessboard square with file part the d-file rank part the sixth rank" = chessboard square: d6 "rank part of e7" = chessboard rank: seventh rank What `corresponding to K`, where `K` is a kind, does is to tell Inform that the numerical value internally stored to represent the meaning of a part should be treated as a value of kind `K`. By default, `K` is `number`. `K` can be set to any numerical kind, or to any enumeration with the right number of instances. `chessboard rank` above has 8 instances, which matches the range of 8 possible values for `rank`: if these numbers had not matched, a problem message would have been issued. If `K` uses real arithmetic then automatic floating and rounding are used in order to convert from or to a whole-number part. Consider this example, which sneakily contains only a single part: The GR10 is a room. Distance is a kind of value. 1.0km specifies a distance. A trail position is a kind of value. Kilometer 2000 specifies a trail position with parts depth (corresponding to distance). When play begins: showme Kilometer 230; showme the depth part of Kilometer 230; showme the trail position with depth part 67.51; This produces: ``` transcript trail position: Kilometer 230 "depth part of Kilometer 230" = distance: 230.0km "trail position with depth part 67.51km" = trail position: Kilometer 68 ``` Note that `67.51km` was rounded here to the nearest `number` value, 68. ## Counting and repeating through specified values ^^{units of measure: repeating through} The final version of `chessboard square` which we reached was this: A chessboard file is a kind of value. The chessboard files are the a-file, the b-file, the c-file, the d-file, the e-file, the f-file, the g-file and the h-file. A chessboard rank is a kind of value. The chessboard ranks are the first rank, the second rank, the third rank, the fourth rank, the fifth rank, the sixth rank, the seventh rank, the eighth rank. A chessboard square is a kind of value. specifies a chessboard square with parts file (values "a, b, c, d, e, f, g, h", corresponding to chessboard files) and rank (1 to 8, corresponding to chessboard ranks). Something interesting to note about `chessboard square` is that its range of possible values is not unlimited. With only 8 possible files and 8 possible ranks, there are just 64 possible values. This contrasts with a specification like: A monetary value is a kind of value. $1.99 specifies a monetary value with parts dollars and cents. where the range is for practical purposes unlimited — well, in fact, `$21474836.47` is really the limit, but this is not an everyday amount to find in one's pocket. There are over two billion values, and it would be completely impractical to `repeat with M running through monetary values`. Inform will throw a problem message if we try. But Inform _will_ allow us to repeat through `chessboard square` values, count them, take random values, and so on. Thus: ``` transcript "number of chessboard squares" = number: 64 "list of chessboard squares" = list of chessboard squares: {a1, a2, a3, a4, a5, a6, a7, a8, b1, b2, b3, b4, b5, b6, b7, b8, c1, c2, c3, c4, c5, c6, c7, c8, d1, d2, d3, d4, d5, d6, d7, d8, e1, e2, e3, e4, e5, e6, e7, e8, f1, f2, f3, f4, f5, f6, f7, f8, g1, g2, g3, g4, g5, g6, g7, g8, h1, h2, h3, h4, h5, h6, h7, h8} "a random chessboard square" = chessboard square: c7 ``` Loops such as `repeat with S running through chessboard squares` are now possible, as are implicit loops which involve searching through values to look for matches against conditions. For example, given: Definition: a chessboard square is white rather than black: let F be the file part of it; let file parity be whether or not F is the a-file or F is the c-file or F is the e-file or F is the g-file; let R be the rank part of it; let rank parity be whether or not R is the first rank or R is the third rank or R is the fifth rank or R is the seventh rank; if file parity is rank parity, no; yes. ...we can write, for example, `number of white chessboard squares`, which will of course calculate out to 32. # Tables ## Laying out tables {TABLES} {PM_TableCoincidesWithKind} {PM_TableColumnEmptyLists} {PM_TablePlayerEntry} {PM_TableVariableEntry} {PM_TableDescriptionEntry} {PM_TableUnknownEntry} {PM_TableIncompatibleEntry} {PM_TableMisnamed} {PM_TableNameDuplicate} {PM_TableNameAmbiguous} {PM_TableTooManyColumns} {PM_TableColumnArticle} {PM_TableColumnAlready} {PM_TableWithoutRows} {PM_TableUndefined} {PM_TableOfQuantifiedKind} {PM_TableOfBuiltInKind} {PM_TableOfExistingKind} {PM_TableDefiningObject} {PM_TableWithBlankNames} {PM_TableEntryGeneric} {PM_TableKindlessColumn} {PM_TableColumnBrackets} {PM_TableRowFull} ^^{tables <-- columns, in tables <-- rows, in tables}^^^{tables <-- entries, in tables} ^^{tables: formatting} ^^{tables: defining} ^^{defining: tables} ^^{tables: tabs in formatting tables} ^^{tabs vs spaces, in tables+ofsource+} ^^{spaces vs tabs (in tables)} ^^{line breaks: in formatting tables} ^^{type-checking: in tables} When printed books need to display detailed information in a systematic way, they break off from running text and print a table instead. Inform does the same. Here is a typical example: {*}Table 2.1 - Selected Elements Element Symbol Atomic number Atomic weight "Hydrogen" "H" 1 1 "Iron" "Fe" 26 56 "Zinc" "Zn" 30 65 "Uranium" "U" 92 238 After the two titling lines, each line represents one row in the table, and entries on a line must be separated by at least one tab character. A table must occupy a single whole paragraph, with no skipped lines or missing entries. The top line is a title, the first word of which must be the word `Table`. We can then either give a table number (this need not actually be a number: `Table C2`, or some such, would be fine), or give a name, or both – as in this case. The possible titling formats are: Table 2.3 Table of Population Statistics Table 2.3 - Population Statistics In the last example we could call the table either `Table 2.3` or `Table of Population Statistics`. Each column then has a name, and the contents must all be the same kind of value. In the elements table the `Symbol` column contains only text, for instance, and the `Atomic weight` column contains only numbers. Any kinds of value will do, so long as all the entries in the column are mutually compatible. (For instance, mixing rooms and things in a single column would be fine, as these can be reconciled, but mixing numbers and rooms would not.) ## Looking up entries ^^{tables: looking up by row number} ^^{rows: number of rows in/from (table name)+phr+} The simplest way to access the information inside tables is to ask explicitly for it, specifying the row number, the column name and what table is to be consulted. So, given our example table {*}Table 2.1 - Selected Elements Element Symbol Atomic number Atomic weight "Hydrogen" "H" 1 1 "Iron" "Fe" 26 56 "Zinc" "Zn" 30 65 "Uranium" "U" 92 238 we can write the following description: symbol in row 3 of the Table of Selected Elements to produce the value `"Zn"`. Or the following will run off some chemical data: {*}repeat with N running from 1 to the number of rows in the Table of Selected Elements: say "The atomic weight of [element in row N of the Table of Selected Elements] is [atomic weight in row N of the Table of Selected Elements]." The result of which will be: The atomic weight of Hydrogen is 1. The atomic weight of Iron is 56. The atomic weight of Zinc is 65. The atomic weight of Uranium is 238. Note that the first row in a table is row number 1, and that the last can be found with the phrase: > phrase: {ph_numrows} number of rows in/from (table name) ... number > > This phrase produces the number of rows (including any blank rows) in the given table. Example: > > number of rows in the Table of Selected Elements ## Corresponding entries ^^{tables: looking up by cross-reference} ^^{|corresponding to: in tables} Continuing our example of the elements: {*}Table 2.1 - Selected Elements Element Symbol Atomic number Atomic weight "Hydrogen" "H" 1 1 "Iron" "Fe" 26 56 "Zinc" "Zn" 30 65 "Uranium" "U" 92 238 If we want to know the atomic number of Uranium, say, it seems artificial to have to talk about the particular row number where the information happens to be. So we are also allowed to cross-reference, like so: the atomic number corresponding to a symbol of "Fe" in the Table of Selected Elements This results in 26, and similarly the symbol corresponding to an atomic number of 26 in the Table of Selected Elements results in `"Fe"`. But we have to be careful: the element corresponding to an atomic number of 27 in the Table of Selected Elements This is not allowed (it produces an error at run-time), because there is no row with atomic number 27 in this rather limited table. We can check this in advance with the condition: if there is an element corresponding to an atomic number of 27 in the Table of Selected Elements ... Or more simply: if there is an atomic number of 27 in the Table of Selected Elements ... The condition `if there is...` can be used with any reference to a table entry: for instance, `if there is a symbol in row 5 of the Table of Selected Elements` would be false, because there are only four rows. ## Changing entries ^^{tables: changing entries} ^^{+to+now (a condition): changing table entries} ^^{type-checking: in tables} ^^{testing phrases: showme the contents of (table name)+phr+} Here is another rather definitive, immutable-looking table: {*}Table 4 - Recent Monarchs Name Accession Family "Anne" 1702 Stuart "George I" 1714 Hanover "George II" 1720 Hanover "George III" 1760 Hanover "George IV" 1820 Hanover "William IV" 1830 Hanover "Victoria" 1837 Hanover "Edward VII" 1901 Saxe-Coburg-Gotha "George V" 1910 Windsor "Edward VIII" 1936 Windsor "George VI" 1936 Windsor "Elizabeth II" 1952 Windsor But table entries can be changed as freely as variables: that is, any value can be entered so long as it has the right kind. We cannot put a dynasty into the `Name` column, or text in the `Accession` column. The phrase needed is `now ... is ...`, just as it is for properties or variables: {**}Dynasty is a kind of value. The dynasties are Stuart, Hanover, Saxe-Coburg-Gotha and Windsor. The Table Office is a room. The Succession is in the Table Office. "The Succession, a ponderous list of English monarchs, takes pride of place." Instead of examining the Succession: say "The Succession List runs as follows..."; repeat with N running from 1 to the number of rows in the Table of Recent Monarchs: say "[accession in row N of Table 4]: [name in row N of Table 4] ([family in row N of Table 4])." Instead of attacking the Succession: now the family corresponding to an accession of 1720 in the Table of Recent Monarchs is Stuart; now the name in row 4 of the Table of Recent Monarchs is "Graham I"; now the name in row 5 of the Table of Recent Monarchs is "Trixibelle IV"; say "You deface the English succession, making suitable amendments with a quill pen. Considering it is supposed to be mightier than the sword the effect is a little disappointing." Test me with "examine succession / attack it / examine it". Once we start changing tables, it sometimes becomes useful to check what they contain. > phrase: {ph_showmetable} showme the contents of (table name) > > This phrase prints a crude but sometimes useful display on screen of the current contents of the named table. It's intended for authors to see when testing, not for players of the finished version to see. > phrase: {phs_currenttablerow} say "[current table row]" > > This text substitution produces a crude but sometimes useful listing of the entries in the currently chosen table row. > phrase: {phs_tablerow} say "[row (number) in/from table (table name)]" > > This text substitution produces a crude but sometimes useful listing of the entries in the specified row. > phrase: {phs_tablecolumn} say "[(column name) in/from table (table name)]" > > This text substitution produces a crude but sometimes useful listing of the entries in the specified column. ## Choosing rows {PM_NoRowSelected} ^^{tables: choosing rows} ^^{randomness: choosing a random table row} ^^{rows: choose a/the/-- row (number) in/from (table name)+phr+} ^^{rows: choose a/the/-- row with (table column) of (value) in/from (table name)+phr+} The following would be one way to print out a list of recent Kings and Queens: {*}To list the succession: say "The Succession List runs as follows..."; repeat with N running from 1 to the number of rows in the Table of Recent Monarchs: say "[accession in row N of the Table of Recent Monarchs]: [name in row N of the Table of Recent Monarchs] ([family in row N of the Table of Recent Monarchs])." This works, but is repetitive. We often want to work on a single row for a while, either to change things or think about the contents, and it is tiresome to keep specifying the row over and over again. The following shorthand provides some relief: > phrase: {ph_chooserow} choose a/the/-- row (number) in/from (table name) > > This phrase selects the row with the given number. Row numbers in a table start from 1, so > > choose row 1 from the Table of Recent Monarchs > > selects the top row. That allows us to improve the loop: To list the succession: say "The Succession List runs as follows..."; repeat with N running from 1 to the number of rows in the Table of Recent Monarchs: choose row N in the Table of Recent Monarchs; say "[accession entry]: [name entry] ([family entry])."; Actually, as we'll see in the next section, this kind of loop is needed so often that there's a shorthand wording for it. Note that since `accession` is a column name, `accession entry` means the entry in that column of the currently chosen row. This notation can only be used if a `choose` has certainly already happened, and it is a good idea to make that choice somewhere close by in the source code (and certainly in the same rule or phrase definition) for the sake of avoiding errors. We can also choose rows by specifying something about them, like so: > phrase: {ph_chooserowwith} choose a/the/-- row with (table column) of (value) in/from (table name) > > This phrase selects the _first_ row, working down from the top of the given table, in which the given column has the given value. Example: > > choose row with a name of "Victoria" in the Table of Recent Monarchs; > > A run-time problem message is produced if the value isn't found anywhere in that column. There can of course be any number of rows where a given column entry has the same value. In our example table of monarchs, there were six rows with a `family` of `Hanover`, and two with an `accession` of 1936. On the other hand, the `name` entries were all unique. It is very much up to an author what sort of data is stored in a table, how the data is sorted, and whether it has repeats. Sometimes it will happen that a column's name clashes with the name of something else: for instance, if we call a column `apples` but we also have a kind called `apple`, so that the word `apples` could mean either some fruit or the column. Inform will generally prefer the former meaning as more likely. In case of such trouble, we can simply refer to `the apples column` rather than just `the apples`: for instance, `choose row with an apples column of...` rather than `choose row with an apples of...` We can also choose a row quite at random: > phrase: {ph_chooserandomrow} choose a/the/-- random row in/from (table name) > > This phrase makes a uniformly random choice of non-blank rows in the given table. Note that although a table always has at least one row, it can't be guaranteed that it always has a non-blank row, so it's possible for this to fail: if it does, a real-time problem message is thrown. We have now seen several ways to choose rows. For small and medium-sized tables, good advice is to use whichever method involves least work. But when tables grow large, speed may be an issue here. `choose row N` is a very fast operation, which takes the same length of time however large the table or row number. But `choose row with a name of ...` means a lot of comparisons, checking each row. With big data sets, we may be better off writing our own search tactics. Another advantage of choosing by row number is that rows as such are not values in Inform, but numbers of course are. So we can remember that we are at row 362 by storing the number 362 somewhere, and return to that position later using `choose row 362 from ...`. ## Repeating through tables ^^{tables: repeating through} ^^{(reverse order), for table rows+sourcepart+} We very often want to run through a table doing something to, or with, each row in turn, so a special loop is provided for this. Rather than having to write all this out: To list the succession: say "The Succession List runs as follows..."; repeat with N running from 1 to the number of rows in the Table of Recent Monarchs: choose row N in the Table of Recent Monarchs; say "[accession entry]: [name entry] ([family entry])." We can simply use this instead: > phrase: {ph_repeattable} repeat through (table name): > > This phrase causes the block of phrases following it to be repeated once for each row in the given table, choosing each row in turn, from top to bottom. Blank rows are skipped. Example: > > To list the succession: > say "The Succession List runs as follows..."; > repeat through the Table of Recent Monarchs: > say "[accession entry]: [name entry] ([family entry])." Note that there is no loop variable here, unlike in other forms of `repeat`, because it's the choice of row which keeps track of how far we have got. Note also that it's `repeat through...`, not `repeat running through...` We can alternatively go backwards: > phrase: {ph_repeattablereverse} repeat through (table name) in reverse order: > > This phrase causes the block of phrases following it to be repeated once for each row in the given table, choosing each row in turn, from bottom to top. Blank rows are skipped. More often we want a sequence which is neither forwards nor backwards, but which depends on the actual values in the table. > phrase: {ph_repeattablecol} repeat through (table name) in (table column) order: > > This phrase causes the block of phrases following it to be repeated once for each row in the given table, choosing each row in turn, in order of the values in the given column. Blank rows are skipped. Example: > > repeat through the Table of Recent Monarchs in name order: ... > repeat through the Table of Recent Monarchs in accession order: ... > > work through the same table in rather different orders. The sequence is lower to higher (small numbers to high numbers, A to Z, and so on); insert "reverse" after "in" to reverse this. > phrase: {ph_repeattablecolreverse} repeat through (table name) in reverse (table column) order: > > This phrase causes the block of phrases following it to be repeated once for each row in the given table, choosing each row in turn, in order of the values in the given column. Blank rows are skipped. Example: > > repeat through the Table of Recent Monarchs in reverse name order: ... > repeat through the Table of Recent Monarchs in reverse accession order: ... > > work through the same table in rather different orders. The sequence is higher to lower (high numbers to small numbers, Z to A, and so on); delete the `reverse` after `in` to reverse this. In a loop like this, the data is not searched very efficiently, which is fine for modest-sized tables like the examples in this chapter, but might be a problem for much larger tables: see the later section on sorting. These definitions mentioned blankness several times, and that's the topic to cover in the next section. ### See Also - [Sorting] for reordering a table to put it into increasing or decreasing order of the entries in any column. ## Blank entries ^^{tables: blank entries <-- blank entries in tables} ^^{|--: as a blank table entry} ^^{punctuation: double-dash: as a blank table entry} We are allowed to leave certain entries blank (perhaps to be filled in later, perhaps not) by writing `--` instead of the relevant value: {*}Table 2.1 - Selected Elements Element Symbol Atomic number Atomic weight "Hydrogen" "H" 1 1 "Iron" "Fe" -- 56 "Zinc" -- 30 65 "Uranium" "U" 92 238 In effect, blank entries don't exist. `--` is not a value, but only a hole where a value might be. Attempting to read a blank entry throws a run-time problem message, so if there is ever any doubt about whether an entry might be blank or not, it is essential to check for this: > phrase: {ph_thereis} if there is (a table entry): > > This condition is true if the entry referred to exists, that is, that is, the space for it in the table is not blank. Examples: > > if there is a symbol corresponding to an atomic number of 30 in the Table of Selected Elements ... > if there is an atomic number in row 2 of the Table of Selected Elements ... > phrase: {ph_thereisno} if there is no (a table entry): > > This condition is true if the entry referred to does not exist, that is, the space for it in the table is blank. Examples: > > if there is no symbol corresponding to an atomic number of 30 in the Table of Selected Elements ... > if there is no atomic number in row 2 of the Table of Selected Elements ... The reference here to a _table entry_ can be any of the following possibilities: Reference to a table entry | Example ---------------------------- | ------- `TC entry` | `if there is an atomic weight entry` `TC in row N in/of/from T` | `if there is a symbol in row 5 of Table 2.1` `TC listed in T` | `if there is an atomic number listed in Table 2.1` `TC corresponding to TC of V in/from T` | `if there is an element corresponding to atomic weight of 65 in Table 2.1` `TC of V in/from T` | `if there is an atomic number of 56 in Table 2.1` Where `TC` is the name of a table column, `N` is a row number (counting from 1 as the top row), `T` is a table, and `V` is some value which might or might not be stored in the table. ## Blank columns ^^{tables: blank columns} An entire column of blank entries `--` is problematic: {*}Table 2 - Selected Elements Element Symbol Atomic number Atomic weight "Hydrogen" "H" 1 -- "Iron" "Fe" 26 -- "Zinc" "Zn" 30 -- "Uranium" "U" 92 -- Inform is unable to work out what kind of value should go into the `atomic weight` column here, since it has no examples to guess from. We can get around this by writing in the name of a kind of value: {*}Table 2 - Selected Elements Element Symbol Atomic number Atomic weight "Hydrogen" "H" 1 a number "Iron" "Fe" 26 -- "Zinc" "Zn" 30 -- "Uranium" "U" 92 -- That top entry in the `atomic weight` column is also blank, but now Inform knows that anything put into the column in future will be a number. If there are many rows, and perhaps several blank columns, it would become very tedious to have to keep typing out `--`. So this is optional *at the end of a row*: it remains compulsory for a blank value appearing in between two values which aren't blank. This is the general idea: {*}Table 2 - Selected Elements Element Symbol Atomic number Density Specific gravity "Hydrogen" "H" 1 a number a number "Iron" "Fe" 26 "Zinc" "Zn" 30 "Uranium" "U" 92 ## Blank rows ^^{tables: blank rows} ^^{empty / non-empty+adj+: for tables} ^^{non-empty / empty+adj+: for tables} ^^{tables: empty / non-empty+adj+} There is no difficulty about entirely blank rows: or rather, the only difficulty is once again that they are boring to type out. We can avoid the necessity by appending `with ... blank rows` at the foot of the table: {*}Table 2 - Selected Elements Element Symbol Atomic number Atomic weight "Hydrogen" "H" 1 a number "Iron" "Fe" 26 -- "Zinc" "Zn" 30 -- "Uranium" "U" 92 -- with 3 blank rows (These words cannot be placed in between rows, but only at the bottom.) And indeed the table can start out completely empty: {*}Table 3 - Undiscovered Periodic Table Element (text) Symbol (text) Atomic number (a number) Atomic weight (a number) with 92 blank rows Blank rows are useful because they enable us to add new data to a table. In effect, they are invisible when not used. A repeat loop like repeat through Table 3: ... automatically skips blank rows, so it would initially do nothing at all. Similarly, choosing a `random` row will never choose a blank one. A convenient way to test if a table contains non-blank rows is to use the built-in adjectives `empty` and `non-empty`. So: if the Undiscovered Periodic Table is empty, ... tests whether all of its rows are blank; if even one cell contains a value then the table is `non-empty`. ## Adding and removing rows ^^{tables: adding rows} ^^{tables: removing rows} ^^{tables: blank entries} ^^{tables: blank rows} ^^{tables: blank columns} Writing in new rows is simple, once we can find space for them: > phrase: {ph_chooseblankrow} choose a/the/-- blank row in/from (table name) > > This phrase chooses a row in the given table which is currently blank under every column. A run-time problem message is issued if no rows are blank. Example: > > choose a blank row in Table 3; > now element entry is "Fluorine"; > now symbol entry is "F"; > now atomic number entry is 9; > now atomic weight entry is 19; To avoid problem messages, it can be important to worry about free space. To that end we can not only find the number of rows (as we have already seen) but also the number currently blank and not blank: > phrase: {ph_numblank} number of blank rows in/from (table name) ... number > > This phrase produces the number of rows in the given table which are entirely blank (that is, blank under every column). > phrase: {ph_numfilled} number of filled rows in/from (table name) ... number > > This phrase produces the number of rows in the given table which are not entirely blank (that is, at least one column has a value in this row). `Filled` here really means `non-blank`: a row can be filled in this sense even if only one of its values exists. Since every row is either blank or filled, it must be true that: the number of blank rows in Table 3 the number of filled rows in Table 3 add up to `the number of rows in Table 3`. We've seen that blank entries can be filled with values using `now`: now symbol entry is "F"; But the same method can't be used to put blanks back, since a blank is not a value. Instead: > phrase: {ph_blankout} blank out (a table entry) > > This phrase replaces the entry referred to with a blank, erasing any value previously stored there. Example: > > choose row 1 in the Table of Fish Habitats; > blank out the salinity entry; These more destructive phrases need a steady hand: > phrase: {ph_blankoutrow} blank out the/-- whole row > > This phrase replaces the currently chosen row with blanks, erasing any value previously stored under any of the columns. Example: > > choose row 1 in the Table of Fish Habitats; > blank out the whole row; > phrase: {ph_blankoutcol} blank out the/-- whole (table column) column in (table) > > This phrase replaces the currently chosen column with blanks, erasing any value previously stored in any of the rows. Example: > > blank out the whole salinity column in the Table of Fish Habitats; > phrase: {ph_blankouttable} blank out the/-- whole of (table) > > This phrase replaces every row of the currently chosen table with blanks, erasing any value previously stored anywhere in it. Example: > > blank out the whole of the Table of Fish Habitats; > > This is only really useful when a Table is being used to hold working space for some calculation or other. ## Sorting ^^{tables: sorting tables} ^^{randomness: sorting tables in random order} ^^{(reverse order), for table rows+sourcepart+} There are several ways to sort a table, corresponding loosely to the different orders in which tables can be repeated through. First: > phrase: {ph_sortrandom} sort (table name) in random order > > This phrase rearranges the rows of the given table so that the non-blank rows occur at the top, in a uniformly random order, and any blank rows at the bottom. Example: > > sort the Table of Recent Monarchs in random order; Secondly: > phrase: {ph_sortcolumn} sort (table name) in (table column) order > > This phrase rearranges the rows of the given table so that the non-blank rows occur at the top, so that the given column has ascending order, and any blank rows at the bottom. Example: > > sort the Table of Recent Monarchs in accession order; > > Ascending order means 1 up to 10, say, or A up to Z, with blank values coming last. > phrase: {ph_sortcolumnreverse} sort (table name) in reverse (table column) order > > This phrase rearranges the rows of the given table so that the non-blank rows occur at the top, so that the given column has descending order, and any blank rows at the bottom. Example: > > sort the Table of Recent Monarchs in reverse name order; > > Descending order means 10 down to 1, say, or Z down to A, with blank values coming last. How sorting is done depends on the contents of the column being sorted on. If it holds numbers then numerical order is used, with 2 coming before 7, and so on. (And similarly for real numbers, though the existence of infinities makes this more interesting.) If times are sorted then they are sorted from midnight to midnight, following the `is greater than` relation, not with 4 AM as the zero point, as with `is after`. If text is sorted then alphabetical order is used, though this doesn't always come out the way you might expect, because upper case and lower case letters are treated as different: A-Z come before a-z, and accented letters such as é come after the regular alphabet. (What's happening here is that Inform is sorting on raw character values, not performing the full Unicode collation algorithm, which would be too slow at run-time.) Note that blank values will always be placed below non-blank ones, and entirely blank rows last of all. This is true even if we use `reverse`. The method of sorting is "stable", that is, if two rows have the same value then they will stay the same way round in the sorted table, rather than being swapped over. For example, if we sort this into reverse index order: Index Comment 1 "Originally row 1" 2 "Originally row 2" 2 "Originally row 3" 3 "Originally row 4" then we get Index Comment 3 "Originally row 4" 2 "Originally row 2" 2 "Originally row 3" 1 "Originally row 1" As a result note that repeating through this sorted table goes through the original rows in order 4, 2, 3, 1; whereas repeating through the original table in reverse order goes through in order 4, 3, 2, 1. (This is all to explain the word "loosely" in the opening sentence of this section.) > phrase: {ph_sorttablephrase} sort (table name) with (phrase (table name, number, number) -> number) > > This phrase sorts the table with a custom comparison phrase. The phrase is given the table name and two row numbers to compare, and it must return a number which indicates the relative order of the two rows: negative if the left row should come before the right, zero if the rows should be sorted as if they are equal, and positive if the left row should come after the right. Any completely blank rows will be put at the bottom, but if the table has partially blank rows, then the comparison phrase must be designed to account for the possibility of blank entries. > > The [Olympic Medals] example demonstrates two custom comparison phrases. ## Listed in... ^^{tables: describing things listed in tables} ^^{descriptions (references to things): listed in table} Tables are especially useful for combining a run of basically similar rules in a simple and concise way. The `listed in` condition, as in if the newfound object is an item listed in the Table of Treasures... looks through a given table (here `table of treasures`), in a given column (`item`), to see if a given value is present (`the newfound object`). If this is successful, the row where it was found is automatically chosen; but if not, note that any existing row selection will be lost, so make use of the row only if the test succeeds. We can similarly use `... listed in ...` in a description used when specifying an action. Thus: {*}After taking an item listed in the Table of Treasures: if there is no time entry: now the time entry is the time of day; increase the score by the value entry; say "Taken!" This assumes a table in the following shape: {**}Table of Treasures Item Value Time brooch 5 a time tiara 8 -- coronet 10 -- In effect the table has allowed us to combine three very similar rules into one. The time column records the first time at which the item has been picked up, which starts out blank since at the start of play it has never been picked up. This enables us to award the appropriate number of points on the first occasion only. ## Topic columns ^^{tables: topic columns} ^^{topics: in table columns} ^^{punctuation: slash: separating synonymous words in topics} ^^{|/: separating synonymous words in topics} A column whose name is just `Topic`, or whose name has `(topic)` in brackets after it, is special. It is used for matching fragments of a typed-in command, so the use of topics here is really an overlap with the `Understand...` system for making sense of typed command. That will be the subject of its own chapter, [Understanding]. For example, suppose the player meets a Sybil who has a penchant for telling passers-by which is the Greek muse for what. ``ASK SYBIL ABOUT POLYHYMNIA``, the player at once types. How is Inform to work out what to say? Here is a solution: {*}After asking the Sybil about a topic listed in the Table of Sybil's Replies: say "The Sybil declaims for a while, the gist being that the muse in question looks after [muse entry]." Table of Sybil's Replies Topic Muse "calliope" "epic poetry" "clio" "history" "erato" "love poetry" "euterpe" "music" "melpomene" "tragedy" "polyhymnia" "sacred poetry" "terpsichore" "dancing" "thalia" "comedy" "urania" "astronomy" "monica" "tidiness" "phoebe" "massage" "rachel" "oval hair-cuts" What is special about `Topic` columns is that they do _not_ contain text in the ordinary way, even though that's what the entries look like, because of the quotation marks. The entry `"polyhymnia"` (about half-way down) is not read as a value of the kind `text` — a string of letters, `p` then `o` then... and so on; it is read as a very simple "grammar" which looks at a fragment of typed command to see if it is equal to the word ``POLYHYMNIA`` or not. This is a value of the kind `topic`, not `text`. Topic values can't normally be typed in Inform, but they do occur in these columns, and in the text-like part following the word `Understand`. Topics do not have to be single words, and do not have to be fixed pieces of wording. For example: Table of Sybil's Replies (continued) "suzanne vega" "love songs" "muse [number]" "dreary everyday stuff" And we can now ``ASK SYBIL ABOUT MUSE 17``, or ``ASK SYBIL ABOUT SUZANNE VEGA`` Note that there is no point capitalising topics (`"Suzanne Vega"`, or `"Polyhymnia"`) because commands are read case-insensitively. As texts, `"clio"` and `"CLIO"` and `"Clio"` would all be different from each other, but as topics, they are all the same because they match the same word. Topics can be written to use the full range of abilities of the "understanding" system, so for more possibilities, see the chapter [Understanding]. With that said, topic columns in tables are mostly used for quite simple cases like the ones above, because that is what authors most often need. Still, one more feature is worth drawing attention to here. It would be clumsy to have to write: Table of Sybil's Replies (continued) "flora" "flowers" "eve" "flowers" where we want ``EVE`` to be another name for ``FLORA``. So: Table of Sybil's Replies (continued) "flora/eve" "flowers" The `/` notation works only for single words, so if we wanted to have alternative possibilities some or all of which were longer, then: Table of Sybil's Replies (continued) "Bridget" or "Bridge" or "Bridget Jones" "publishing" ## Another scoring example {*}To record (T - text) as achieved: choose row with a citation of T in the Table of Tasks Achieved; if there is no time entry: now time entry is the time of day; increase the score by the points entry. The phrase above expects to see a table like this one: {**}Table of Tasks Achieved Points Citation Time 1 "pride" a time 3 "anger" 2 "avarice" 4 "envy" 1 "lust" 2 "gluttony" 3 "sloth" The middle column records the tasks to be achieved, the first column records the points on offer for each: the final column, initially blank, will store the times at which the tasks are first achieved. Before eating, record "gluttony" as achieved. The first time we record "gluttony" as achieved, 2 points will be awarded and the time will be logged in the Table, but on all subsequent occasions nothing will happen. So the combination of the phrase and the Table will look after a scoring system based on achieving specific goals (probably not the seven deadly sins, of course). We can, if we choose, use the same system to display a log of recent accomplishments: repeat through the Table of Tasks Achieved in reverse time order: say "[time entry]: [citation entry] ([points entry])." ## Varying which table to look at {kind_tablename} ^^{tables: used as values} ^^{values: tables as values} ^^{|table name} So far, we have always used fixed table names when referring to tables: for instance in source like `sort the Table of Recent Monarchs in accession order`, we refer to the `Table of Recent Monarchs`, a definite and explicitly named table. With a little care, however, we are allowed to have variables which themselves hold the names of tables. This opens up the possibility of more elaborate ways of storing and interconnecting information in table form, but is probably best avoided until it becomes necessary. For example, suppose we have two different tables with the same basic structure: {*}Table 1 - Nifty Opening Plays in US Scrabble word score "muzjiks" 128 Table 2 - Nifty Opening Plays in UK Scrabble word score "quartzy" 126 "squeezy" 126 We could then record which one of these tables to use in a variable: {**}The lexicon is a table name that varies. The lexicon is Table 1. Note that for this purpose, the kind of value is a special kind called `table name`, not `table`. (The word `table` already has too many meanings and we must be careful to avoid ambiguities here.) We could make use of this as follows, for instance: {**}To flip tables: say "You exchange dictionaries, lexically crossing the Atlantic. "; if the lexicon is Table 1, now the lexicon is Table 2; otherwise now the lexicon is Table 1; choose a random row in the lexicon; say "Did you know that according to [the lexicon], [word entry] scores [score entry]?" which produces text such as ``` transcript You exchange dictionaries, lexically crossing the Atlantic. Did you know that according to Table 1 - Nifty Opening Plays in US Scrabble, muzjiks scores 128? ``` ## Defining things with tables {PM_TableDefiningNothing} {PM_TableDefiningTheImpossible} ^^{tables: creating multiple things with a table} ^^{things+kind+: creating: multiple things with a table} ^^{properties: defining properties with a table} ^^{defining: things: multiply using tables} ^^{tables: defining multiple kinds with a table} ^^{kinds: defining: multiple kinds with a table} ^^{defining: kinds: multiply using tables} Suppose we need to create a collection of objects which differ in their properties, but are basically part of a larger pattern. (Usually these objects will be things, but they don't have to be.) For instance, suppose we want a collection of coloured shirts: A jersey is a kind of thing. A jersey is wearable. A jersey has a number called year established. A jersey has a text called citation. The description of a jersey is "Since [year established], the Tour de France has awarded this jersey to the [citation]." Now we have the pattern, but making the actual shirts is tedious and repetitive: The yellow jersey is a jersey. The year established of the yellow jersey is 1919. The citation of the yellow jersey is "race leader". The polkadot jersey... And so on. Instead, we can use a table to abbreviate all of this: {*}"Tour des Maillots" The Staging Area is a room. A jersey is a kind of thing. A jersey is wearable. Some jerseys in the Staging Area are defined by the Table of Honorary Jerseys. The description of a jersey is "Since [year established], the Tour de France has awarded this jersey to the [citation]." Table of Honorary Jerseys jersey year established citation a yellow jersey 1919 "race leader" a polkadot jersey 1933 "King of the Mountains" a green jersey 1953 "highest point scorer on sprints" a white jersey 1975 "best cyclist aged 25 or less" The first column provides names for the new things to be created. Subsequent columns provide property values. Note that we did not need to say that jerseys have a number called `year established` because Inform is able to infer this from the column heading and the presence of numbers in the column; similarly for `citation`. An entry can be left blank (written `--`), and the result is then that the property is set to an appropriate default value: for `year established` this would be 0, for `citation` a blank text, and so on. Note that Inform reads articles such as `the` or `a` in the first column just as it would when something is created with any other sentence. It's even possible to define kinds this way. It's rare to need to create many kinds at once, and really only sensible when for some reason a host of very similar subkinds are needed. {*}"By the Rivers of Serra da Mantiqueira" Oaxaca, Espírito Santo, Lambayeque, Valle del Cauca, Ecuador, Venezuela, Rio de Janeiro are regions. A bromeliad is a kind of thing. Some kinds of bromeliad are defined by the Table of Alphabetically Early South American Bromeliads. Table of Alphabetically Early South American Bromeliads name habitat pitcairnia abundans Oaxaca pitcairnia abyssicola Espírito Santo pitcairnia acicularis Lambayeque pitcairnia adscendens Valle del Cauca pitcairnia aequatorialis Ecuador pitcairnia agavifolia Venezuela pitcairnia alata Ecuador pitcairnia albiflos Rio de Janeiro Pontões Capixabas is a room. In Pontões Capixabas are three pitcairnia abyssicolas and a pitcairnia agavifolia. Pontões Capixabas is in Espírito Santo. Instead of examining a bromeliad (called the plant): if the location is in the habitat of the plant: say "You see these all over [habitat of the plant]."; otherwise: say "You usually only see these in [habitat of the plant]." Test me with "examine abyssicola / examine agavifolia". There are more examples in a very early demonstration piece for Inform: see [Reliques of Tolti-Aph](https://github.com/I7-Examples/The-Reliques-of-Tolti-Aph). ## Defining values with tables ^^{properties: defining properties with a table} ^^{tables: defining a kind of value with a table} ^^{kinds: defining: kinds of value: defining with a table} ^^{defining: kinds of value: defining with a table} ^^{values: kinds of value: defining with a table} Just as we can define many similar things (or kinds) using a table, we can also define a whole run of new values. Again, this avoids unnatural prose like The chemical elements are Hydrogen, Helium, Lithium, ..., and Ununquadium. We can give these new values properties, too. For example: {*}Solar distance is a kind of value. 1000 AU specifies a solar distance. Planet is a kind of value. The planets are defined by the Table of Outer Planets. Table of Outer Planets planet semimajor axis Jupiter 5 AU Saturn 10 AU Uranus 19 AU Neptune 30 AU Pluto 39 AU creates five values of the kind `planet`, but it also makes a property called `semimajor axis` which belongs only to these five values. Thus: say "Pluto orbits at [semimajor axis of Pluto]." produces `Pluto orbits at 39 AU.` We can both use and change this value: Praying is an action applying to nothing. Understand "pray" as praying. Instead of praying: now the semimajor axis of Pluto is 1 AU; say "Your prayers are answered, and the Almighty moves Pluto in closer to the fire." Similar properties would be made for each column of the table after the first (there can be any number of properties, including none). Because the values are created first, before the rest of the table is gone through, we can even use `planet` as one of the values of properties: Table of Outer Planets planet semimajor axis centre of government Jupiter 5 AU Jupiter Saturn 10 AU Saturn Uranus 19 AU Saturn Neptune 30 AU Pluto Pluto 39 AU Pluto All of this is intended to be closely parallel to defining a whole run of things, such as the coloured jerseys, using a table, but there are two important restrictions: firstly, when a kind of value is defined by table, the table must contain all of its possible values; and secondly, the column names (after the first) cannot coincide with names of any properties held by any other value (or thing, for that matter). So it is a good idea to give the columns very specific names (`centre of government`) rather than vague names which might cause clashes elsewhere (`owner`). Two technical footnotes. In a table used to define a kind of value, blank entries are not left blank: they are filled in with suitable default values. For instance, if the semimajor axis column had been all `--`s except for listing Neptune at `30 AU`, say, Inform would deduce that the column was meant to hold a value of kind `solar distance`, and would set the solar distances for all of the other planets to be `0 AU`. It does this to ensure that `solar distance of P` exists for any planet P. The second technical note is that we must not sort such a table, because it is used during play to store the properties, and if it were to get rearranged then so would the properties be – with probably disastrous results. ## Table continuations {PM_TableNotContinuation} ^^{tables: continuing tables} ^^{(continued), for tables+sourcepart+} A table is an arrangement for putting information together concisely in a single place, so it might seem odd that we sometimes need to divide it up: but once in a while, we do. Suppose we have: Table of Outer Planets planet semimajor axis Jupiter 5 AU Saturn 10 AU Uranus 19 AU Neptune 30 AU Pluto 39 AU But then someone in Chile with a telescope the size of ^{God's own teacup} notices something a long, long way out, and the newspapers get terribly excited. We can write an addendum: Table of Outer Planets (continued) planet semimajor axis Orcus 39 AU Quaoar 43 AU Xena 68 AU Sedna 524 AU This may seem unnecessary – why not simply add extra rows to the original table? – but it allows us to split the table between different parts of the source text, if we want to, or to continue a table which exists only in an extension. (Thus if we were using an extension which involved the planets, and had a table like this one, we would be able to add new planets without changing the extension.) The name for the continuation must be identical to the original. The continuation has no existence in its own right: Inform simply splices the two (or more) pieces together, exactly as if the table were all in one piece at the place where it first occurred. Thus the above creates only one table, the `Table of Outer Planets`, with nine rows. Each column in the continuation must exist in the original, but not every column need be given: those omitted are filled with blank entries. The columns need not be in the same order. Both original and continuations are allowed to quote a number of blank rows: if so, the combined total is used. At time of writing the International Astronomical Union has not yet consented to name 2003 UB313 after Xena, the Warrior Princess, but this is surely only a bureaucratic delay. (Footnote: on 24 August 2006 it was demoted to dwarf planet status, like the luckless Pluto, and on 13 September renamed Eris; though its moon's official name, Dysnomia, is an ingenious double-meaning to do with the name of Xena's actress, Lucy Lawless.) ## Table amendments {PM_TableAmendmentMisfit} {PM_TableAmendmentMismatch} ^^{tables: amending tables} ^^{(amended), for tables+sourcepart+} Tables can have amendments as well as continuations. The arrangement is much the same: a supplementary table supplies new rows for the original table. But instead of adding the new rows at the end of the original, as a continuation would, an amendment replaces matching rows in the original. (So the original stays the same size.) The amendment table must have exactly the columns of the original and in the same order. Moreover, each row in the amended table must match exactly one row in the original. For instance: Table of Plans moment outcome 10 AM "takeover of Mars" 11:30 AM "canals reflooded" 11:45 AM "chocolate bar production doubled" Table of Plans (amended) moment outcome 11:45 AM "volcanic cave production doubled" creates a three-row `Table of Plans`, with reference to the chocolate bars struck out. Amendment rows may be given in any order. The process of matching a row begins at the left-most column: Inform tries to see if any single row in the original table has a matching entry. If none does, a Problem is issued. If more than one do, Inform then looks at the second column, and so on. For instance: Enthusiasm is a kind of value. The enthusiasms are pumped, wired and languid. Table of Mental States feeling extent consequence pumped 1 "you feel able to run for your life" pumped 2 "you feel able to run for President" wired 1 "you feel able to run" languid 1 "you feel" Table of Mental States (amended) feeling extent consequence pumped 2 "you feel able to run for the Nebraska State Legislature" Here the amendment is made to the second row of the original table. The value in the leftmost column, `pumped`, matches two rows in the original, so Inform moves on to the next column, reads `2`, and finds that only one row in the original still qualifies – so that is the one replaced. For the present, at least, the columns used for matching may only contain: numbers, times, objects, action names, activities, figure names, sound names, truth states and any new kinds of value or units which have been declared. ## Recap of the syntax for tables There is no new information in this section: it's a recap giving a full description of the syntax for writing tables in a single place. Like a rule or a phrase, a **table** has its own syntax and occupies a single paragraph in the source text. This paragraph is internally divided into lines. The table contains the following: * The **title line**. This must begin with the word `Table`. It then consists of a number, or `of` and then a textual name, or a number and a name divided by a hyphen; and then, optionally, _either_ `(continued)` _or_ `(amended)`. Examples: - `Table 2` - `Table of Selected Elements` - `Table 2 - Selected Elements (continued)` - `Table 2 (continued)` - `Table of Selected Elements (amended)` * The **heading row**, divided up into one or more headings by tab characters. The first heading is in column 1, the second is in column 2, and so on. * Each **heading** consists of a column title and then, optionally, the name of a kind written in brackets. Examples: - `Element` - `Discoverer (text)` - `Atomic weight (a number)` - `Topic` - `Question (a topic)` Exceptionally, the heading `Topic` is read as if it were `Topic (a topic)`, i.e., giving both the name and the kind of this column as `topic`. * Optionally, one or more **entry rows**, similarly divided up into one or more entries with tab characters. The first entry is in column 1, the second is in column 2, and so on. * Each **entry** must be one of the following: 1) Any Inform constant value. Examples: `5`, `{ "socks", "shoes" }`, `the verb contain`. * If the heading for this column gave a kind, this value must be compatible with that kind. For example, if the heading read `Atomic weight (a number)`, then `17` would be valid, but `"No"` would not. * If the heading for this column gave a kind as `topic`, note that material inside double-quotes is read as a topic value, not a text value. Topics have the same syntax as the double-quoted text found in `Understand` sentences, and are patterns of words rather than printable matter. - For example, `"area [number]"` is valid as a `topic` but not as a `text`. It means "match pairs of words like ``AREA 51`` or ``AREA SIX``". - Whereas `"++[time of day]++"` and `"area [51]"` are valid as `texts` but not as a `topic`. * If the heading did not give a kind, then there must be a kind such that all values of entries in this column compatible with that kind. For example, `10`, `3.765` and `-21` are all compatible with `real number`. But there is no kind which can hold `12:02 am` and `"sixpence"`, which are too unlike each other. * A special rule applies if the heading for this column is `topic`. The column must then contain `Understand`-style grammar. This looks like a quoted text, perhaps with substitutions in square brackets, but in fact it follows the syntax rules for the sort of word pattern found after `Understand`. 2) A blank marker `--`, meaning that no value appears in this position. `--` is not a value: it is a notation meaning the absence of one. 3) The name of a kind, such as `a text`, but _only_ in the first data row, and _only if_ all subsequent entries in this column are blank, and _only if_ a kind has not already been given in brackets in this column's heading. The table entry in this position is again a blank. * The number of entries must not be greater than the number of headings in the heading row. * If the number of entries is less than the number of headings in the heading row, the missing columns are filled out as if `--` had been typed in the remaining entries: in other words, short rows are filled out with blanks. * Optionally, a **blank row line** consisting of `with`, then a literal positive number, then `blank row` or `blank rows`. Example: `with 64 blank rows`. This simply abbreviates typing 64 entry rows in which each entry was typed as `--`. # Understanding ## Understand {PM_OldVerbUsage} {PM_UnderstandCommandWhen} {PM_NotNewCommand} {PM_NotOldCommand} {PM_NontextualUnderstand} {PM_UnderstandMismatch} {PM_TextlessMistake} {PM_UnderstandAsActivity} {PM_UnderstandAsBadValue} {PM_UnderstandVague} {PM_LiteralPunctuation} {PM_UnderstandEmptyText} {PM_UnderstandCommaCommand} {PM_UnderstandAsCompoundText} {PM_ObsoleteHeldTokens} {PM_UseTextNotTopic} {PM_UseThingNotObject} {PM_UnparsableKind} {PM_UnknownToken} {PM_BizarreToken} {PM_OverComplexToken} {PM_TextTokenRestricted} {someone_token} {UNDERSTANDING} ^^{understanding <-- commands (of the player) <-- verbs: understanding verbs in player's command}^^^{understanding <-- grammar of player's command} ^^{actions: understanding in player's command} ^^{(applying to), in defining actions+sourcepart+} ^^{understand (verb) as (action)+assert+} ^^{understanding: verbs} ^^{defining: input grammar} ^^{grammar tokens} ^^{someone+token+} ^^{something+token+} ^^{(requiring), in defining actions+sourcepart+} ^^{visibility+rel+: requirement in defining actions} ^^{XYZZY} ^^{Actions page of Index panel+ui+} ^^{user interface: Index panel: Actions page} ^^{Index panel+ui+: Actions page} ^^{supplying a missing noun/second noun+activity+} ^^{missing noun: supplying a missing noun/second noun+activity+} During play, the computer and the player alternate in writing messages to each other: in the player's case, these are short instructions, usually saying what to do next. A wide range of such "commands" are automatically understood, but these only apply to the standard built-in actions. (This wide range is conveniently tabulated in the Commands part of the Actions index.) If we want the player to be able to command new actions, then we need to specify what is to be understood as what. For this, we supply special sentences starting with the word "Understand". Suppose we return to the earlier example of a newly created action: Photographing is an action applying to one thing and requiring light. We then supply lines of grammar (as they are called) for Inform to recognise, like so: Understand "photograph [someone]" as photographing. Understand "photograph [an open door]" as photographing. The part in quotation marks after the word `Understand` looks like text — something which Inform can say, or can manipulate in various letter-by-letter ways. The square brackets even look like text substitutions. In fact, though, `"photograph [an open door]"` is _not_ a text value. It is a pattern used to match the words in a command. It will match the word ``PHOTOGRAPH`` followed by the name of an open door which is currently "in scope" (an idea we will come back to, but which roughly means nearby). It will not match any other wording. For obvious reasons, this pattern of words needs to match the expectations of the action. Photographing applies to `one thing`, so these instructions are both a little odd: one supplies no things, and the other supplies two. Understand "photograph" as photographing. Understand "photograph [someone] standing next to [something]" as photographing. The first is actually allowed by Inform, even though it supplies no things at all, but should only be used in conjunction with a rule for the `supplying a missing noun` activity which makes an automatic choice of the missing thing. But the second line is always wrong and is rejected with a problem message. ## New commands for old grammar {PM_ThreeValuedLine} {PM_TooManyAliases} {PM_TooManyGrammarLines} {PM_GrammarIllFounded} ^^{understand (verb) as (action)+assert+} ^^{understanding: verbs} ^^{understand the command (verb) as (verb)+assert+} ^^{understanding: adding synonyms for verbs} ^^{something+token+} ^^{|with nouns reversed} ^^{reversed nouns, in understanding actions} ^^{nouns: reversed, in understanding actions} ^^{grammar tokens: for kinds of thing} ^^{Actions page of Index panel+ui+} ^^{user interface: Index panel: Actions page} ^^{Index panel+ui+: Actions page} In the photography example, we are providing entirely new grammar for an action not ordinarily built in to Inform. But we often want simply to provide alternative grammar for existing actions, or even to put new interpretations on commands that Inform already recognises. For instance: Understand "deposit [something] in [an open container]" as inserting it into. The inserting action is built in to Inform, but the command ``DEPOSIT`` is not, so this is created as new. It is occasionally useful to put a twist on this: Understand "fill [an open container] with [something]" as inserting it into (with nouns reversed). The clause `(with nouns reversed)` tells Inform to exchange the two nouns parsed, which is necessary because the inserting action expects the noun to be the item and the second noun to be the container, not vice versa. The following example: Understand "access [something]" as opening. might look as if it makes ``ACCESS`` behave just like "open" when the player types it, but that's not so: ``OPEN`` can also be used in constructions like "open the door with the brass key", in which case it is understood as the unlocking action. We could add another line to make ``ACCESS`` behave this way too, but if what we really want is to make ``ACCESS`` behave just like ``OPEN``, it's easier simply to say so: Understand the command "access" as "open". This is very useful when adding a new command which needs synonyms: Understand the commands "snap" and "picture" as "photograph". We can check the current stock of commands by looking at the table in the Actions index: for instance, before making ``SNAP`` synonymous with ``PHOTOGRAPH``, it might be wise to check that it is not already defined as a command for breaking something. ## Overriding existing commands ^^{understand (verb) as (action)+assert+} ^^{understanding: verbs} ^^{understand (verb) as something new+assert+} ^^{understanding: removing existing definitions of verbs} ^^{understand nothing as (action)+assert+} ^^{understanding: removing existing definitions of verbs} ^^{|as something new} ^^{(something new), in understanding actions+sourcepart+} ^^{|nothing: in understanding actions} ^^{Actions page of Index panel+ui+} ^^{user interface: Index panel: Actions page} ^^{Index panel+ui+: Actions page} Suppose we are devising specialist commands for a game of whist, and we want ``DISCARD`` as one of them. Looking at the table of commands in the Action index, we find that, inconveniently enough, ``DISCARD`` already has a meaning: it is synonymous with ``DROP``, and while that might be sensible most of the time, it is perfectly wrong now. We need a way to free up ``DISCARD`` for our own use. We can do that by: Understand the command "discard" as something new. This cuts it loose, so to speak, and ready to be given new meanings. If we check the Actions index again, we find no mention of ``DISCARD`` – it is now a blank slate – but ``DROP`` is still exactly as it was. We could now say something like: Understand "discard [something]" as discarding. (If we had declared that ``DROP`` was something new, the whole thing would have happened in reverse, with ``DISCARD`` retaining all of the original grammar. Inform does not distinguish between a command and its synonym.) The `... as something new` sentence works even for a command which did not exist anyway, for instance with: Understand the command "zylqix" as something new. Of course this does nothing – but it is intentional that it generates no problem messages: it means that the sentence can be used to force a command to be fresh and untouched by previous definitions, which might be useful when working with extensions by other people. It is also possible to clear out all the commands leading to a given action: Understand nothing as taking. The commands ``TAKE`` and ``GET`` will still exist, but now they'll only have their other senses (for taking off clothes, for getting out of boxes). ## Standard tokens of grammar {things_token} {TOKENS} ^^{understanding: arbitrary objects} ^^{grammar tokens <-- tokens of grammar <-- understanding: grammar tokens} ^^{grammar tokens: for kinds of thing} ^^{kinds: in grammar tokens} ^^{descriptions (references to things): in grammar tokens} ^^{someone+token+} ^^{something+token+} ^^{something preferably held+token+} ^^{things+token+} ^^{things inside+token+} ^^{other things+token+} ^^{punctuation: slash: separating synonymous words in grammar} ^^{|/: separating synonymous words in grammar} ^^{actions: applying to multiple objects} The square-bracketed parts of `Understand` grammar are called _tokens_. Rather than matching a single specific word, they will normally match a range of possibilities. For example, the grammar `"[number]"` will match ``SIX`` or ``1935``, whereas `"number"` only matches the word ``NUMBER``. Any description of an object can be used as a token: `"[a door]"` matches the name of any door in scope, for example, and `"[an open door]"` matches only those which are currently open. But it is usually not a good idea to write overly specific tokens like this. The command ``DETONATE`` might be intended to be used only with things of the kind `bomb`, for example, but we would still want to _understand_ the command ``DETONATE BANANA``, in order to reject it with a better reply than just ``You can't see any such thing.`` Inform also has a miscellaneous range of useful tokens with special wordings, which the command parser is particularly good at handling well. Between them, they handle all of the commonly-needed cases, so these are the tokens most often used by authors (and by the Standard Rules) in practice. For the most part, they match what their wordings suggest, but command parsing is a finicky business and there are some subtleties which experts occasionally need to be aware of. 1) `"[something]"`. Matches the name of any object in scope. The word "thing" is used colloquially here, and doesn't literally mean the object has to have the kind `thing`. In practice, it almost always will, but the `directions` are also usually in scope, for example. Suppose we `Understand "photograph [something]" as photographing.` An attempt to type ``PHOTOGRAPH NORTHWEST`` will then be understood, because the northwest direction is in scope, but such a command would generate an action which the accessibility rules would immediately reject, saying ``You must name something more substantial.`` So it is hardly ever necessary to worry about the difference, but the token `"[a thing]"` would be stricter, excluding the names of directions. ``PHOTOGRAPH NORTHWEST`` would then be met with ``You can't see any such thing.`` 2) `"[something preferably held]"`. Matches the name of any object in scope, but where there is some ambiguity about which object is being named, prefer something the player is holding. For example: Understand "wear [something preferably held]" as wearing. If the player types ``WEAR HAT``, and is carrying a black hat while there is also a white hat on the table, this command will now be read as referring to the black hat. Otherwise, the command might have been replied to with a ``Which do you mean...?`` question. 3) `"[someone]"`. Matches the name of any person in scope. This is slightly preferable to typing `"[a person]"`. It matches the same possibilities, but when it fails to match, the command parser produces more graceful replies. 4) `"[things]"`. Like `"[something]"`, but allows ``ALL`` or a plural like ``SIX COINS`` to be recognised, resulting in not one object being matched, but many. ``ALL`` will match all of the objects in scope except for the player, for example. The result will be a sequence of actions, one for each match. 5) `"[things preferably held]"`. Like `"[something preferably held]"`, but also like `"[things]"` in that it matches multiple objects. For ``ALL`` the preference for being held would make no difference, but for ``SIX COINS`` it might, in a very coin-rich environment. The command parser will then try to choose as many as possible of the six coins needed from the player, and only then use coins which are merely nearby. 6) `"[things inside]"`. Meaningful only in grammar for actions applying to two things. Matches only what is contained in the thing referred to by the _other_ name in the command. Inform's built-in set of actions use this to recognise ``TAKE ALL FROM THE BOX`` so that the ``ALL`` matches only items which are in the box (and in scope: if the box is opaque and closed, ``ALL`` would match nothing in this case, because the contents would not be in scope). If the Standard Rules had written: Understand "take [things inside] from [something]" as removing. then ``TAKE ALL FROM THE BOX`` would produce matches including the box itself, which is clearly not what the player intended. 7) `"[other things]"`. Meaningful only in grammar for actions applying to two things. Like `"[things]"`, except that it excludes the _other_ name in the command. Again, this is only rarely useful except to the Standard Rules, which uses it to ensure that ``PUT ALL ON TABLE`` does not even try to put the table on the table. (That action would inevitably fail if it were tried, of course, and we don't want to exasperate the player by trying it.) 8) `"[any door]"`, `"[any locked container]"`, `"[any thing]"`, etc. Matches the name of any object of the given kind, completely ignoring scope. Note that `"[anything]"` is read as `"[any thing]"`; `"[anybody]"` and `"[anyone]"` as `"[any person]"`; and `"[anywhere]"` as `"[any room]"`. `any` should be used only with care, and is best when combined with a specific kind which won't be too large. For more, see [Scope]. 9) `"[any things]"`. This should be used only with care. As the wording suggests, this is `any` combined with `"[things]"`, and that is a frightening thought. ``ALL`` would then match a potentially huge number of objects. This is a special case. `any` with another plural — `"[any doors]"`, say — does not do this. 10) `"[text]"`. Matches _anything at all, even gibberish_. This is listed here as a special case because it has to be handled in unusual ways. It gets its own section in this book: see [The text token]. ## Actions applying to kinds of value ^^{understanding: values: numbers} ^^{values: understanding} ^^{understanding: numbers} ^^{numbers: understanding} ^^{number+token+} ^^{grammar tokens: for numbers} ^^{type-checking: in input grammar} Almost all actions apply to things: the player picks them up, pushes them, looks at them and so on. We only occasionally need to recognise other kinds of value, but when we do, we can. For instance: Adjusting it to is an action applying to one thing and one number. Understand "adjust [something] to [a number]" as adjusting it to. The substitution `"[a number]"` matches any number (actually any whole number that is not too large) typed by the player. Inform checks the various kinds being used to make sure that everything matches, so, for instance, this would be disallowed: Understand "adjust [something] to [something]" as adjusting it to. because this grammar line would produce two things, not one thing and one number, which is what we said `adjusting it to` needs. Not every kind can be understood, but many can, including those we create ourselves. For example, if we define: State is a kind of value. Solid, liquid, gas and plasma are states. then we can define an action `applying to one state`, say, and then the token `"[a state]"` would recognise ``SOLID``, ``LIQUID``, ``GAS`` or ``PLASMA`` but no other words. Similarly for: A weight is a kind of value. 10kg specifies a weight. which would enable `"[a weight]"` to match ``27KG``, for example. The issue of "scope" does not arise for values which are not objects. Scope is all about where things are in the physical world, but the number 17, or for that matter the possibility of being a gas, makes equal sense everywhere. So although it's quite legal to write `"[any number]"`, using the `any` to mean anywhere, the effect is exactly the same as writing just `"[a number]"`. ## The text token {text_token} ^^{understanding: arbitrary text} ^^{text+token+} ^^{topics: understanding} ^^{topic understood (- snippet)+glob+} ^^{grammar tokens: for text} ^^{snippets} In the previous section, we saw that `"[number]"` matches any number, and so on for many other kinds of value. So it's natural to wonder: how about text? The answer is that there is indeed `"[text]"` token, but that it does _not_ produce a text value, despite the name. Instead, it produces a value which represents a so-called _snippet_ of a full command. For example, if the player types ``ASK SYBIL ABOUT HELEN OF TROY``, the `"[text]"` token in the grammar for the ``ASK`` command produces the snippet ``HELEN OF TROY``. What can we do with that? In effect the command is only partially parsed: this snippet of the final three words is being left to us to parse later. Here is an example of an action applying to a `topic`: {*}The Enigmatic Void is a room. Getting help about is an action applying to one topic. Understand "help on [text]" as getting help about. Carry out getting help about: showme the topic understood. The word `topic` here is used rather loosely, but is traditional in interactive fiction. If we try the above example, we might see: >HELP ON SPACE TIME CONTINUUM "topic understood" = snippet: SPACE TIME CONTINUUM What happens here is that a special variable called `topic understood` is set equal to the unparsed snippet of the player's command. And this is not a `text` value: it is a `snippet` value. If we want to turn it into a text, we can do so: Carry out getting help about: let T be "[topic understood]"; showme T. ...would instead result in: >HELP ON SPACE TIME CONTINUUM "T" = text: SPACE TIME CONTINUUM So if we wanted to, we could then poke our way through the text character-by-character, and so on. But in fact it's generally annoying to have to do that, which is why Inform gives us the snippet value instead. The snippet is better because we can use the command parser to analyse it further. This is often done with tables of possibilities: see [Topic columns] for worked examples of that. The fact that `"[text]"` can match anything means that it's difficult to tell which version of a command was intended if they disagree only from a `"[text]"` onwards. For example, given: Yelling specifically is an action applying to one topic. Understand "yell [text]" as yelling specifically. Understand "yell [text] at/to [someone]" as answering it that (with nouns reversed). How can Inform know which action to cause if given the command ``YELL GIBBERISH AT MAUREEN``? Is this an instruction to yell ``GIBBERISH AT MAUREEN``, or to yell ``GIBBERISH`` at the luckless Maureen? Inform will usually try the second possibility first, as being the more specific, but there is some risk that the command ``YELL HUZZAH`` may _also_ trigger the second possibility, because of a feature of the command parser called "autocompletion". If Maureen is the only person present, the parser may decide that ``YELL HUZZAH`` was intended for her ears, and read it as if ``YELL HUZZAH AT MAUREEN`` had been the full command. All of this is to say: it's best to avoid situations where `"[text]"` can appear both inside a command and at the end of a command, when the first word is the same. ## Scope ^^{scope} ^^{any+token+} ^^{anywhere+token+} ^^{anybody+token+} ^^{anyone+token+} ^^{anything+token+} ^^{understanding: things: not in scope with (any)+sourcepart+} ^^{grammar tokens: for rooms} ^^{grammar tokens: for things not in scope} ^^{SCOPE+testcmd+} ^^{testing commands: >SCOPE} At first sight, the command parser seems like a component of Inform which ought to look at the words typed, and find a meaning in them, without knowing anything about the state of the story. Suppose the player is in Piccadilly Circus and types ``TAKE CROWN JEWELS``, even though the crown jewels are locked up miles away in the Tower of London. Shouldn't the parser recognise that? It seems like a clearly expressed wish. Of course, the resulting `taking the Crown Jewels` action should not be allowed to happen, but that's an issue for the rules about taking to sort out. It shouldn't be the _parser_ which decides what is and is not allowed to happen. In a way, that seems reasonable. But then consider: * Merely the fact that ``TAKE CROWN JEWELS`` resulted in a reply like ``The crown jewels are in the steel cage.`` rather than ``You can't see any such thing.`` gives an unscrupulous player information which should not be available. * There might be thousands of named things in the story. If all their names have to be recognisable all of the time, the parser will be slower and will handle ambiguous requests less well. If the story begins in a child's bedroom in 1971 and the player types ``GET SPACESHIP``, a reply like ``Which do you mean, the toy spaceship or Apollo 14?`` is unfortunate. Instead, then, the parser normally only recognises names of objects which are somehow close to where the player currently is in the story. This restricted sort of access to the world is called "scope", and objects which are "in scope" are the currently nearby ones whose names would be recognised. But it is not a restriction on what actions can or cannot happen. It is a restriction on what names are recognised in commands. Most authors can forget about scope almost all of the time, and just let the parser do its thing. But every so often, it's useful to be able to tinker with what is, and is not, in scope. A good way to get a sense of this is to wander around any story with much to it and type the debugging command ``SCOPE`` from time to time, which will list what's in scope to the player at any given point. (In principle, scope applies to anybody, even though other characters do not get to type commands. In a game where the player is Sherlock Holmes, Professor Moriarty will have a scope of his own. Most of the time these will be different.) So, then, tokens like `"[something"]` or `"[someone]"` or even `"[an open door]"` only match the names of objects which are in scope. (See the section on [Standard tokens of grammar].) But we do sometimes want to enable commands to mention things from far away, or which are even out of play altogether. The simplest way to do that is to use `any`. For example, the following gives the player the ability to walk between rooms without giving explicit directions of movement. Going by name is an action applying to one thing. Carry out going by name: say "You walk to [the noun]."; move the player to the noun. Understand "go to [any adjacent visited room]" as going by name. In a finished work, we would want ``GO TO`` to produce helpful errors if non-adjacent but visited rooms were named, and so on, but the important point here is that `any` has placed certain room names in scope, something which ordinarily never happens. As might be expected, `"[anything]"` means the same as `"[any thing]"` (and because of that is required to match a `thing`, unlike `"[something]"`, which can match any object); `"[anybody]"` and `"[anyone]"` mean the same as `"[any person]"`; and `"[anywhere]"` means the same as `"[any room]"`. So, then, `any` allows scope restrictions to be completely bypassed. We can also modify scope in more nuanced ways with the [Deciding the scope of something] activity. But supposing we don't do that, what exactly _is_ in scope for a given actor? That's the subject of the next section. ## Formal definition of scope This section can safely be skipped by most Inform authors, but for experts it provides answers to questions like "exactly what is visible to the player?", or "when exactly is this action in the presence of somebody?". ### When scope is used by Inform As we have seen, scope is an idea of nearby-ness which is used by the command parser to see which names to recognise in commands. The command ``TAKE HOLY GRAIL`` will be understood only if the Holy Grail is in scope, and so on. Scope roughly means "within sight or touch", but only roughly. It's used in Inform in other places too: * To define the `visibility relation`. `A` can see `B` if: - there is light where `A` is, _and_ - `B` is in scope for `A`. * To define the `audibility relation`. `A` can see `B` if `B` is in scope for `A`. * To define the `touchability relation`. `A` can touch `B` if: - `B` is in scope for `A`, _and_ - the accessibility rulebook does not prevent this. * To decide whether an action is happening `in the presence of` something or somebody. For example, this rule will take effect if and only if the sarcophagus is in scope for the player: Before doing something in the presence of the sarcophagus: say "The mummy shakes the sarcophagus menacingly." ### Main scope definitions The following method determines scope, provided that the activity [Deciding the scope of something] has not pre-empted or added to it. 1) When the command parser is matching the special `"[things inside]"` token: - (1a) The other item named by the command is searched for scope. Note that that other item will have to have been in scope, or this would never be considered. 2) Otherwise, if the actor is the player and it is dark where the player is: - (2a) All directions are in scope. - (2b) The player is _both_ in scope _and_ searched for scope. - (2c) If the player is inside or on top of something, that container or supporter is in scope. 3) Otherwise, if the actor is out of play: - (3a) All directions are in scope. - (3b) The actor is in scope. 4) Otherwise: - (4a) All directions are in scope. - (4b) The actor's scope ceiling is searched for scope. The _scope ceiling_ is worked out by going "up one level" to whatever supports or contains the actor, and repeating this process until we reach either a room or a closed opaque container. - (4c) If the actor is inside or on top of something, that container or supporter is in scope. 5) When a thing or room is _searched for scope_: - (5a) If it is a person, anything it carries or wears but does not conceal is _both_ in scope _and_ searched for scope. - (5b) If it is a supporter, anything it supports but does not conceal is _both_ in scope _and_ searched for scope. - (5c) If it is a room, anything it contains but does not conceal is _both_ in scope _and_ searched for scope. - (5d) If it is a container which is either open or transparent, anything it contains but does not conceal is _both_ in scope _and_ searched for scope. - (5e) Concealment is determined by the [Deciding the concealed possessions of something] activity, but by default nothing is concealed. 6) When something is in scope, anything it incorporates is in scope. ### How light and darkness are determined Even that is not everything, because we still have to say how Inform decides whether there is light or darkness where an actor is. 7) There is light where an actor is if the room, container or supporter of the actor offers light. If not, or if the actor is out of play, there is darkness. 8) An object _offers light_ if _any of the following_: - it is a `lit` thing; - it is a `lighted` room; - it contains, supports, wears, carries or incorporates something which has light; - it is supported, worn, carried or incorporated by something which offers light; - it is contained by a room which offers light; - it is contained by an open or transparent container which offers light. 9) A thing _has light_ if _any of the following_: - it is `lit`; - it supports, carries or wears something which has light; - it is an open or transparent container which contains something which has light. The gist of rules (7) to (9) here is that there is light for the actor if there's a light source somewhere in the room, provided that no closed opaque container makes a barrier between the actor and the light source. ### Hypotheticals Here are some hypothetical scenarios, to show how these rules more or less realistically approximate real-life experience. Suppose we are in the British Museum courtyard, where there's a sarcophagus and a packing case, which contains a Canopus jar. It is mid-afternoon. The player, in the true spirit of Lord Elgin, is plundering the place and is now inside the packing case. - Suppose the case is closed, and it's dark inside. The case itself _is_ in scope, which prevents ``ENTER CASE`` followed by ``CLOSE CASE`` leaving a player unable to escape because ``OPEN CASE`` won't be recognised. But the Canopus jar is now out of scope. If the player carries a rucksack with a coil of rope inside, both are in scope. - Same scenario, but this time the player has a torch. Now the case behaves just like a little room of its own, except that (4c) means the case itself is in scope. The jar is now in scope. - Same scenario, but now the packing case is made of transparent perspex instead of wood. Now even the sarcophagus is in scope, on the grounds that the player can see it through the walls of the container. Note that rule (4b) means that the room containing the player is never itself in scope, even when (as is usually the case) it is the player's "scope ceiling". Its contents are in scope, but it itself is not. So in all of these scenarios, ``EXAMINE BRITISH MUSEUM`` will be disallowed because ``BRITISH MUSEUM`` is not the name of something in scope. Rule (6) looks straightforward but has some caveats: - If the player is wearing a hat and a small green feather is part of the hat, then both the hat and the feather are in scope, even in the dark. - If the packing case has a metal clasp which is `part of` it, then the clasp is in scope both inside and outside the case. This may be a helpful start when experimenting with such hypotheticals: {*}"Some Scope for Misunderstandings" The British Museum is a room. A sarcophagus is in the British Museum. The case is an open openable enterable opaque container in the British Museum. A Canopus jar is in the case. The torch is a device. The player is carrying the torch. Carry out switching on the torch: now the torch is lit. Carry out switching off the torch: now the torch is not lit. The player wears a felt hat. A green feather is part of the hat. The player carries a rucksack. In the rucksack is a coil of rope. Test me with "showme / enter case / close case / showme / switch on torch / showme". ## Understanding names ^^{understand (nouns) as (thing)+assert+} ^^{understanding: things: specific things} ^^{plurals: understanding (in commands)} ^^{|plural of: in player command} ^^{understanding: synonyms} ^^{use options: catalogue: |no automatic plural synonyms} ^^{no automatic plural synonyms+useopt+} So far in this chapter, Understand sentences have been used to give names to actions, but they can also be used to name objects – in particular, things and rooms. This normally happens automatically. For instance, writing The St Bernard is an animal in the Monastery Cages. means that the command parser recognises ``ST BERNARD`` as referring to the dog. It also recognises ``BERNARD`` and ``THE ST BERNARD`` and even ``ST``, and some other variations too. Some of those variations look a little odd, but the command parser takes the view that it is better to accept some strange commands which players will never type than to reject reasonable ones which they might. And in that spirit, it would be good to accept a command like ``EXAMINE DOG``. One way we could do this is to write: Understand "dog" as the St Bernard. When a kind is created, Inform generates a plural of the kind's name. When objects of that kind are created, it's automatically the case that commands can refer to any of those objects by that plural name. For instance, given... The Lake is a room. A duck is a kind of animal. Four ducks are in the Lake. ...the player can type ``TAKE DUCKS`` to try to pick up all four. Once again the automatic behaviour can be enhanced: Understand "birds" and "ruddy ducks" as the plural of duck. Now ``TAKE BIRDS`` and ``TAKE DUCKS`` are equivalent. Plurals can even, strange as it may seem, be given for single things: The magpie is in the Lake. Understand "birds" as the plural of the magpie. And now ``TAKE BIRDS`` tries to take all four ducks and the magpie too. In fact, it is the norm that any given thing can be referred to by the plural of its kind name. ``EXAMINE ANIMALS`` would scrutinise the St. Bernard, even if it were alone, but would not automatically work for the ducks: things only receive the plural name of the most specific kind to which they belong. If you don't want this behaviour, it can be suppressed with a use option: Use no automatic plural synonyms. ## Understanding kinds of value {var_understood} ^^{understanding: values: kinds of value} ^^{values: kinds of value: understanding} ^^{understanding: numbers} ^^{numbers: understanding} ^^{number+token+} ^^{grammar tokens: for numbers} ^^{number understood (- number)+glob+} ^^{((kind)) understood (- kind of value)+glob+ --> understood} ^^{grammar tokens: for kinds of value} ^^{time+token+} ^^{time period+token+} In many cases, if K is the name of a kind of value, then Inform automatically makes an Understand token called `"[K]"` which matches only values of K. An example is `"[number]"`, which matches text like 203 or ``SEVEN``. There is a chart of the kinds of value in the Kinds index for a project, showing which ones can be understood in this way. In particular, any newly created kind of value can always be understood. We make good use of that in the example story "Studious": {*}"Studious" The Studio is a room. "The unreal world of the photographic studio, full of fake furniture, cantilevered stands and silver-white shades like miniature parachutes." The lumpy black camera is in the Studio. "A lumpy black camera hangs from a tripod." The rake-thin model is a woman in the Studio. "A rake-thin model, exquisitely bored and boringly exquisite, angles herself indolently." Limb is a kind of value. The limbs are left leg, left arm, right leg and right arm. Detailing is an action applying to one limb and one visible thing, requiring light. Check detailing: if the camera is not carried then say "You can hardly photograph without a camera, now can you?" instead. Report detailing: say "Click! You take a detail photograph of the [limb understood] of [the second noun]." Understand "photograph [limb] of [a person]" as detailing. Test me with "get camera / photograph left leg of model". Note the way we can refer to the limb mentioned by the player as the `limb understood`. Similarly, we could talk about the `number understood` if the value parsed had been a number, and so on. When commands need to talk about time, we need to remember that `"[a time]"` matches a value of the `time` kind — times of day, such as ``10:15 AM`` or ``MIDNIGHT``. By contrast, `"[a time period]"` matches a value of `time period`, such as ``10 MINUTES`` or ``AN HOUR``. So we would likely want: Understand "wait until [a time]" as ... Understand "wait for [a time period]" as ... in order to recognise ``WAIT UNTIL 10:20 AM`` and ``WAIT FOR TEN MINUTES``, respectively. ## Commands consisting only of nouns ^^{understanding: sentences without verbs} ^^{understanding: noun-first sentences} ^^{answering (actor)+action+} In every example so far, and in almost all practical cases, the first word in a command which results in an action will be something fixed: a verb, in fact. When we write Understand "photograph [something]" as photographing. we are saying that the first word of such a command will always be ``PHOTOGRAPH``. Occasionally, though, we would like to understand a noun as a command, perhaps in a situation where the command is obvious. If we say: Understand "[something]" as examining. then the command ``EXAMINE`` will be implicit when the player types a bare noun: ``` transcript A red box and a blue ball are here. > BALL The blue ball is plaited from many small leather patches. ``` so that the command ``BALL`` has resulted in the action `examining the blue ball`. This is a feature which should be used sparingly, since it could easily lead to confusion if not carefully explained to the player. By default, it is not used at all. It also has what may be a serious limitation: verbless commands like this work only when typed by the player as actions to follow – they do not work as instructions for other people. So for instance ``SVEN, BALL`` would not ask Sven to try examining the ball – instead it would generate the action `answering ball to Sven`. (This is because the Inform parser decides whether ``PERSON, SOME TEXT`` is a request or just conversation by looking at the first word after the comma to see if it's a command.) ## Understanding values {PM_UnderstandAsQualified} {PM_UnderstandPluralValue} ^^{understand (nouns) as (thing)+assert+} ^^{understanding: values} ^^{understanding: kinds of things} ^^{understanding: things: kinds of things} ^^{understanding: synonyms: for things and values} ^^{grammar tokens: for kinds of value} `Understand` can be used to supply new ways to talk about both things and other values. For instance, if we create: A brass lantern is in the Building. then it can be called ``BRASS``, or ``LANTERN``, but not ``LAMP``: Inform does not really know what these words mean, and has no grasp of synonyms. We can arrange for ``LAMP`` to work as well like so: Understand "lamp" as the lantern. Understand "old lamp" as the lantern. It is not ordinarily the case that a thing can be called by the name of its kind: if we put a woman called April into a room, then she can usually be called ``APRIL``, but not ``WOMAN``. (The exception is when we do not specify any name for her – in that case, Inform will give up and call her just ``WOMAN``. Also, Inform _does_ allow the plural name of a kind to be used. ``TAKE THREE COINS`` would pick up three different things of the kind `coin`, if that were a kind, and if there were three of them to hand.) With care, we can do the same trick for entire kinds of thing at once. So there is not usually any form of words which can refer to anything of a given kind. If we should want this, we have to say so explicitly: Understand "machine" as a device. Device is a kind, so now the word ``MACHINE`` can be used to refer to any device: if there are two in the same place, the result might play out like so: > SWITCH MACHINE ON Which do you mean, the bale twiner or the grain thresher? > TWINER You watch absorbed as a perfect cube of hay is trussed up like a parcel. Similarly, we might conceivably want to allow new ways to recognise values – in this case, a number: Understand "eleventy-one" as 111. When making complicated names, we need to watch out for the possibility of writing a definition which will cause Inform to go around in circles (something which will show up as a "Too many activities at once" run-time problem). For instance, Understand "[thing] substitute" as the placebo. will fail because Inform, working left to right, needs to look for every possible object name before it can progress: one possibility is the placebo itself: to check that, it needs to look for every possible object name: and so on, never finishing. A definition like this one very likely matches too much in any case (would we really want to accept ``PLACEBO SUBSTITUTE`` or ``CIGARETTE SUBSTITUTE SUBSTITUTE SUBSTITUTE`` here, as the definition implies?). ## This/that {PM_OverAmbitiousSlash} {PM_SlashedCommand} ^^{understanding: synonyms} ^^{punctuation: slash: separating synonymous words in grammar} ^^{|/: separating synonymous words in grammar} ^^{punctuation: double-dash: optional words in Understand grammar} ^^{|--: optional words in Understand grammar} We have already seen `or` used in `Understand` sentences: Understand "scarlet" or "crimson" as red. For convenience, `and` can also be used instead of `or` here: Understand "scarlet" and "crimson" as red. In general, any number of alternative forms can be given which are to be understood as the same thing (in this case the colour red). When the alternatives are in any way complicated, `or` should always be used, but a shorthand form is allowed for simple cases where it is only a matter of a single word having several possibilities: Understand "reach underneath/under/beneath [something]" as looking under. This is shorthand for: Understand "reach underneath [something]" or "reach under [something]" or "reach beneath [something]" as looking under. Which in turn is shorthand for: Understand "reach underneath [something]" as looking under. Understand "reach under [something]" as looking under. Understand "reach beneath [something]" as looking under. It's possible also to make that second word optional: Understand "reach underneath/under/beneath/-- [something]" as looking under. because `--` is read by Inform as "no word at all". If `--` is an option, it can only be given once and at the end of the list of possibilities. To recapitulate: the slash `/` can only be used between single, literal words, or between the next to last word and `--`. It is best for the wayward prepositions of English (`in/into/inside`, and so forth). For anything more complex, always use `or`. ## New tokens {PM_MixedOutcome} {PM_TwoValuedToken} {NEWTOKENS} ^^{understanding: synonyms: as grammar tokens} ^^{grammar tokens: defining} ^^{defining: grammar tokens} ^^{punctuation: slash: separating synonymous words in grammar} ^^{|/: separating synonymous words in grammar} Inform provides a stock of tokens to use which, between them, cover most needs pretty well: see [Standard tokens of grammar]. But like most aspects of Inform, this can be extended with new tokens to the author's design. Why might this be convenient? Mainly to avoid repetition. For example, suppose we have to set up multiple commands like ``PLACE CUSHION AGAINST BOMB`` or ``PUSH CUSHION AGAINST BOMB``, but we want to make sure the player will get the same result with a whole variety of possible variations on this. It would be repetitive to write: Understand "place [something] beneath/under/by/near/beside/alongside/against [something]" as placing. Understand "place [something] next to [something]" as placing. Understand "place [something] in front of [something]" as placing. Understand "push [something] beneath/under/by/near/beside/alongside/against [something]" as placing. Understand "push [something] next to [something]" as placing. Understand "push [something] in front of [something]" as placing. What's really going on here is that we want to accept a slew of different prepositions as being equivalent to each other in these two verbs. So this is more elegant: Placing it against is an action applying to two things. Understand "beneath/under/by/near/beside/alongside/against" or "next to" or "in front of" as "[against]". Understand "place [something] [against] [something]" as placing it against. Understand "push [something] [against] [something]" as placing it against. So this example creates an entirely new grammar token, `"[against]"`, and then makes use of it twice. Unlike the tokens seen so far in this chapter, this token does not match an object or a value: it simply matches some fixed wording, and does not record which variant on this fixed wording the command contained. So the line Understand "place [something] [against] [something]" as placing it against. produces just two things, as the `placing it against` requires, despite the fact that three tokens are present. (But see the next section for how to define a new token which _does_ produce a value.) Something to be aware of, as with other grammar, is that the slash `/` indicates a choice between words only, not between entire phrases. For instance, if we had tried: Understand "beneath/next to/in front of" as "[against]". then this would have matched ``BENEATH TO FRONT OF``, ``NEXT TO FRONT OF``, ``BENEATH IN FRONT OF``, or ``NEXT IN FRONT OF``, but nothing else. It means "a choice of ``BENEATH`` or ``NEXT``, then a choice of ``TO`` or ``IN``, then ``FRONT``, then ``OF``. If in doubt, it's better to use `or` to spell things out: Understand "beneath" or "next to" or "in front of" as "[against]". ## Tokens can produce values ^^{understanding: values: grammar tokens producing values} ^^{grammar tokens: producing values} ^^{defining: grammar tokens: producing values} ^^{values: kinds of value: understanding} ^^{type-checking: in grammar tokens} The examples just seen were tokens which simply matched specific words typed by the player, but newly created tokens can also produce values: Colour is a kind of value. The colours are red, green and blue. Understand "colour [a colour]" or "[a colour] shade" as "[tint]". Here the `"[tint]"` token matches, for instance, `colour red` and `blue shade`, which would result in the values red and blue, respectively. Tokens are not allowed to produce more than one value, and if several patterns are given to define them then those patterns have to be compatible. That means the following is disallowed, since it might work out to a colour, or to an object, leaving Inform unable to judge whether an action can safely be applied to the result. Understand "colour [a colour]" or "[something]" as "[tint]". ## Understanding things by their properties {PM_UnknownUnderstandProperty} {PM_BadUnderstandProperty} {PM_BadUnderstandPropertyAs} {PM_BadReferringProperty} {PM_UnknownUnpermittedProperty} ^^{understanding: properties as describing things} ^^{understanding: things: by properties} ^^{properties: understanding things by properties} ^^{understand (nouns) as (thing)+assert+} ^^{understand (property) as describing/referring to (thing)+assert+} ^^{(describing), in (understand as)+sourcepart+} ^^{(referring to), in (understand as)+sourcepart+} Items are ordinarily understood only by their original given names. For instance, if we have: In the Herb Garden is a china pot. then the player could refer to this as ``POT``, ``CHINA POT`` or ``CHINA``. We can embellish this by adding extra forms: Understand "chinese pot" or "chinese vase" as the china pot. But suppose the pot changes its nature in the course of play? If we have: The china pot can be unbroken or broken. The china pot is unbroken. After dropping the china pot: say "Crack!"; now the china pot is broken; now the printed name of the pot is "broken pot". So now the player would reasonably expect to call it ``BROKEN POT``, a wording which would have been rejected before. We can achieve this by writing: Understand the unbroken property as describing the pot. which allows ``UNBROKEN`` or ``BROKEN`` to describe the pot, depending on its state. And, since the player might well use a different adjective but with the same idea in mind, we can even add: Understand "shattered" or "cracked" or "smashed" as broken. Understand "pristine" as unbroken. This is something of a toy example, but the feature looks rather more useful when there are more pots than just one: {*}"Terracotta" A flowerpot is a kind of thing. A flowerpot can be unbroken or broken. Understand the broken property as describing a flowerpot. After dropping an unbroken flowerpot: say "Crack!"; now the noun is broken; now the printed name of the noun is "broken flowerpot"; now the printed plural name of the noun is "broken flowerpots". The Herb Garden is a room. In the Herb Garden are ten unbroken flowerpots. We then have the dialogue: ``` transcript Herb Garden You can see ten flowerpots here. > GET TWO FLOWERPOTS flowerpot: Taken. flowerpot: Taken. > DROP ALL flowerpot: Crack! flowerpot: Crack! > LOOK Herb Garden You can see two broken flowerpots and eight flowerpots here. > GET AN UNBROKEN FLOWERPOT Taken. ``` and so on and so forth. There are in fact two slightly different forms of this kind of sentence: Understand the broken property as describing a flowerpot. Understand the broken property as referring to a flowerpot. The only difference is that in the `describing` case, the property's name alone can mean the thing in question – so ``TAKE UNBROKEN`` will work; whereas, in the `referring to`, the property's name can only be used as an adjective preceding the name of thing itself – so ``TAKE UNBROKEN FLOWERPOT`` will work but ``TAKE UNBROKEN`` will not. ## Understanding things by their relations {PM_GrammarObjectlessRelation} {PM_GrammarBadRelation} {PM_GrammarValueRelation} ^^{understanding: relations as describing things} ^^{understanding: things: by relations} ^^{relations: understanding things by relations} ^^{understand (nouns) as (thing)+assert+} ^^{(related by), for understanding things by relations+sourcepart+} ^^{something related by (relation)+token+} Sometimes it makes sense for the name of something to involve the names of other things to which it is related. For instance, if we say ``TAKE THE BOTTLE OF WINE``, we mean that the bottle currently contains wine – if it were the very same bottle containing water, we would call it something else. For names which must involve related names, a special form of token is provided. For instance, we could say: A box is a kind of container. Understand "box of [something related by containment]" as a box. The Toyshop is a room. The red box is a box in the Toyshop. Some crayons are in the red box. and now ``TAKE BOX OF CRAYONS`` will work, because ``CRAYONS`` matches against `"[something related by containment]"` for the red box – or it does for as long as the crayons are there. We can have similar matches against relations of all kinds, but have to name the relation explicitly. (See the examples at the end of this section for plenty of cases.) Note that ``BOX OF CRAYONS`` in this example is a single item. The command ``EXAMINE BOX OF CRAYONS`` generates the action `examining the red box`, because that is the one currently containing the crayons. We could instead have written: Understand "home of the [something related by containment]" as a box. and then ``EXAMINE HOME OF THE CRAYONS`` would have worked instead, but would again have generated the action `examining the red box`. We can also reverse the sense. If we write: A box is a kind of container. Understand "box in [something related by reversed containment]" as a box. The Toyshop is a room. The crate and the hammock are in the Toyshop. In the crate is a box. In the hammock is a box. then ``TAKE THE BOX IN THE HAMMOCK`` will work: here, the relation goes the other way, because the box is being contained by the other-named item, rather than doing the containing. The following example demonstrates a subtle trap: Understand "[something related by R]" as a thing. where `R` is a relation where certain things are related to themselves. For example, that would happen with: Understand "[something related by visibility]" as a thing. This would mean that the Toymaker, say, can be referred to by the name of any object visible to the Toymaker. The result is that the parser goes in endless circles: when trying to match text against the possible names of the Toymaker, it sees that it ought to match against the names of everything visible to the Toymaker. But that includes the Toymaker himself. So the parser needs to match the possible names of the Toymaker. So... and so on, without end. This trap can be avoided either by using a relation which will not loop the parser into circles like this, or by using grammar which begins with some fixed wording. This, for example: Understand "viewer of [something related by visibility]" as a thing. works fine, because now the parser trying to match a name will look first for ``VIEWER OF`` up front, and only then try to match a name against the rest. This process could go on a while (``EXAMINE VIEWER OF VIEWER OF VIEWER OF VIEWER OF VIEWER OF VIEWER OF VIEWER OF VIEWER OF TOYMAKER``), but not forever, because each fresh round of name-parsing consumes two of the words, and the words eventually run out. ## Context: understanding when {PM_BadWhen} ^^{when (condition)+sourcearg+: arbitrary conditions for (understand)+sourcepart+} ^^{understanding: conditionally} ^^{understanding: limiting cases where understand rules apply} ^^{understanding: (when) clauses for+sourcepart+} ^^{conditions: for (understand)+sourcepart+} ^^{publicly-named / privately-named (object)+adj+} ^^{privately-named / publicly-named (object)+adj+} ^^{item described (- object)+glob+} We have now seen several different forms of `Understand` sentence: for instance, Understand the colour property as describing a building block. Understand "mix [colour] paint" as mixing paint. Understand "rouge" as red. Understand "curious girl" as Alice. Any of these may optionally have a condition tacked on: for instance, Understand "mix [colour] paint" as mixing paint when the location is the Workshop. Understand "rouge" as red when the make-up set is visible. In principle, `when ...` can take in any condition at all. In practice a little care should be exercised not to do anything too slow, or which might have side-effects. (For instance, referring the decision to a phrase which then printed text up would be a bad idea.) Moreover, we must remember that the `noun` and `second noun` are not known yet, nor do we know what the action will be. So we cannot safely say `when the noun is the fir cone`, for instance, or refer to things like `the number understood`. (We aren't done understanding yet.) If we want more sophisticated handling of such cases, we need to write checking rules and so on in the usual way. Contexts can be useful to make sense of things having different names depending on who is being spoken to, as here: Understand "your" as a thing when the item described is held by the person asked. With this rule in place ``FRODO, GIVE ME YOUR RING`` means that Frodo will know which ring is meant, even if there are a couple of dozen other rings present. If the name of something has to change completely, perhaps because the player's understanding of events has changed completely, then Inform's standard way of handling names can be a nuisance. When an item or room is created, Inform automatically makes its name understood as referring to it (in fact, it makes each individual word in that name understood). For instance, The Wabe is a room. The blue peacock and the sundial are in the Wabe. means that the player can type ``EXAMINE BLUE PEACOCK`` or ``PUSH SUNDIAL`` or ``SHOWME WABE`` or ``TAKE BLUE``, and so on. This is almost always a good thing, and here there's no problem, because peacocks and sundials are not usually disguised. But here is a case where a disguise is needed: The ZZ91 file is a privately-named thing in the drawer. The printed name of ZZ91 is "[if the ZZ91 file is handled]secret document[otherwise]dusty paper". Understand "dusty" and "paper" as ZZ91 when ZZ91 is not handled. Understand "secret" and "document" as ZZ91 when ZZ91 is handled. After taking ZZ91 for the first time: say "Heavens! It is a secret document! You blow the dust right off it!" Despite the clandestine sound of the property `privately-named`, all it means is that Inform creates the object (here, the `ZZ91 file`) without automatically Understanding the words in its name (``ZZ91``, ``FILE``) as referring to it. This doesn't mean the player can never interact with it: for one thing, ``TAKE ALL`` would pick it up. It just means that the only `Understand` grammar attached to the object will be what the author explicitly declares. So in this case, the file can be called ``DUSTY``, ``PAPER`` or ``DUSTY PAPER`` before it is taken, but not after; and can be called ``SECRET``, ``DOCUMENT`` or ``SECRET DOCUMENT`` after. The reverse property is `publicly-named`, which is the default. `Privately-named` only affects how Inform _compiles_ the object, so it can't usefully be given or taken away during play. As in the example above, `Understand ... when ...` is the way to change names during play. ## Changing the meaning of pronouns ^^{pronouns: setting pronouns} ^^{(IT), in player commands+commandpart+} ^^{pronouns: (IT), in player commands+commandpart+} ^^{(THEM), in player commands+commandpart+} ^^{pronouns: (THEM), in player commands+commandpart+} ^^{(HIM), in player commands+commandpart+} ^^{pronouns: (HIM/HER), in player commands+commandpart+} ^^{(HER), in player commands+commandpart+} ^^{ambiguously plural (thing)+propcat+} The pronouns ``IT``, ``HIM``, ``HER`` and ``THEM`` are constantly adjusted during play, to save the player time when typing commands. If the player types ``EXAMINE NECKLACE`` on one turn, it's sufficient to type ``TAKE IT`` on the next, and ``IT`` will be understood as meaning whatever ``NECKLACE`` meant last turn. (``IT`` will be set for things with singular names, but ``THEM`` for things with plural names. Both at once will be set for a thing which has been given the `ambiguously plural` property - for example, so that ``EXAMINE BASKET OF ROLLS`` would set both ``IT`` and ``THEM`` to the basket-of-rolls thing if that had been made `ambiguously plural`.) All of that happens automatically, but once in a while the result can be unfortunate. Suppose that when the player examines the necklace, a security system automatically drugs her unconscious, and she wakes up in a cell, hours later, and is told that the cell is bare except for a key on the floor. If she types ``TAKE IT``, she clearly doesn't mean ``IT`` to mean the necklace any more; she means the key. Inform's parser can't make guesses like this, so the following phrase can be used to help it. > phrase: {ph_setpronouns} set pronouns from (object) > > This phrase adjusts the meaning of pronouns like IT, ``HIM``, ``HER`` and ``THEM`` in the command parser as if the object mentioned has become the subject of conversation. Example: the combination of > > set pronouns from the key; > set pronouns from Bunny; > > might change ``IT`` to mean the silver key and ``HIM`` to mean Harry "Bunny" Manders, while leaving ``HER`` and ``THEM`` unaltered. ## Does the player mean... {rules_dtpm} ^^{does the player mean+rb+} ^^{+toout+it is likely / possible / unlikely (does the player mean)} ^^{+toout+likely / possible / unlikely, it is likely / possible / unlikely (does the player mean) <-- |very likely / unlikely} ^^{+toout+unlikely / possible / likely, it is unlikely / possible / likely (does the player mean)} ^^{+toout+possible / likely / unlikely, it is possible / likely / unlikely (does the player mean)} ^^{disambiguation: of player commands <-- understanding: disambiguation} When the player types an ambiguous reference, we need to work out what is meant. Consider the following source text: The Champs du Mars is a room. The great Eiffel Tower is here. "The great Tower stands high over you." The souvenir model Eiffel Tower is here. "Comparatively tiny is the souvenir version." Now suppose the player types ``GET TOWER``. The response will be: ``` transcript Which do you mean, the great Eiffel Tower or the souvenir model Eiffel Tower? ``` Which is a silly question, exposing our work of IF as something artificial. It's obvious to the author of the source text, and to the player, that the souvenir must be what is meant: but this is not obvious to the computer program running the story. Works of IF gain a subtle feeling of quality from being able to understand ambiguous references of the kind above, and Inform provides us with a way to do this by giving the parser clues in the form of `Does the player mean...` rules. For instance, if we add: Does the player mean taking the great Eiffel Tower: it is very unlikely. then the response to ``GET TOWER`` will now be: ``` transcript (the souvenir model Eiffel Tower) Taken. ``` `Does the player mean...` rules look at the actions which are possible interpretations of what the player typed, and grade them according to how likely they seem. (Note that these rules are only ever used to handle ambiguities: if the player unambiguously types ``GET GREAT EIFFEL TOWER``, that will be the action. And the rules are only used where they are able to make a decision: if there are still multiple equally plausible meanings, the parser will ask about all possibilities, not just the most likely ones.) Rules in this rulebook can either decide nothing, or come up with one of the following verdicts: - `it is very likely` - `it is likely` - `it is possible` - `it is unlikely` - `it is very unlikely` If there are no `does the player mean` rules, or the rules make no decision on a given possible action, it will be ranked as `it is possible`. We may use these rules to affect all sorts of interaction with a specific object or kind of object, as in Does the player mean doing something with the cursed dagger of Thog: it is very unlikely. Does the player mean doing something with the cursed dagger of Thog when the player is hypnotised: it is likely. ...and so on. Notice that we can also make rules about actions that apply to two objects, so for instance: Does the player mean throwing the can of shoe polish at the shoe polish vending machine: it is likely. which nicely clarifies ``THROW POLISH AT POLISH``, but does not comment on the likelihood of throwing the can at other things or of throwing other things at the vending machine. Moreover, the (suspected) identity of the first item will be known when the rule is consulted; thus Does the player mean tying the noun to the noun: it is very unlikely. will tell Inform to prefer not to tie something to itself if other interpretations are available. But there is a caveat. There are some cases where this mechanism will not in fact help Inform to choose its way out of an ambiguous command, because of the way it parses one noun at a time. It usually needs to understand the first noun before it will even try to make sense of the second. So a rule like: Does the player mean throwing the can of shoe polish at the tree: it is likely. may not work if the player types ``THROW POLISH AT TREE`` and ``POLISH`` is ambiguous, because when the parser is trying to understand ``POLISH``, it hasn't yet seen to the end of the command and realised that the second noun will be the tree; so the second noun is unset and the rule won't match. As a caveat to the caveat, the `inserting it into`, `removing it from` and `putting it on` actions have this slightly back to front. These are parsed using the (little-used) `"[other things]"` or `"[things inside]"` tokens, and the Inform parser tries to detect the second noun before the first one, since the identity of the first has to depend on the second. So for instance if the situation contains `an oak tree` and also `an oak chest`, we could write: Does the player mean inserting into the oak chest: it is very likely. which would successfully make ``PUT COIN IN OAK`` mean the chest, not the tree. (Note the way we write `inserting into` without saying anything about what's being inserted, not even that it's `something`.) ## Multiple action processing ^^{lists: the multiple object list} ^^{actions: multiple action processing} ^^{rulebooks: multiple action processing rules} When the player types a command like ``DROP ALL``, this is (usually) a request to carry out more than one action. After the command parser has decided what constitutes ``ALL`` (a process which can be influenced using the `deciding whether all includes` activity), it forms up a list and then runs through it, starting an action for each in turn. The result usually looks something like this: > GET ALL foxglove: Taken. snake's head fritillary: Taken. However, by adding rules to the `multiple action processing rulebook`, we can take a look at the actions intended, and rearrange or indeed change them before they take effect. To do that, we have to deal with a special list of objects. For two technical reasons this isn't stored as a `list of objects that varies` – first because it needs to exist even in low-memory situations where we can't afford full list-processing, and second because there are times when changing it might be hazardous. Instead, two phrases are provided to read the list and to write it back: > phrase: {ph_multipleobjectlist} multiple object list ... list of objects > > This phrase produces the current multiple object list as a value. The list will be the collection of objects found to match a plural noun like ``ALL`` in the most recent command typed by the player. If there is no multiple object, say if the command was ``TAKE PEAR``, the list will be empty: it won't be a list of size 1. > phrase: {ph_altermultipleobjectlist} alter the/-- multiple object list to (list of objects) > > This phrase sets the multiple object list to the given value. The list is ordinarily the collection of objects found to match a plural noun like ``ALL`` in the most recent command typed by the player, but using this phrase at the right moment (before the `generate action rule` in the turn sequence rules takes effect). ## Understanding mistakes ^^{mistakes, in the player's command} ^^{understand (words) as a mistake+assert+} ^^{understanding: mistakes} ^^{actions: understanding as mistakes} ^^{punctuation: brackets: for defining mistakes} ^^{|( ): for defining mistakes} ^^{text+token+: in understanding mistakes} ^^{testing commands: comments in transcripts from beta testers} ^^{comments: in transcripts from beta testers} When inspiration strikes the player, they can usually be relied upon to make a good-faith effort to communicate the new idea: they will guess the right command. If they guess wrongly, the mistake is probably the author's, because a good author will try to anticipate all possible wordings and make all of them work. Nevertheless it is sometimes good practice to nudge the player towards the right wording – particularly if the player has the right idea but is not explicit enough: for instance, typing ``TALK TO JUDGE`` when we really want to know what is to be said (``JUDGE``, ``GUILTY``); or if the player tries something like ``PLAY CHESS`` rather than ``MOVE PAWN TO KING 4``. Similarly, if we make a casual reference such as "In your childhood days, you loved sliding in stocking feet across this hallway", a player might type ``SLIDE IN STOCKING FEET``: a nice idea, and which deserves a nice response, even though it asks to do something beyond the scope of the story. Inform provides a simple mechanism for recognising a command but at the same time recognising that *it does not properly specify an action*. Such commands are called _mistakes_, for the sake of a memorable term, but the player has not really behaved badly, and should be helped rather than reproved. For instance: Understand "act" as a mistake. While that works – the command to ``ACT`` is indeed rejected – it is not very good, because no very helpful message is brought up. The following is much better: Understand "act" as a mistake ("To join the actors, you have to adopt a role in the play! Try PLAY HAMLET or similar."). Or we could once again insist on a given context: Understand "act" as a mistake ("To join the actors, you have to adopt a role in the play! Try PLAY HAMLET or similar.") when the location is the Garden Theatre. That still has the drawback that the command ``ACT HAMLET`` will not be recognised: so the final version we want is probably Understand "act" or "act [text]" as a mistake ("To join the actors, you have to adopt a role in the play! Try PLAY HAMLET or similar.") when the location is the Garden Theatre. We need to be careful to avoid circular things like this, which don't do what the author hoped: Understand "[text]" as a mistake ("'[the topic understood]' is something I really wish you wouldn't say.") when the topic understood is a topic listed in table 1. The trouble is that `the topic understood` isn't set until the line has been understood, but Inform checks the `when...` condition _before_ it tries to understand the line. Indeed, even this: Understand "[text]" as a mistake ("'[the topic understood]' is something I really wish you wouldn't say."). is unsafe, because `topic understood` doesn't exist for a mistake. When there's a mistake, nothing was understood. It's sneaky but possible to use mistakes to implement out-of-world commands in a way which bypasses actions entirely: Understand "turns" as a mistake ("This is turn [turn count in words]."). As another example, the following can be useful when beta-testing of a new work, though we would not want it in the final published edition. Many authors like to ask their testers not to try anything in particular, simply to play naturally: but to record the transcript of the session, and email it back to the author. The following command is a device to allow the tester to type a comment in to the transcript: Understand "but [text]" as a mistake ("Noted."). For instance, the tester might type ``BUT DIDN'T WE SAY DARCY WAS TALL?``, to which the story would reply "Noted." – and the author can search for such comments when receiving the transcript. If we are careful, we can make the reply depend on what was typed in the mistaken command: Understand "steal [something]" as a mistake ("Just TAKE [the noun] and leave without paying: that's stealing in my book."). The care comes in because Inform applies much less checking to mistakes than to other actions, and odd errors will result if we try to refer to (say) "the second noun" in a command which did not have a second noun. It's probably wise to take particular care if using `as a mistake` with any command which might include the mistake among what the player calls ``ALL``: for example, if `"take [sydney harbour bridge]"` is understood as a mistake, then ``TAKE ALL`` will may result in this, even though the player doesn't intend any such thing. ## Precedence ^^{understanding: precedence of commands understood} ^^{understanding: choosing between multiple grammar lines} ^^{mistakes, in the player's command} ^^{precedence: of commands understood} When several different lines of grammar are supplied to meet the same circumstances, it makes a big difference what order they are tried in. For instance, suppose we have: Understand "photograph [a door]" as photographing. Understand "photograph [an open door]" as photographing. The second line is more specific than the first, so Inform takes these grammar lines the other way around: it checks for `open door` before it checks for `door`. That didn't matter here, since both lines came out with the same result (the action of photographing), but it matters very much in the next example: Understand "employ [a door]" as opening. Understand "employ [an open door]" as entering. More subtle is a line already seen: Understand "on/in/inside" or "on top of" as "[within]". Here Inform puts `on top of` before `on/in/inside`, since otherwise only the `on` of ``ON TOP OF`` will be recognised. Mistakes always take precedence over non-mistakes: this is intended to make sure that Understand "take umbrage" as a mistake ("Nobody takes umbrage in this story, mister."). will take precedence over Understand "take [something]" as taking. even if there is, in fact, a character called Mr Nimbus Umbrage so that the command could conceivably make sense. Finally, there are a few grammars where the number of values produced is different in different lines. For example, the Standard Rules include these among the possible ``PUT`` commands: Understand "put [something preferably held] on" as wearing. Understand "put [other things] on/onto [something]" as putting it on. One produces a single object, the other produces two. Inform gives precedence to the first of these, that is, it tries the one with fewer values first. This is important when reading commands like ``PUT MARCH ON WASHINGTON SHIRT ON``, and also prevents bogus autocompletions, in which ``PUT HAT ON`` might wrongly be autocompleted by the parser and read as if it were ``PUT HAT ON THE TABLE``. # Activities ## What are activities? {ACTIVITIES} {kind_activity} {PM_BadActivityName} ^^{activities} ^^{activities: not the same as actions} ^^{actions: not the same as activities} It is poor form to define with negatives, but the first thing to say about activities is that they are *not* actions. This needs saying because Inform often seems to treat them as if they are, by allowing us to write rules like so: Before printing the name of a woman, say "Ms ". With this rule in place, someone called "Daphne" will always be described as ``Ms Daphne``, and so on. The language looks as if we were imposing a rule on an action called `printing the name of`, but there is no such action: instead, it is an _activity_. To spell out the difference: > **An *action* is a simulated task for a character in the story, such as the protagonist.** > > **An *activity* is a real task for the computer program doing the simulation.** Activities allow us to influence or change some of the standard habits of Inform, using rules as flexible and powerful as those applicable to actions, though activities are in several ways simpler and easier. ## How activities work ^^{activities} ^^{going on (activity)+adj+} ^^{activities: golden rules for constructing} All activities start, continue for a while and then finish. As a general rule, no activity ever lasts more than a turn, and although one activity often interrupts another one, that new activity then finishes before the old one does. They therefore sit inside each other like Russian nesting dolls. While Inform does provide low-level ways to control activities which could be used to break these conventions, the built-in activities all follow them, and authors are well advised to follow suit. As an example of that nesting, suppose the following is printed as part of the description of a grocery: You can see a banana, an apple and a star-fruit here. At the moment when Inform prints ``apple``, two activities are under way: `listing contents of the Grocery`, and `printing the name of the apple`. The sequence of events was in fact: say "You can see " [ start listing contents of the Grocery ] say "a " [ start printing the name of the banana ] say "banana" [ finish printing the name of the banana ] say ", an " [ start printing the name of the apple ] say "apple" [ finish printing the name of the apple ] say " and a " [ start printing the name of the star-fruit ] say "star-fruit" [ finish printing the name of the star-fruit ] [ finish listing contents of the Grocery ] say " here." The golden rule is: if activity B starts during activity A, it must also finish during activity A. If we ever need to find out, we can always test: if the printing the name activity is going on, ... if the printing the name activity is not going on, ... but as we shall see, it's usually simpler to attach `while printing the name` provisos to rules. ## Rules applied to activities ^^{activities: rules for activities} ^^{before (activity)+rb+} ^^{rules: before rules} ^^{after (activity)+rb+} ^^{rules: after rules} ^^{for (activity)+rb+} ^^{rules: for activities} ^^{rulebooks: for actitivies} The activity `printing the name of something` is the process of printing up the name of something on screen: ordinarily, this means saying the text in the object's `printed name` property. Actions very often break off and finish midway through their processing stages, because something happens in the story, or because it turns out that the action was impossible. A taking action might end at the before, instead or check stage, for example. Activities are easier to understand because they have just three rulebooks — before, for and after — and because they generally work through all three right to the end of processing, and thus finish in an orderly way. For example, the three rulebooks for printing the name are called `before printing the name`, `for printing the name` and `after printing the name`, and this is the general pattern. What normally happens is a three-stage process: 1) All `before printing the name of` rules are considered. 2) The most specific, applicable `rule for printing the name of` is considered. 3) All `after printing the name of` rules are considered. Why is this what "normally" happens, not what "always" happens? * Like action rules, activity rules can use the `instead` keyword to finish their rulebooks early. In the `before` and `after` stages, this can be useful: Before printing the name of a device: say "<< " instead. Before printing the name of something: say "( ". After printing the name of a device: say " >>" instead. After printing the name of something: say " )". These rules might then result in the names of two items being printed as ``<< electric toaster >>`` and ``( slice of bread )``. The use of `instead` in the first before rule causes the second one not to be reached, and similar for the after rules. Without the `instead` keywords, the device's name would have been printed as ``<< ( electric toaster >> )``. * The `for` rulebook of an activity has the opposite convention. It runs just one rule, not all of them, so using `instead` would make no difference there. Instead, though, `continue the activity` can be used to allow a `for` rule to hand the job on to another rule, as if it had not been the one chosen: For printing the name of a device (called the machine): if the machine is switched off, continue the activity; say "ACTIVE DEVICE". The effect there is that if the device is switched off, this rule chooses to do nothing, telling Inform to choose the next most applicable `for` rule to handle matters. (Probably Inform's built in `standard name printing rule`, which then prints ``ELECTRIC TOASTER``.) * As was mentioned earlier, Inform provides some low-level tricks for running activities in non-standard ways. It hardly ever breaks the above pattern for any of the built-in activities, and in the few cases when it might, that is noted in the remaining sections of this chapter. * In particular, it's possible to set up an activity so that Inform provides a fall-back functionality even in the case where no "for" rules exist for the activity at all. Again, Inform uses this ability as little as possible, and only where there are efficiency or reliability reasons to do so. * Some calamity might occur which ends the story while an activity is mid-way, in which case the rest of the activity might not take place. "When it's time for the fallout / And St Peter calls us all out, / We'll just drop our agendas and adjourn" (Tom Lehrer). Again, though, some built-in activities continue even after the story has ended, in order to avoid potential confusion. `Printing the name of` is one of those. So this rule does what might be expected, i.e., it _does_ suddenly end the story, but it doesn't actually end it mid-sentence: For printing the name of Lord Voldemort: end the story saying "What part of He Who Must Not Be Named did you not understand?" ## While clauses {PM_BadWhenWhile} ^^{rules: arbitrary conditions for rules, using (while)+sourcepart+} ^^{while (condition)+sourcearg+: arbitrary conditions for rules} ^^{conditions: for activity rules} ^^{rules: applying only while performing activities} ^^{activities: checking for ongoing activities in rules} Rules applied to actions can become baroque (`after going through a door in the presence of an animal when` and so on and so forth), but activities are again simpler: they only have one possible clause attached, which is called `while`. For instance, the following would provide a fairly sledgehammer hint that the sack should not lightly be thrown away: The sack is a player's holdall. The sack is carried. Rule for printing the name of the sack while the sack is not carried: say "your abandoned sack". Any condition can be given after the `while`, and we can also specify that another activity has to be going on. Thus: Rule for printing the name of the lemon sherbet while listing contents: say "curious sort of lemon sherbet sweet". This nicely distinguishes between contexts where it's appropriate to be more verbose, and where it isn't. Thus: ``` transcript You can see a teaspoon and a curious sort of lemon sherbet sweet here. > TAKE ALL teaspoon: Taken. lemon sherbet: Taken. ``` ## New activities {EXTACTIVITIES} ^^{activities: defining} ^^{defining: activities} ^^{rules: for activities} ^^{rulebooks: for actitivies} ^^{empty / non-empty+adj+: for activities} ^^{non-empty / empty+adj+: for activities} ^^{activities: empty / non-empty+adj+} Activities are all about influencing the standard mechanisms which Inform uses, so it might at first seem that there is no need to create new activities: but on further reflection, quite a lot of the writing of interactive fiction involves creating new and systematic ways to do things, and as soon as we have a general rule, we will want to have exceptions. Inform therefore allows us to create our own activities, giving us ways to influence the operation of our own mechanisms. There are two kinds of activity: those which relate to a specific value (usually an object but not necessarily), and those which do not. Here are some examples of activities being created: Assaying is an activity. Analysing something is an activity. Announcing something is an activity on numbers. These names are all present participles (note the `-ing`s), which emphasises that they are about an ongoing process. This naming convention is good style, and all of the built-in activities follow it, but it is not actually compulsory. `Barbra Streisand is an activity.` would be quite legal. Inform looks for the clue `something` (or `of something`) after the activity's name to see if it will work on a value: so analysing and announcing will do, but assaying won't. If we don't specify a kind, Inform assumes the value will be an object, as if we had written: Analysing something is an activity on objects. As always in Inform, the names of activities are themselves values. - `assaying activity` has kind `activity on nothing` - `analysing activity` has kind `activity on objects` - `announcing activity` has kind `activity on numbers` Creating an activity is like creating an action: it automatically makes new rulebooks – `before analysing`, `for analysing` and `after analysing` – but they start out empty, so the activity does nothing yet. Just as it does for rulebooks, Inform defines the adjectives `empty` and `non-empty` for activities to test this state: if the analysing activity is empty, ... will be true only when all three of its rulebooks are empty. A newly created activity never happens unless we take steps to make it do so. We can make an activity happen at any time by writing phrases like so: > phrase: {ph_carryout} carry out the (activity) activity > > This phrase carries out the given activity, which must be one not applying to any value. Example: > > carry out the assaying activity; > phrase: {ph_carryoutwith} carry out the (activity on values) activity with (value) > > This phrase carries out the given activity, which must apply to a kind of value matching the one supplied. Example: > > carry out the analysing activity with the pitchblende; > carry out the announcing activity with the score; To make the activity do something useful, we need to put a rule into its `for` rulebook: Rule for announcing a number (called N): say "Ladies and gentlemen, [N]." The last for assaying rule: say "Professionally, you cast an eye around mineral deposits nearby, noticing [list of rocks in the location]." `The last` is a technicality about rulebooks (see the next chapter, [Rulebooks]) which, put briefly, guarantees that this rule comes last among all possible `for assaying` rules. This is good form because the whole point of an activity is to make it easy for further rules to interfere – so we deliberately hang back to last place, giving precedence to anybody else who wants it. The `for` rulebook is one where rules stop the activity, by default, when they take effect – in the same way that the `instead` rules stop actions by default. If this causes problems, we can use: > phrase: {ph_continueactivity} continue the activity > > This phrase should be used only in rules in activity rulebooks. It causes the current rule to end, but without result, so that the activity continues rather than stopping as a result of the rule. This is useful for rulebooks (like the `for` rulebook of an activity) where the default is that a rule does stop the activity. Activities are more useful than they first appear. Every new one provides a context which other activities can observe. We could, for instance, define Rule for printing the name of a rock while assaying: ... so that during assays more technical names are used. ## Activity variables {PM_ActivityVariableNameless} {PM_ActivityVarAnd} {PM_ActivityVarOverspecific} {PM_ActivityVarUnknownKOV} {PM_ActivityVarValue} ^^{activities: variables for activities} ^^{variables: for activities} ^^{defining: activity variables} ^^{|called: in defining activity variables} Just as actions can have variables, which are created when the action starts and disappear when it finishes, so activities can also have variables. They are visible to the rules for that activity, and nowhere else. (If the activity should happen a second time within its first run, that second occurrence gets its own copy of the variable, leaving the original untouched.) Typically it will be useful to set a variable to some default value at the `before` stage, calculate some interesting value for it in the `for` stage, and make use of the outcome during the `after` stage. For instance: Analysing something is an activity. The analysing activity has a text called first impression. Instead of examining something (called the sample), carry out the analysing activity with the sample. Before analysing: now the first impression is "unremarkable". Rule for analysing someone: now the first impression is "living tissue". After analysing something (called the sample): say "Your professional opinion of [the sample] is that it is [first impression]." ## Beginning and ending activities manually ^^{activities: beginning/ending by hand} ^^{activities: abandoning by hand} If we have declared a new activity, like `analysing`, what we should almost always use to run the activity is the standard phrase `carry out`, like so: carry out the analysing activity with the pitchblende; See [New activities]. This goes through the whole machinery of rules – before, for, after – in the normal way. However, as was mentioned earlier in this chapter, Inform has low-level features making it possible to run activities in non-standard ways. These features should only be used when absolutely necessary (for example for performance reasons), and even then, care should be taken to preserve the usual conventions for how the three activity stages are run. To reiterate: Inform authors will never need the features in this section, and will only ever need `carry out`. But with that said, here goes. > phrase: {ph_beginactivity} begin the (activity) activity > > This phrase causes the named activity to become active, and runs its `before` rulebook. The activity must be one which applies to nothing. Example: > > begin the assaying activity; > > It is the user's responsibility to ensure that in all cases a matching `end the ... activity` or else `abandon the ... activity` phrase is subsequently reached. > phrase: {ph_beginactivitywith} begin the (activity on values) activity with (value) > > This phrase causes the named activity to become active, and runs its `before` rulebook. The activity must be one which applies to a value of a matching kind. Example: > > begin the analysing activity with the pitchblende; > > It is the user's responsibility to ensure that in all cases a matching `end the ... activity` or else `abandon the ... activity` phrase is subsequently reached. And when we are done: > phrase: {ph_endactivity} end the (activity) activity > > This phrase runs the `after` rulebook of the activity and then causes it to become inactive. The activity must be one which applies to nothing. Example: > > end the assaying activity; > > It is the user's responsibility to ensure that this only ever happens in a way which matches an earlier `begin the ... activity` phrase. > phrase: {ph_endactivitywith} end the (activity on values) activity with (value) > > This phrase runs the `after` rulebook of the activity and then causes it to become inactive. The activity must be one which applies to a value of a matching kind. Example: > > end the analysing activity with the pitchblende; > > It is the user's responsibility to ensure that this only ever happens in a way which matches an earlier `begin the ... activity` phrase. So the usual structure is like so: begin the analysing activity with the pitchblende; ... end the analysing activity with the pitchblende; This time the activity is ongoing throughout as many phrases as we care to write between the `begin` and `end`. The before rules are considered at the time of the `begin ...` phrase; the after rules at the `end ...`. What, then, of the `for` rules? In the above setup, they would simply be ignored. But we can make them effectual thus begin the analysing activity with the pitchblende; ... if handling the analysing activity with the pitchblende: ... ... end the analysing activity with the pitchblende; We place the activity's normal behaviour inside the `if`; the condition, `if handling...`, is true only if no rule has intervened. This means that we (or other authors using our activity) can create their own for rules to substitute here. If we elsewhere write Rule for handling the analysing activity with the pitchblende when the player is not sober: say "You can't seem to focus." that rule will intervene and take the place of whatever we have placed inside the condition. > phrase: {ph_handlingactivity} if handling (activity) activity: > > This should be used only where the given activity has been started with `begin ...` and will be finished with `end ...`. It runs the `for` rules for the activity, and then comes out true if none of those for rules intervened in the handling of that activity. (The activity must be one which doesn't apply to any value.) > phrase: {ph_handlingactivitywith} if handling (activity on values) activity with (value): > > This should be used only where the given activity has been started with `begin ...` and will be finished with `end ...`. It runs the `for` rules for the activity, and then comes out true if none of those for rules intervened in the handling of that activity. (The given value must be the one it is being applied to.) It is also legal to force an early end to an activity with: > phrase: {ph_abandonactivity} abandon the (activity) activity > > This phrase ends an activity at once (without consulting any further rulebooks, including its `after` rulebook). It can only be used with an activity which has had its `begin` but not yet its `end` phrase; it is a drastic remedy best taken only if it is clear that circumstances have changed so that the activity now seems inappropriate. It must not be used during one of the rules for the activity: it can only be used between the begin and for stages, or between the for and end stages. > > abandon the assaying activity; > phrase: {ph_abandonactivitywith} abandon the (activity on values) activity with (value) > > This phrase ends an activity at once (without consulting any further rulebooks, including its `after` rulebook). It can only be used with an activity which has had its `begin` but not yet its `end` phrase; it is a drastic remedy best taken only if it is clear that circumstances have changed so that the activity now seems inappropriate. It must not be used during one of the rules for the activity: it can only be used between the begin and for stages, or between the for and end stages. > > abandon the analysing activity with the pitchblende; Bad things may happen if we do not follow the golden rules: * all activities must go through all three stages in sequence, or be abandoned either _between_ the before and for stage, or _between_ the for and after stage; * if activity B starts during activity A then it must finish before the end of activity A; * an activity must not, in any case, last longer than a turn; * if an activity is applied to some object or value, as in the above examples where it is applied to the pitchblende, then all uses of the above low-level phrases must be applied to the same object. Inform does _not_ police these golden rules. If we want to use these somewhat hazardous features, we need to be careful doing so. ## Introduction to the list of built-in activities ^^{activities: catalogue} Activities tend to be about process, rather than outcome. Many of the things Inform does – printing up lists of items, reading commands from the keyboard, and so on – are done as activities, because that way the process can be nudged a little. Too many works of interactive fiction betray their mechanical nature by making it visible that the general machinery being used does not quite seem natural for this or that situation. Activities enable us to add the many graceful touches which avoid that: which contribute nothing to a work, and also everything. The rest of this chapter covers every activity built in to Inform, with one section for each. It is intended primarily for reference, but may be worth skimming through at a first reading, to give a sense of the possibilities. ## Deciding the concealed possessions of something {act_con} {var_particular} ^^{hiding things: carried by other characters} ^^{concealment+rel+} ^^{concealment+relcat+} ^^{concealed (thing)+adj+} ^^{concealed possessions} ^^{possessions: deciding the concealed possessions of something+activity+} ^^{particular possession (- thing)+glob+} **1. When it happens.** Frequently – whenever Inform needs to check whether something is visible or not. Nothing should be printed, and the activity needs to run quickly, so it should not (for instance) calculate best routes through complicated maps before getting an answer. **2. The default behaviour.** There is no concealment. The ordinary rules still apply, though: the contents of a closed opaque container are invisible because there is a barrier in the way which cannot be seen through, even though nobody is `concealing` anything. **3. Examples.** To repeat a number of brief examples given at the end of the chapter on [Things], where this activity made an early appearance: Rule for deciding the concealed possessions of the Cloaked Villain: if the particular possession is the sable cloak, no; otherwise yes. The coin is in the Roman Villa. The face and inscription are parts of the coin. Rule for deciding the concealed possessions of the coin: if the coin is carried, no; otherwise yes. The value `particular possession` is the one whose concealment is in question, of course. We can ignore this if someone is invariably secretive: Rule for deciding the concealed possessions of the furtive ghost: yes. In general a rule for deciding the concealed possessions of something will decide `yes` if finishes without making a decision, but it's better style to write such a rule in such a way that it always makes a decision. ## Printing the name of something {act_pn} ^^{printing the name of something+descactivity+}^^^{descriptions (displayed) <-- displaying descriptions} ^^{names: printing the name of something+activity+} ^^{printed name of (object)+prop+} ^^{printed name of (object)+propcat+} **1. When it happens.** Whenever the name of a thing or room is printed, either as part of text visible to the player, or sometimes internally in order to determine something about that name. **2. The default behaviour.** For items other than the current player, the `printed name` property is printed out; but for the current player, ``you`` or ``yourself`` is printed. (That doesn't necessarily mean that the `printed name` of the player is never used. Suppose there are two people, Alice and Bob, and the narrative switches between them: when Alice is the player, she appears as ``yourself`` but Bob is ``Bob``; but when Bob is the player, he is ``yourself`` and Alice is ``Alice``.) **3. Examples.** (a) A pen which is described differently in inventories: Rule for printing the name of the pen while taking inventory: say "useful pen". `Taking inventory` is a condition which is true if that's the current action and not otherwise, so the effect is that the pen is called `a useful pen` only in inventory listings. `While looking` is a similarly useful one. (b) Italicising the names of novels: A novel is a kind of thing. Dr Zhivago and Persuasion are novels. Before printing the name of a novel, say "[italic type]". After printing the name of a novel, say "[roman type]". (c) Telling the time: After printing the name of the wrist watch while taking inventory: say " (time: [the time of day])". (d) Merging containers with their contents: {*}Rule for printing the name of the bottle while not inserting or removing: if the bottle contains sand, say "bottle of sand"; otherwise say "empty bottle"; omit contents in listing. This example makes use of a special phrase: > phrase: {ph_omit} omit contents in listing > > This phrase changes the form of an inventory listing, room description, etc., so that it will simply list ``a bottle of sand`` or ``an empty bottle``, rather than ``a bottle (in which is sand)`` or ``a bottle (which is empty)``. It should be used only when the listing is imminent, and does not have permanent effect. The clause about not inserting or removing is to prevent messages like ``You put the sand in the bottle of sand.``, where it's confusing to refer to the bottle as anything other than ``the bottle``. ## Printing the plural name of something {act_ppn} ^^{printing the plural name of something+descactivity+} ^^{names: printing the plural name of something+activity+} ^^{printed plural name of (object)+prop+} ^^{printed plural name of (object)+propcat+} ^^{plurals: printing the plural name of something+activity+} **1. When it happens.** Only when a group of identical items is present in the same place, and are being described jointly with text like ``You can see five gold rings here.`` The activity happens after ``five`` and before ``here.`` (See the activity `printing a number of something` if the whole phrase needs to be altered.) **2. The default behaviour.** The plural name – in this case ``gold rings`` – is printed out. **3. Examples.** (a) Suppose we want to emphasise how nice it is to have more than one gold ring: {*}Rule for printing the plural name of a gold ring: say "gleaming gold rings". (b) If the number needs changing as well, it's necessary to use the `printing a number of something` activity instead. ## Printing a number of something {act_pan} ^^{printing a number of something+descactivity+} ^^{numbers: printing a number of something+activity+} ^^{listing group size (- number)+glob+} **1. When it happens.** Only when a group of identical items is present in the same place, and are being described jointly with text like ``You can see five gold rings here.`` The activity prints the ``five gold rings`` part. The variable `listing group size` contains the number, which in this example would be 5, and is always at least 2. **2. The default behaviour.** The number of items is printed, in words (``five``) and then the `printing the plural name` activity is run (``gold rings``). **3. Examples.** (a) Using this activity is for perfectionists, because the normal behaviour is almost always fine. Still: {*}Rule for printing a number of blocks when the listing group size is 3: say "all three blocks". (b) Or perhaps: {*}Rule for printing a number of ants: say "altogether [listing group size in words] ants". (c) If the only part needing variation is the plural name, it's simpler and tidier to use the `printing the plural name of something` activity instead. ## Listing contents of something {act_lc} ^^{listing contents of something+descactivity+} ^^{listing rules: for listing contents} ^^{together: group (description of objects) together+phr+} **1. When it happens.** When taking inventory, the list is produced by the activity `listing contents of yourself`; when looking, a list of items which do not deserve their own paragraphs is produced by `listing contents of` the location. **And when it doesn't happen.** (a) If the Storage Room contains a sideboard and an open shoe box, then `listing contents of the Storage Room` is used to produce the part of the room description mentioning sideboard and box. But if the box in turn contains a pair of brogues, then `listing contents of the shoe box` is not used to say that part. So this works: Rule for printing the name of the brogues while listing contents of a room: ... But this won't affect room descriptions: Rule for printing the name of the brogues while listing contents of the shoe box: ... (b) The activity also doesn't happen when, for instance, `"[a list of animals]"` is printed, because that isn't a list of the contents of any room or location. **2. The default behaviour.** The list is printed out. **3. Examples.** (a) We have already seen that it can be elegant to elaborate on a description in the context of a list. Here we add ``discarded`` to a sweet wrapper which is found on the ground. Rule for printing the name of the wrapper while listing contents of a room: say "discarded sweet wrapper". (b) Lists can be considerably shortened and tidied up if similar items are grouped together. We do this by specifying what should be grouped together before listing contents, using the special phrase `group ... together`: Utensil is a kind of thing. The knife, the fork and the spoon are utensils. Before listing contents: group utensils together as "utensils". The result will be, say, ``two utensils (knife and spoon)``, if both are found in the same place. (c) We can less obtrusively group items together like so: Before listing contents while taking inventory: group utensils together. Three special phrases exist for this kind of list organisation: > phrase: {ph_group} group (description of objects) together > > This phrase causes the objects described to be listed together in a single item as part of an inventory or room description. The effect is temporary, and the phrase should only be used when this list is imminent. Example: > > Utensil is a kind of thing. The knife, the fork and the spoon are utensils. Before listing contents: group utensils together. > > This might produce the list item ``fork and spoon``. > phrase: {ph_groupart} group (description of objects) together giving articles > > This phrase causes the objects described to be listed together in a single item as part of an inventory or room description, but giving each individual item its indefinite article. The effect is temporary, and the phrase should only be used when this list is imminent. Example: > > Utensil is a kind of thing. The knife, the fork and the spoon are utensils. Before listing contents: group utensils together giving articles. > > This might produce the list item ``a fork and a spoon``. > phrase: {ph_grouptext} group (description of objects) together as (text) > > This phrase causes the objects described to be listed together in a single item as part of an inventory or room description, summarised with the given text. The effect is temporary, and the phrase should only be used when this list is imminent. Example: > > Utensil is a kind of thing. The knife, the fork and the spoon are utensils. Before listing contents: group utensils together as "utensils". > > This might produce the list item ``two utensils (fork and spoon)``. ## Grouping together something {act_gt} ^^{grouping together something+descactivity+} ^^{listing rules: for grouping together} ^^{listing group size (- number)+glob+} **1. When it happens.** Only while listing contents, and only when a collection of items to be grouped together is reached. This in turn happens only if a `before listing contents` rule has chosen it (see previous section). The first item in the group is the one to which the activity formally applies. The variable `listing group size` usually gives the number of items grouped together in this way, but care is needed if the `something` covers multiple groups, because then this will all be working on a list of groups, not of items. For example, in a `grouping together things` rule, where `things` is such a broad description that it can apply to multiple kinds of thing all appearing in the list, the list-maker is likely to set `listing group size` to the number of groups. If the list contains five men and six women, for example, `listing group size` might be 2 rather than 11. **2. The default behaviour.** The items grouped together are printed in an English phrase, such as ``egg, chicken and farmer``. In particular, they are not split onto separate lines even if the rest of the list is. (See previous section.) **3. Examples.** (a) Here are Scrabble pieces which are described as ``the tile W from a Scrabble set`` or similar outside of lists, but which, when they turn up together in lists, are rolled together into ``the tiles A, B and D from a Scrabble set``. {*}A Scrabble piece is a kind of thing. The X, the Y and the Z are Scrabble pieces. Before listing contents: group Scrabble pieces together. Before printing the name of a Scrabble piece while not grouping together, say "tile ". After printing the name of a Scrabble piece while not grouping together, say " from a Scrabble set". Before grouping together Scrabble pieces, say "the tiles ". After grouping together Scrabble pieces, say " from a Scrabble set". (b) Maybe we only want an abbreviated form when there are five or more tiles in one place: {*}A Scrabble piece is a kind of thing. The X, the W, the F, the Y and the Z are Scrabble pieces in the Lounge. Before listing contents: group Scrabble pieces together. Before grouping together Scrabble pieces when the listing group size is greater than 4: say "some [listing group size in words] tiles (". After grouping together Scrabble pieces when the listing group size is greater than 4: say ") from a Scrabble set". (c) We can throw out all pretence at listing and say whatever we like, in fact: Before listing contents while taking inventory: group utensils together. Rule for grouping together utensils: say "the usual utensils". ## Issuing the response text of something {act_resp} ^^{responses (library messages): issuing the response text of something+activity+} **1. When it happens.** When Inform prints a text marked with a response letter `(A)`, `(B)`, `(C)`, ..., in a rule making use of them. For example, in this rule: Carry out taking inventory (this is the print empty inventory rule): if the first thing held by the player is nothing, say "[We] [are] carrying nothing." (A) instead. Or, less directly, let R be the print empty inventory rule response (A); say "To be frank: [text of R]."; **2. The default behaviour.** To print the current textual value of the response, making any substitutions in the ordinary way. **3. Examples.** This activity is not the best way to amend responses or make them dynamic; the whole idea of responses is that they can be changed just as if they were text variables. This activity should be used only if it's important to amend blocks of responses in some systematic way. (a) With that said, some interesting effects can be achieved. This is a way to see which responses are being printed, for example: Before issuing the response text of a response (called R): say "[R]: ". whence: > WAIT standard report waiting rule response (A): Time passes. (b) And this intercepts the activity in order to re-run it in each of the six viewpoints. (Note the way a variable is used to prevent the rule from applying to all of those re-runs as well.) The response inhibition is initially false. Rule for issuing the response text of a response (called R) when the response inhibition is false: now the response inhibition is true; let the current viewpoint be the story viewpoint; repeat with P running through narrative viewpoints: now the story viewpoint is P; say "[P]: [text of R][command clarification break]"; now the story viewpoint is the current viewpoint; now the response inhibition is false. With that in place, > EAST first person singular: I can't go that way. second person singular: You can't go that way. third person singular: He can't go that way. first person plural: We can't go that way. second person plural: You can't go that way. third person plural: They can't go that way. ## Printing room description details of something {act_details} ^^{printing room description details of something+descactivity+} ^^{room description details: printing room description details of something+activity+} **1. When it happens.** When an item is listed in the miscellaneous collection of items present in a room (the ones which do not deserve their own paragraphs): this is normally the last paragraph of a room description. **2. The default behaviour.** A bracketed piece of extra information is added for certain items such as containers: ``` transcript You can also see Po and a cage (empty) here. ``` The `` (empty)`` (note initial space) was added by this activity. (Note that this activity is not responsible for describing further items visible because of the item in question: that is, it does not print the text such as ``(in which is a notepad)`` which would appear if there were contents. If we want to remove such text, we should use `omit contents in listing`: see the activity `for printing the name of something`.) **3. Examples.** (a) To get rid of such addenda entirely, try: Rule for printing room description details: stop. (b) To add a new form of addendum: Rule for printing room description details of a person: say " (at last, someone to talk to)" instead. If both examples (a) and (b) are in place at once, we might now read: You can also see Po (at last, someone to talk to) and a cage here. ## Printing inventory details of something {act_idetails} ^^{printing inventory details of something+descactivity+} ^^{inventory details: printing inventory details of something+activity+} **1. When it happens.** When an item is listed in an inventory of items carried by the player. **2. The default behaviour.** A bracketed piece of extra information is added for certain items such as containers: a flaming branch (providing light) The `` (providing light)`` (note initial space) was added by this activity. **3. Examples.** (a) To get rid of such addenda entirely, try: Rule for printing inventory details: stop. (b) To add a new form of addendum: Rule for printing inventory details of something edible: say " (yummy!)[run paragraph on]". ## Printing a refusal to act in the dark {act_toodark} ^^{darkness: printing a refusal to act in the dark+activity+} ^^{refusal to act: printing a refusal to act in the dark+activity+} **1. When it happens.** When an action which requires light is tried, and the visibility rules decide that not enough light is present. **2. The default behaviour.** To print ``It is pitch dark, and you can't see a thing.`` **3. Examples.** (a) This might do for some twilit, penumbral room: Rule for printing a refusal to act in the dark: if we are examining something, say "It's not totally dark here, perhaps, but certainly too dim for close-up examination of anything." instead. ## Printing the announcement of darkness {act_nowdark} ^^{darkness: printing the announcement of darkness+activity+} ^^{announcement of darkness: printing the announcement of darkness+activity+} **1. When it happens.** Inform frequently calculates to see if the player is in light or darkness: this activity happens on the change from light to darkness. **2. The default behaviour.** To print ``It is now pitch dark in here!``. **3. Examples.** (a) The most obvious use is to change the text: Rule for printing the announcement of darkness: say "Ooh-er! It's now very nearly pitch dark in here." instead. (b) But we could also use this activity for sneakier purposes, silently moving things around: Before printing the announcement of darkness: now all of the gremlins are in the kitchen. (c) A special description for occasions when the player has climbed into a container and shut it (so that the darkness is the result of their own actions, rather than some external circumstance): Rule for printing the announcement of darkness when closing a container which contains the player: say "Congratulations: now you can't see a thing." instead. ## Printing the announcement of light {act_nowlight} ^^{darkness: printing the announcement of light+activity+} ^^{light: printing the announcement of light+activity+} ^^{announcement of light: printing the announcement of light+activity+} **1. When it happens.** Inform frequently calculates to see if the player is in light or darkness: this activity happens on the change from darkness to light. **2. The default behaviour.** To try the looking action, which usually prints up a room description. **3. Examples.** (a) Perhaps the player is initially too disoriented to look around in any coherent way: Rule for printing the announcement of light in the Dazzling Temple: say "You are almost blinded by the suffusion of white light, and have spots before your eyes." instead. ## Printing the name of a dark room {act_darkname} ^^{darkness: printing the name of a dark room+activity+} ^^{names: printing the name of a dark room+activity+} ^^{rooms+kind+: name of a dark room} **1. When it happens.** When looking in darkness, or writing the (default) status line in darkness. **2. The default behaviour.** To print ``Darkness``. **3. Examples.** (a) One might modify the darkness with some adjective: Before printing the name of a dark room, say "Near ". (Note that this activity does not come in different forms for different dark rooms: the wording is fixed at `printing the name of a dark room`, and we are not allowed to substitute particular dark rooms or assign a `(called ...)` onto the mention of the dark room.) ## Printing the description of a dark room {act_darkdesc} ^^{printing the description of a dark room+descactivity+} ^^{darkness: printing the description of a dark room+activity+} ^^{descriptions (displayed): dark room} **1. When it happens.** When looking in darkness. **2. The default behaviour.** To print ``It is pitch dark, and you can't see a thing.`` **3. Examples.** (a) A simple variation of wording: Rule for printing the description of a dark room: say "Your eyes can barely make anything out." instead. (b) More stylishly, Rule for printing the description of a dark room: try listening instead. which produces, for instance, Darkness You hear nothing unexpected. (Note that this activity does not come in different forms for different dark rooms: the wording is fixed at `printing the description of a dark room`, and we are not allowed to substitute particular dark rooms or assign a `(called ...)` onto the mention of the dark room.) ## Constructing the status line {act_csl} ^^{status line} ^^{screen top} ^^{left hand status line (- text)+glob+} ^^{right hand status line (- text)+glob+} **1. When it happens.** Just before input is accepted from the keyboard, Inform constructs a "status window" at the top of the window which is normally displayed in reverse colours (white on black instead of black on white, say). This was once just a single line, and the name of this activity is a reminder of those simpler times. **2. The default behaviour.** Makes the status window up as a single line with two pieces, printed from the text variables `left hand status line` and the `right hand status line`. Since these can freely be changed, note that the status window is already very customisable without using rules applied to this activity. (See [Changing the status line].) **3. Examples.** (a) One use for this activity is to vary location names in the status window. This is especially helpful to abbreviate unduly long names, which might not otherwise fit: The Temple Of A Thousand Mightily Peeved Deities is a room. Rule for printing the name of the Temple while constructing the status line: say "Temple". Note that this works not by adding a rule to the activity, but by detecting whether or not it is currently running. (b) Again, it's usually not necessary to apply activity rules to this, but occasionally amusing effects are possible if we do: {*}The blindfold is wearable and carried. Rule for constructing the status line while the blindfold is worn: do nothing. (c) More dramatically: A room can be underwater or dry land. The Beach is a room. South of the Beach is the Continental Shelf. The Shelf is underwater. Oxygen remaining is a number that varies. Every turn while the player is in an underwater room: decrement the oxygen remaining; if the oxygen remaining is less than 0: end the story saying "You have drowned". After going from a dry land room to an underwater room: now the oxygen remaining is 5; say "You hold your breath." After going from an underwater room to a dry land room: now the oxygen remaining is 0; say "You take a breath with great relief." Table of undersea status details left column middle column right column "[the player's surroundings]" -- "[score]/[turn count]" "[bold type]Submerged[roman type]" "Oxygen: [oxygen remaining]" "DANGER" Rule for constructing the status line while the player is in an underwater room: draw the status window with the table of undersea status details. For further effects, see [The main screen and the status window]. ## Writing a paragraph about {act_wpa} ^^{writing a paragraph about+descactivity+} ^^{paragraph: writing a paragraph about+activity+} ^^{descriptions (displayed): notable things in room} ^^{mentioned / unmentioned (thing)+prop+} ^^{unmentioned / mentioned (thing)+prop+} ^^{mentioned (thing)+propcat+} ^^{unmentioned (thing)+propcat+} ^^{paragraph breaks: for confusing the normal display of objects} **1. When it happens.** Just *before* writing a paragraph about some item in a room description. **2. The default behaviour.** Is to do nothing. However, if a rule is supplied which prints something up, then this replaces the paragraph which would otherwise have been printed. Moreover, any items whose names are said in the course of this rule – for instance, by being listed – are then excluded from the remainder of the room description, because they are considered as having been described sufficiently already. Warning: because we often want a `for` rule for this activity to make some calculation and then possibly choose to do nothing (see the example [Otranto]), Inform suppresses the usual paragraph not when a `for` rule took effect but when it detected a paragraph having been printed. This can get confused if a text substitution affecting paragraph breaks, say `"[line break]"`, is within the final `say` of a `for writing a paragraph about` rule. **3. Examples.** (a) This is a neat way to wrap several things together into the same paragraph: {*}Rule for writing a paragraph about Mr Wickham: say "Mr Wickham looks speculatively at [list of women in the location]." because now ``Mr Wickham looks speculatively at Velma and Daphne.`` will now prevent the appearance of the subsequent text ``You can also see Velma and Daphne.`` Inform keeps track of which objects have already been named with an either/or property called `mentioned`, which it assigns whenever the name of an object has been automatically printed. So in this case, Velma and Daphne are now mentioned. Note "automatically printed", though: if the text printed had just been `"Mr Wickham looks speculatively at Velma and Daphne"`, rather than the text-substitution list used above, then Inform would not know that Velma and Daphne have been described. If we ever need to override this – say, we want to list all the women but make sure that Velma gets another paragraph anyway – we could change Velma to unmentioned again after the listing. ## Listing nondescript items of something {act_lni} ^^{listing nondescript items of something+descactivity+} ^^{descriptions (displayed): miscellaneous things in room} ^^{marked for listing / unmarked for listing (thing)+prop+} ^^{unmarked for listing / marked for listing (thing)+prop+} ^^{marked for listing (thing)+propcat+} ^^{unmarked for listing (thing)+propcat+} ^^{nondescript items: listing nondescript items of something+activity+} ^^{activities: abandoning} **1. When it happens.** This activity prints up the also-ran paragraph at the end of a room description. These are nondescript items because they don't merit paragraphs of their own: if, as sometimes happens, there are none in the room, then no such paragraph is printed and this activity does not happen. (So to add a further paragraph to a room description, a simpler `after looking` rule should be used, not an `after listing nondescript items` rule.) **2. The default behaviour.** The paragraph ordinarily reads as ``You can also see a cask and a clock.`` or similar. Before the activity begins, those objects which are nondescript – in this case the cask and the clock – are given the property of being `marked for listing`. If it turns out that nothing is marked for listing, because of before rules like the one in the example below, then nothing is printed and **the activity is abandoned**, so that the rules for and after are never reached. **3. Examples.** (a) Promoting something out of the nondescript category, by unmarking it. {*}Before listing nondescript items: if the watch is marked for listing: say "The watch catches your eye."; now the watch is not marked for listing. (b) Changing the normal phrasing of the paragraph. Note that we can also change the listing style; the one below is the default. {*}Rule for listing nondescript items of the Distressingly Messy Room: say "Strewn carelessly on the floor"; list the contents of the Distressingly Messy Room, as a sentence, tersely, listing marked items only, prefacing with is/are, including contents and giving brief inventory information; say "." ## Printing the locale description of something {act_pld} ^^{printing the locale description of something+descactivity+} ^^{locale description: printing the locale description of something+activity+} ^^{descriptions (displayed): room contents} ^^{rooms+kind+: printing the room contents} ^^{precedence: of displayed items}^^^{precedence <-- ordering <-- priority} ^^{mentioned / unmentioned (thing)+prop+} ^^{unmentioned / mentioned (thing)+prop+} ^^{mentioned (thing)+propcat+} ^^{unmentioned (thing)+propcat+} **1. When it happens.** A "locale description" is Inform jargon for the part of a room description which catalogues the visible items in the room. When looking, Inform will normally print the description of the room itself, followed by a locale description for the room. But if the player is in a cage in the room, there will be two locale descriptions: one for the room, then another for the cage. This activity is used to write the locale description for a single domain, and the "something" can be either a room, an enterable container, or an enterable supporter. **2. The default behaviour.** Is quite complicated, and is written up in full in the typeset form of the Standard Rules downloadable from the Inform website. Briefly, though: we first run the `choosing notable locale objects` activity to find out what ought to be mentioned here. That assembles a list of things to mention, sorted into priority order. Items with priority 1 go first, then those with priority 2, and so on. The `printing a locale paragraph` activity is run for each, and in practice that usually hands the job over to `writing a paragraph about`. Sometimes a paragraph will indeed be written, but not always. Sometimes there is nothing interesting to say, and an item is left until a final, single paragraph which gathers up the leftovers (``You can also see a scarlet fish, a harmonium and a kite here.``), the printing of which is done by the `listing nondescript items of` activity. As soon as any item picks up the either/or property `mentioned`, by having its name printed, it is struck out so that it will not appear subsequently, whatever its priority. **3. Examples.** As general advice: if the effect wanted can be got using `writing a paragraph about` and `listing nondescript items of` alone, use those; if it's necessary to meddle further, use `choosing notable locale objects` and `printing a locale paragraph` to alter the normal processes; use the all-powerful `printing the locale description` activity only when the whole process needs to be altered, not the item-by-item workings. (a) In the Very Misty Moorlands, nothing on the ground can ordinarily be seen through the swirling mist, so the locale description is suppressed entirely: {*}Rule for printing the locale description of the Very Misty Moorlands: say "Mist coils around your feet, thick as a blanket. You cannot even see the ground you walk upon." instead. Report taking something in the Very Misty Moorlands: say "You grope blindly in the mist and pick up [the noun]." instead. (b) Here we take the chance to insert an additional paragraph into the locale description. This does relate to an item which might be described later, but where the player doesn't know that: {*}The Horological Workshop is a room. The marble table is fixed in place in the Workshop. The parcel is a closed opaque container on the marble table. The alarm clock is a device in the parcel. The alarm clock is switched on. Before printing the locale description of a room (called the locale): if the locale encloses the alarm clock and the alarm clock is switched on, say "A faint ticking noise can be heard." ## Choosing notable locale objects for something {act_cnlo} ^^{choosing notable locale objects for something+descactivity+} ^^{notable locale objects: choosing notable locale objects for something+activity+} ^^{descriptions (displayed): room contents} ^^{rooms+kind+: printing the room contents} ^^{precedence: of displayed items} ^^{+to+set the locale priority of (object) to (number)} **1. When it happens.** See `printing the locale description`. This activity is expected to decide which items ought to be mentioned in a locale description for a given room, enterable container or enterable supporter, and to give each item a priority, which is a number ranging upwards from 1 (which is the top priority). The lower the priority number, the earlier the mention, or at least, the earlier the opportunity to be mentioned: it's up to other activities whether to give it a paragraph of its own or not. This activity only makes something a candidate, and decides what order the candidates will be tried in. **2. The default behaviour.** By default, this activity contains only the `standard notable locale objects rule`. This chooses exactly those items directly contained by the locale, assigning all of them priority 5. Note that this includes scenery, and other probably unwanted items – those will be excluded later. **3. Examples.** (a) In the Misty Moorlands, only large items on the ground are visible through the mist: {*}A thing can be large or small. A thing is usually small. The stepladder is a large thing in the Misty Moorlands. Rule for choosing notable locale objects for the Misty Moorlands: repeat with item running through large things in the Misty Moorlands: set the locale priority of the item to 5. Report taking a small thing in the Misty Moorlands: say "You grope blindly in the mist and pick up [the noun]." instead. Note the special phrase set the locale priority of the item to 5; which should be used only in rules for locale activities. It makes the given item a candidate and sets its priority. (Setting the priority to 0 forces an item not to be a candidate, and can thus undo the effect of previous rules.) It's best to avoid situations where an item has a locale priority which is higher than that of something it is on top of, or inside, since this can result in an oddly-worded description. ## Printing a locale paragraph about {act_plp} ^^{printing a locale paragraph about something+descactivity+} ^^{printing a locale paragraph about+activity+} ^^{locale paragraph: printing a locale paragraph about something+activity+} ^^{descriptions (displayed): room contents} ^^{rooms+kind+: printing the room contents} ^^{mentioned / unmentioned (thing)+prop+} ^^{unmentioned / mentioned (thing)+prop+} ^^{mentioned (thing)+propcat+} ^^{unmentioned (thing)+propcat+} ^^{supporters+kind+: that don't list contents in room descriptions} **1. When it happens.** See `printing the locale description`. By this point, the locale description process has identified a number of items as candidates to be described, and worked out a priority order. This activity is then called for each candidate in turn, starting with the highest priority items and working downwards. It can either print some text or not, and can either mark the item as `mentioned` or not: if it does, then the item won't appear subsequently in the locale description. If the activity does nothing, the item becomes "nondescript" and falls through into the final ``You can also see...`` paragraph, unless another rule mentions it in the mean time. **2. The default behaviour.** Is provided by a sequence of seven rules: 1. The `don't mention player's supporter in room descriptions rule` excludes anything the player is directly or indirectly standing on or, less frequently, in. The header of the room description has probably already said something like ``Boudoir (on the four-poster bed)``, so the player can't be unaware of this item. 2. The `don't mention scenery in room descriptions rule` excludes scenery. 3. The `don't mention undescribed items in room descriptions rule` excludes the player object. (It's redundant to say ``You can also see yourself here.``) At present nothing else in I7 is `undescribed` in this sense. 4. The `set pronouns from items in room descriptions rule` adjusts the meaning of pronouns like ``IT`` and ``HER`` to pick up items mentioned. Thus if a room description ends ``Mme Tourmalet glares at you.``, then ``HER`` would be adjusted to mean Mme Tourmalet. 5. The `offer items to writing a paragraph about rule` gives the `writing a paragraph about` activity a chance to intervene. We detect whether it does intervene or not by looking to see if it has printed any text. 6. The `use initial appearance in room descriptions rule` prints the `initial appearance` property of an item which has never been handled as a paragraph, if it has one. 7. The `describe what's on scenery supporters in room descriptions rule` is somewhat controversial. It prints text such as ``On the mantelpiece is a piece of chalk.`` for items which, like the mantelpiece, are scenery mentioned - we assume - in the main room description. (It is assumed that scenery supporters make their contents more prominently visible than scenery containers, which we do not announce the contents of.) **3. Examples.** If all that's required is to supply an interesting paragraph of room description about something then it's always better to use the `writing a paragraph about` activity, not this one. This activity should only be used when the mechanism itself needs to be adjusted. (a) The following excludes doors from room descriptions: {*}For printing a locale paragraph about a door (called the item) (this is the don't mention doors in room descriptions rule): set the locale priority of the item to 0; continue the activity. (It's usually a good idea to `continue the activity` at the end of rules for this activity, since usually they all need to take effect for a happy outcome to the process. Here it doesn't really matter, since we were trying to stop anything from happening about the door, but it doesn't do any harm either.) (b) Here's how to abolish what may be the most contentious rule in the whole Standard Rules: {*}The describe what's on scenery supporters in room descriptions rule is not listed in any rulebook. ## Performing something {act_performing} ^^{performing something+descactivity+} ^^{performing+activity+} ^^{dialogue lines: performing something+activity+} ^^{interlocutor (- thing)+actvar+} ^^{speaker (- thing)+actvar+} ^^{style (- performance style)+actvar+} ^^{|spoken normally} ^^{performance styles: |spoken normally} **1. When it happens.** Whenever the dialogue director has definitely decided to perform a line of dialogue. The activity shouldn't be used to undo that decision (i.e., by not printing anything): to suppress dialogue, put conditions on it. The activity has three private variables: - `speaker`. A `thing`, except that it will be `nothing` for a line which is `narrated`. - `interlocutor`. A `thing`, except that it will be `nothing` for a line which is not delivered `to` something. - `style`. A `performance style`, and by default `spoken normally`. **2. The default behaviour.** Performance is carried out by the `default dialogue performance rule`, which reads like so: For performing a dialogue line (called L) (this is the default dialogue performance rule): if L is narrated or L is elaborated or L is non-verbal: say "[textual content of L][line break]"; otherwise: say "[The speaker]"; if the interlocutor is something: say " (to [the interlocutor])"; say ": '[textual content of L]'[line break]". **3. Examples.** (a) This rule puts all narration in italics: For performing a narrated dialogue line (called L): say "[italic type][textual content of L][roman type][line break]". (b) Here we give a different performance for lines with a non-standard performance style: Spoken furiously is a performance style. Before performing a dialogue line (called L): if the style is spoken furiously, say "[bold type]". After performing a dialogue line (called L) : if the style is spoken furiously, say "[roman type]". And then, say: Elizabeth: "We had to pay the ransom, you know." James (spoken furiously): "Even I wouldn't pay fifty thousand pounds for me!" See [Managing dialogue lines] for more. ## Offering something {act_offering} ^^{offering something+descactivity+} ^^{offering+activity+} ^^{dialogue choices: offering+activity+} **1. When it happens.** Whenever the dialogue director has one or more textual choices to ask the player to select between. This activity applies to a list of dialogue choices, which will never be empty. **2. The default behaviour.** Performance is carried out by the `default offering dialogue choices rule`, which reads like so: Last for offering a list of dialogue choices (called L) (this is the default offering dialogue choices rule): let N be 0; repeat with C running through L: increase N by 1; say "([N]) [textual content of C][line break]"; say conditional paragraph break; let M be a number chosen by the player from 1 to N; set the dialogue selection value to M; say "[bold type][textual content of entry M of L][roman type][paragraph break]". **3. Examples.** (a) We could reformat this as a sentence rather than an itemised list like so: For offering a list of dialogue choices (called L): say "Choose: "; let N be 1; repeat with C running through L: if N > 1, say "; "; say "([N]) [textual content of C]"; increase N by 1; say ".[line break]"; say conditional paragraph break; let M be a number chosen by the player from 1 to N; set the dialogue selection value to M; say "[bold type][textual content of entry M of L][roman type][paragraph break]". See [Managing dialogue choices] for more. ## Deciding the scope of something {act_ds} ^^{scope} ^^{|in the presence of} ^^{|presence of} ^^{containment+rel+: placing the contents of something in scope} ^^{Inform 6 equivalent: scope rules} ^^{Inform 6 Designer's Manual+title+} **1. When it happens.** "Scope" is a term of art in interactive fiction programming: it roughly means "what is nearby". See [Scope] for more. The command parser uses scope to decide which names of things to react to, and scope is also used to determine the `visibility relation`, the `audibility relation`, and the `touchability relation`, and whether or not an action is happening `in the presence of` something or somebody. **2. The default behaviour.** For efficiency reasons, the `for` rules for this activity start out empty. Assuming no `for` rule intervenes, what happens in that the algorithm described in [Formal definition of scope] takes effect. But put briefly, the scope for someone consists of everything in the same place as them, unless it is dark or there is some opaque barrier in between. **3. Examples.** (a) We very rarely want to forbid the player to refer to things close at hand, but often want to allow references to distant ones. For instance, a mirage of something which is not present at all: After deciding the scope of the player while the location is the Shrine: place the holy grail in scope. Two different phrases enable us to place unusual items in scope: > phrase: {ph_placeinscope} place (object) in scope > > This phrase should only be used in rules for the `deciding the scope of...` activity. It places the given object in scope, making it accessible to the player's commands, regardless of where it is in the model world. Examples: > > place the distant volcano in scope; > place the lacquered box in scope, but not its contents; > > Ordinarily if something is placed in scope, then so are its parts and (in the case of a supporter or a transparent or open container) its contents; using the `but not its contents` option we can place just the box itself in scope. > phrase: {ph_placecontentsinscope} place the/-- contents of (object) in scope > > This phrase should only be used in rules for the `deciding the scope of...` activity. It places the things inside or on top of the given object in scope, making them accessible to the player's commands, but it does nothing to place the object itself in scope. (It might of course be in scope anyway, and if it is then this phrase won't remove it.) Example: > > place the contents of the lacquered box in scope; > place the contents of the Marbled Steps in scope; > > Note that the object in question can be a room, as in this second example. (b) Another useful device is to be able to see, but not touch, another room: {*}The Cloakroom is a room. "This is just a cloakroom, but through a vague, misty mirror-window you can make out the Beyond." After looking in the Cloakroom, say "In the mirror you can see [list of things in the Beyond]." After deciding the scope of the player while the location is the Cloakroom: place the Beyond in scope. The Beyond is a room. Johnny Depp is a man in the Beyond. (This must, however, also be a mirage, as at time of writing Mr Depp is alive and as well as can be expected following the reviews of _Charlie and the Chocolate Factory_.) Note that `place the Ballroom in scope` doesn't just allow the player to talk about the dancers, the chamber musicians and so forth, also allows, say, ``EXAMINE BALLROOM``. To get one but not the other, use `place the contents of the Ballroom in scope` or `place the Ballroom in scope, but not its contents`. (c) In darkness, the scope of someone is ordinarily restricted to their possessions (and body), but we can override that: After deciding the scope of the player while in darkness: place the location in scope. **4. A note about actions.** This activity takes place during the process of understanding the player's command, when the action that will take place is not fully known. So if the player types ``TAKE SHOEBOX``, this activity would happen when ``SHOEBOX`` is being examined for meaning. Inform knows the action it would be taking if the current line of command grammar were to be accepted, but it does not yet know to what objects that command would be applied. That means attaching a proviso like `... while taking a container` to a rule for this activity will cause the rule to have no effect – whereas `... while taking` would be fine. ## Clarifying the parser's choice of something {act_clarify} ^^{parser's choice: clarifying the parser's choice of something+activity+} ^^{disambiguation: of player commands: displaying parser's chosen thing} ^^{punctuation: brackets: in parser clarifications} ^^{|( ): in parser clarifications} **1. When it happens.** When the player has typed an ambiguous noun reference, and Inform has made a decision about what was meant, and it matters what this decision is. (If the decision is between three identical gold coins, say, then it doesn't matter, and this activity does not take place.) There are a couple of limitations on this: the activity applies only to the first noun, and only if it's an object. So for a command like ``SELECT BLUE``, where ``BLUE`` is a noun referring to a colour value, say, this activity isn't used. But the simple case where the activity does play a part is nevertheless very useful. **2. The default behaviour.** Text in brackets such as ``(the laminated mahogany box)`` is printed, on its own line. **3. Examples.** (a) In the following, asking to ``TAKE TOWER`` results in the parser choosing the souvenir model (because of the `does the player mean...` rule making the alternative unlikely), and then explaining itself by saying ``(The little one, obviously.)`` instead of ``(the souvenir model Eiffel Tower)``. The Champs du Mars is a room. The great Eiffel Tower is here. "The great Tower stands high over you." The souvenir model Eiffel Tower is here. "Comparatively tiny is the souvenir version." The great Eiffel Tower is fixed in place. Does the player mean taking the great Eiffel Tower: it is very unlikely. Rule for clarifying the parser's choice of the model tower: say "(The little one, obviously.)" **4. A note about actions.** This activity takes place during the process of understanding the player's command, when the action that will take place is not fully known. So if the player types ``TAKE SHOEBOX``, this activity would happen when ``SHOEBOX`` is being examined for meaning. Inform knows that the action will be taking, but nothing else. That means attaching a proviso like `... while taking a container` to a rule for this activity will cause the rule to have no effect – whereas `... while taking` would be fine. ## Asking which do you mean {act_which} ^^{which: asking which do you mean+activity+} ^^{disambiguation: of player commands: printing disambiguation request} **1. When it happens.** When the player has typed an ambiguous noun reference, and Inform has not been able to decide what was meant. **2. The default behaviour.** A question such as ``Which do you mean, the laminated mahogany box or the boom box?`` is printed. (This activity shapes the question: it is not responsible for parsing the answer. It would be very mysterious to write rules for this activity such that nothing is printed, because the player would then have no idea what to type.) **3. Examples.** The question is harder to print than may first appear, since one must not simply list the options, but also take into account collections of plural objects (``Which do you mean, the gold-tipped pen or a gold coin?``). It is probably better not to try to rewrite this. (a) But we can place notes before or after: here is a verbose explanation for beginners to IF. Before asking which do you mean: say "Okay, so I'm going to have to ask a question now: you've typed something ambiguous, and I don't know which noun you're referring to." After asking which do you mean: say "(Just type a word or two to give me more information.)" (b) We can also use this activity as a context for other activities. For instance: The Champs du Mars is a room. The great Eiffel Tower is here. "The great Tower stands high over you." The souvenir model Eiffel Tower is here. "Comparatively tiny is the souvenir version." The great Eiffel Tower is fixed in place. Understand "actual" as the great Tower. Rule for printing the name of the great Tower while asking which do you mean: say "actual Tower". Rule for printing the name of the souvenir tower while asking which do you mean: say "souvenir". causes ``TAKE TOWER`` (for instance) to produce a nice tidy question in reply: ``Which do you mean, the actual Tower or the souvenir?`` **4. A note about actions.** This activity takes place during the process of understanding the player's command, when the action that will take place is not fully known. So if the player types ``TAKE SHOEBOX``, this activity would happen when ``SHOEBOX`` is being examined for meaning. Inform knows that the action will be taking, but nothing else. That means attaching a proviso like `... while taking a container` to a rule for this activity will cause the rule to have no effect – whereas `... while taking` would be fine. ## Supplying a missing noun/second noun {act_smn} ^^{missing noun: supplying a missing noun/second noun+activity+} **1. When it happens.** (Two different activities here, but identical except for applying to different nouns.) This happens when an Understand sentence fails to supply a noun for an action which requires one. For example, in the sentence `Understand "seize" as taking.`, the `taking` action is incompletely specified, because it requires a noun, and there's no noun in the command to be understood. Note that this is not what happens if it's the player who fails to supply the noun. That is, suppose the player types a half-finished command like ``TAKE``, which can't be matched against (for example) `Understand "take [things]" as taking.` because the player didn't name any thing(s). Typically a story will reply to such a command with a question asking for clarification, but sometimes it makes guesses about what was meant. The `supplying a missing noun` activity plays no part in this guesswork, and can't influence it: that's the task of the `does the player mean` rulebook. Suppose we do have the first of these cases, then. `Supplying a missing noun` takes place to remedy the problem. It can either: (i) Set a noun, printing text like ``(presumably the black bag)`` if it wants, in which case the action goes forward, though it is still subject to the full rules on accessibility exactly as any other action would be; or (ii) Make no choice, in which case no action takes place and the player's command is rejected. If the activity printed nothing, Inform will produce a generic reply to the player that ``You must supply a noun.``. **2. The default behaviour.** In the default grammar for Inform, only three such half-finished actions are ever Understood. One is `going` with no direction, for which this activity simply prints a refusal. The other two are the two undirected senses, `smelling` and `listening`. In each case, the `supplying a missing noun` activity sets the noun to the current location: so, for instance, typing the bare command ``LISTEN`` might generate the action `listening to the Shoreline`. **3. Examples.** (a) This is the definition Inform uses to make ``LISTEN`` work as outlined above: Rule for supplying a missing noun while listening (this is the ambient sound rule): now the noun is the location. (b) It can be elegant to allow second nouns to be dropped with habitual actions, or where the choice is obvious: {*}Understand "unlock [something]" as unlocking it with. Rule for supplying a missing second noun while unlocking: if the skeleton key is carried, now the second noun is the skeleton key; otherwise say "You will have to specify what to unlock [the noun] with." Note that, in order for our activity to succeed, we do need to supply a grammar line allowing the player to try `unlocking it with` using only one noun. Otherwise, the command ``UNLOCK SOMETHING`` will still produce the question ``What do you want to unlock the door with?`` ## Reading a command {act_reading} {var_command} {kind_snippet} ^^{understanding: special processing of keyboard input} ^^{Inform 6 equivalent: |BeforeParsing} ^^{snippets} ^^{player's command (- snippet)+glob+} ^^{reading a command+activitycat+} ^^{reading a command+activity+} ^^{matched text (- snippet)+glob+} ^^{punctuation: removing from player's command} ^^{regular expressions} ^^{text: regular expressions} ^^{topics: matching snippets} ^^{>OOPS} **1. When it happens.** When reading a command from the keyboard. **2. The default behaviour.** Print the prompt text; wait for the player to type something and press return. Reject an entirely blank line, and treat a command beginning ``OOPS`` as a correction to the previous one. This is a fairly complicated business, so it is probably best not to change the `for` rules for this activity: `before`, and especially `after`, are another matter. (Note, however, that if Inform does reject a blank line and ask for another then this all happens inside the `for` rules: no `after` occurs after the blank line, nor does a `before` happen before the second attempt by the player. It is all a single round of the activity, not two.) **3. Examples.** (a) To lead absolute beginners in gently: Before reading a command while the turn count is 1, say "(This is your chance to say what the protagonist should do next. After the '>', try typing 'take inventory'.)" (b) The following responds politely but firmly if the player tries to type ``PLEASE LOOK``, say, instead of just ``LOOK``: {*}After reading a command: if the player's command includes "please": say "Please do not say please."; reject the player's command. To explain. Fragments of what the player has typed are called snippets: `the player's command` is the entire thing. We can test if a snippet matches a given pattern like so: > phrase: {ph_snippetmatches} if (snippet) matches (topic): > > This condition is true if the given snippet exactly matches the specification. Example: > > if the player's command matches "room [number]", ... > > will be true if the command is ``ROOM 101``, but not if it's ``EXPLORE ROOM 7``. > phrase: {ph_snippetdoesnotmatch} if (snippet) does not match (topic): > > This condition is true if the given snippet does not exactly match the specification. > phrase: {ph_snippetincludes} if (snippet) includes (topic): > > This condition is true if the given snippet includes words matching the specification, either at the beginning, in the middle, or at the end. Example: > > if the player's command includes "room [number]", ... > > will be true if the command is ``ROOM 101``, ``EXPLORE ROOM 7``, or ``ROOM 22 AHOY``, but not if it's ``VISIT ROOM GAMMA 7``. > phrase: {ph_snippetdoesnotinclude} if (snippet) does not include (topic): > > This condition is true if the given snippet does not include any run of words which matches the specification. Lastly, we took drastic action with another new phrase: > phrase: {ph_rejectcommand} reject the/-- player's command > > This phrase should be used only in rules for the `reading a command` activity. It tells Inform not to bother analysing the text further, but to go back to the keyboard. (No time passes; no turn elapses; nothing happens in the simulated world.) (c) An improved version takes commands like ``PLEASE DROP THE COIN`` and strips ``PLEASE`` from them, but then allows them to proceed normally: {*}After reading a command: if the player's command includes "please": say "(Quelle politesse! But no need to say please.)"; cut the matched text. `Matched text` is a snippet containing the words which matched against the pattern in the most recent `includes` condition, so in this case it contains just the single word ``PLEASE``. Two phrases allow snippets to be altered: > phrase: {ph_replacesnippet} replace (snippet) with (text) > > This phrase should be used only in `after` rules for the `reading a command` activity; it replaces the snippet of command, usually the `matched text` found immediately before, with the given text. Example: > > if the player's command includes "room [number]": > replace the matched text with "office". > phrase: {ph_cutsnippet} cut (snippet) > > This phrase should be used only in `after` rules for the `reading a command` activity; it removes the snippet of command. Example: > > if the player's command includes "or else": > cut the matched text. Note that `replace` and `cut` can only be used in `after reading a command` rules: not when an action has been chosen and has gone ahead into its rulebooks. Once the `reading a command` activity has finished, the command is final. (d) To make the word ``GRAB`` an abbreviation for ``TAKE ALL``: {*}After reading a command: if the player's command matches "grab", replace the player's command with "take all". (`Snippet` is actually a kind of value, so we could say `"Ah, you typed '[the player's command]'!"` or some such if we liked. But in practice only three snippets are likely to be useful: the two mentioned above, `player's command` and `matched text`, and the `topic understood`, used when matching the `"[text]"` token in command grammar.) (e) Finally, we can make still more detailed alterations to the text of the command using the techniques presented in the chapter on [Advanced Text]. For instance: > phrase: {ph_changecommand} change the text of the/-- player's command to (text) > > This phrase should be used only in `after` rules for the `reading a command` activity; it replaces the current command text entirely. Example: > > After reading a command: > let T be "[the player's command]"; > replace the regular expression "\p" in T with ""; > change the text of the player's command to T. > > This converts the player's command to text, which is then manipulated by searching for any punctuation mark and replacing it with blank text (that is, deleted), and then put back again as the new command. ## Implicitly taking something {act_implicitly} ^^{taking+action+: implicit taking} **1. When it happens.** When an action is tried which requires the actor (normally the player, of course) to be carrying something, but which is not in fact carried by that person. For instance, if the player types ``WEAR OVERCOAT`` in reference to a Moroccan overcoat currently draped over a chair. **2. The default behaviour.** To print text such as ``(first taking the Moroccan overcoat)`` and then silently try taking the object in question (the overcoat). If the take succeeds, the silence means that nothing else is printed: if it fails, it will say why. No matter what rules are written for this activity, it is impossible to use it to allow the action to go ahead even without the item. The activity allows us to change how, or if, an implicit take will happen, but not to change the consequences of failure. (To do that, we would need to say that `The carrying requirements rule does nothing`, but this kind of unstitching of the action machinery needs to be done with caution.) **3. Examples.** (a) Forbidding implicit takes for certain dangerous items. (This seems especially fair if taking such items might cause death: the player will not wish to be killed on the strength only of our guess as to what they might be intending to do.) Rule for implicitly taking the curare: say "Ordinarily you'd pick up the curare in order to be able to do that, but this seems like a good moment for caution." instead. (b) Changing the way the implicit action is reported for the player: Rule for implicitly taking something (called target): try silently taking the target; if the player carries the target, say "You appropriate [the target] first, of course. [run paragraph on]" (c) Combining implicit takes when the noun and second noun must both be carried: Rule for implicitly taking the noun when the second noun is a thing and the second noun is not carried by the player: try silently taking the noun; try silently taking the second noun; say "(first taking both [the noun] and [the second noun])[line break]" (d) Making another character reply amusingly: Rule for implicitly taking something which is carried by the player when the person asked is Clark: say "'I don't see how I'm supposed to do that when you're holding [the noun],' remarks Clark sulkily." instead. (e) Causing implicit takes which wouldn't otherwise happen. Suppose we have a photographing action, and there are very small flowers which can't conveniently be snapped without being first picked. We then want an implicit take to occur, even though we wouldn't want this for other sorts of photography. So: Check an actor photographing a flower: if the actor is not carrying the noun: carry out the implicitly taking activity with the noun; if the actor is not carrying the noun, stop the action. Note that if the activity doesn't succeed in taking the item, it's expected to print some text explaining this, which is why we don't need to say anything further. ## Printing a parser error {act_parsererror} ^^{understanding: error messages for parsing errors} ^^{error messages: for player commands} ^^{parser error messages} ^^{latest parser error (- command parser error)+glob+} **1. When it happens.** The parser is the part of the run-time software, included in all works produced by Inform, which tries to match the player's command against the grammar provided by the work. When it is unable to make a valid match, the parser prints an error to the player: for instance, > BIFURCATE TREE That's not a verb I recognise. There are more than twenty possible messages. The one which the parser wants to say is stored in the variable `latest parser error`, which has the convenient kind `command parser error`. This has the following possible values: - didn't understand error - only understood as far as error - didn't understand that number error - can't see any such thing error - said too little error - aren't holding that error - can't use multiple objects error - can only use multiple objects error - not sure what it refers to error - excepted something not included error - can only do that to something animate error - not a verb I recognise error - not something you need to refer to error - can't see it at the moment error - didn't understand the way that finished error - not enough of those available error - nothing to do error - referred to a determination of scope error - I beg your pardon error - noun did not make sense in that context error - can't again the addressee error - comma can't begin error - can't see whom to talk to error - can't talk to inanimate things error - didn't understand addressee's last name error **2. The default behaviour.** Prints the message in question. **3. Examples.** (a) Perhaps for newcomers: {*}After printing a parser error: say "If you are new to interactive fiction, you may like to try typing HELP." (b) Or to give the parser a certain amount of character: {*}Rule for printing a parser error when the latest parser error is the I beg your pardon error: say "What's that? Speak up, speak up." instead. {*}Rule for printing a parser error: say "That's a rum thing to say, and no mistake." instead. (c) This can be helpful for seeing what's going on: {*}Rule for printing a parser error: say "The [latest parser error] happened."; continue the activity. ## Deciding whether all includes {act_all} ^^{understanding: deciding whether (ALL) includes something+commandpart+} ^^{+toout+it does / it does not (deciding whether all includes)} ^^{(ALL), including things in+commandpart+} **1. When it happens.** When parsing a command such as ``TAKE ALL``, where the player uses ``ALL`` to signify everything within reach. **2. The default behaviour.** The actual method used is complicated, as ``ALL`` is not as simple as it seems – ``TAKE ALL`` would not include the player's own body, for instance, or the crescent moon. The point of this activity is to allow the normal method to be changed for given objects, or given kinds of object. **3. Examples.** (a) Removing scenery from ``ALL`` (but see (4) below): {*}Rule for deciding whether all includes scenery: it does not. The phrases `it does` and `it does not` make a decision. (b) Ensuring that a given thing, which might otherwise be excluded, is included: {*}Rule for deciding whether all includes the oval roof: it does. **4. The Standard Rules already uses this.** Note that the Standard Rules already stocks this activity with several rules: exclude scenery from take all rule exclude people from take all rule exclude fixed in place things from take all rule **5. A note about actions.** This activity takes place during the process of understanding the player's command, when the action that will take place is not fully known. So if the player types ``TAKE SHOEBOX``, this activity would happen when ``SHOEBOX`` is being examined for meaning. Inform knows that the action will be taking, but nothing else. That means attaching a proviso like `... while taking a container` to a rule for this activity will cause the rule to have no effect – whereas `... while taking` would be fine. ## Printing the banner text {act_banner} ^^{banner text} ^^{when play begins+rb+: printing the banner text+activity+} ^^{bibliographic data} ^^{title+biblio+} ^^{author+biblio+} ^^{headline+biblio+} ^^{release number+biblio+ <-- version number (of story)} ^^{>VERSION} **1. When it happens.** The banner is the bibliographic masthead text, which typically looks something like this: ^^{@Emily Short} Relations An Interactive Fiction by Emily Short Release 1 / Serial number 050630 / Inform 7 v10.2.0 (The serial and build numbers are those applying when the story file was last made: these ones are from the mid-2000s.) The banner is printed at the start of play, and when the player types ``VERSION`` at the command line, and when say `"[banner text]"` occurs. > phrase: {phs_banner} say "[the/-- banner text]" > > This text substitution expands to the banner text giving bibliographic details of the current story file, rather like the opening credits of a movie, or the title page of a book. **2. The default behaviour.** Prints the text above, giving the title, the headline, the author, the release number, the date of compilation (that's the serial number: YYMMDD), and version numbers of the Inform components used to put the story together. This is done by the `standard printing the banner text rule`. Lines 1 to 3 of the standard banner are responses `(A)` to `(C)` of this rule. **3. Examples.** (a) Adding a line to the banner: After printing the banner text, say "DRM authentication code: 13S-451-2034u75y65u%%a1248." (b) Amending a line in the banner: The standard printing the banner text rule response (C) is "There are versions, but it's not like you care." (c) Replacing the banner altogether: Rule for printing the banner text: say "Welcome." instead. ## Printing the player's obituary {act_obit} ^^{end of story} ^^{victory} ^^{death} ^^{winning the story} ^^{losing the story} ^^{when play ends+rb+: printing the player's obituary+activity+} **1. When it happens.** The obituary is the text `"*** You have died ***"` or similar, sometimes followed by a final score, if the appropriate use option (`Use scoring.`) is in force. **2. The default behaviour.** Printing the aforementioned text, then the final score, and reducing the status line to a largely blank state. **3. Examples.** Here's one way to add to the verdict of history: {*}After printing the player's obituary: say "And you visited [number of visited rooms] place[s]." ## Amusing a victorious player {act_amuse} ^^{when play ends+rb+: amusing a victorious player+activity+} ^^{end of story} ^^{victory} ^^{death} ^^{winning the story} ^^{losing the story} ^^{(finally), ending the story+sourcepart+} ^^{>AMUSING} **1. When it happens.** When the player chooses ``AMUSING`` from the short menu of choices after a story has been won. Traditionally, this is where the author gets to point out quirky by-ways of the story, or make some final acknowledgements, or simply salute the player's perseverance. Note that the ``AMUSING`` option is only offered when the story has ended finally, and that it is only offered if there is at least one rule present in the `for amusing a victorious player` rulebook. **2. The default behaviour.** None. The `for amusing a victorious player` rulebook is empty by default, and no amusement is available. **3. Examples.** The format would be like so: {*}Rule for amusing a victorious player: say "Hmm. You're easily amused." ## Starting the virtual machine {act_startvm} ^^{virtual machine: starting the virtual machine+activity+} **1. When it happens.** This activity is provided as a "hook" for any low-level tasks which need to be performed when the virtual computer which runs Inform story files is starting up. This happens much earlier than `when play begins` rules, and contains a lot of critical low-level code; most authors will not need to delve into its details, but if necessary it can be controlled like any other activity. Extension authors however may find it to be a useful place to put their code. It should be remembered that Inform can produce story files for several different virtual computers. On some of these, it may not be safe to print any text during this activity, as the windows which would display such text do not yet exist. In Glulx, Inform's default format, you can safely print text in the after rules, but not the before or for rules. In general, the three rulebooks of the activity should be used in this manner: (i) The before rulebook should be used only for rules that do not need any input/output systems. (ii) The for rulebook should be used for rules involved with setting up the input/output systems. (iii) The after rulebook should be used for rules which depend on the input/output systems. Many extensions would most appropriately put their rules in the after rulebook, though Glk extensions will often need to use all three. **2. The default behaviour.** Inform's low-level systems are set up, as well as the virtual machine's input/output systems. **3. Examples.** No detailed examples will be given here, but the activity might be used (for instance) to set styles for the Glulx windows shortly to be brought into existence. # Rulebooks ## On rules {kind_rule} {kind_rulebook} {RULEBOOKS} {PM_RulebookWithAt} {PM_RulebookWithDefinition} {PM_RulebookWithTo} ^^{rulebooks} When we open the casing and look inside the machinery of Inform, what we see are rules and rulebooks. We seldom need to know how this machinery works, but every once in a while we want to replace components, or even install new mechanisms of our own. And as we shall see, creating new rulebooks can be a neat way to tackle complicated simulations full of exceptions and special cases. So far we have seen many rules, and the term _rulebook_ has frequently but vaguely been used. Here is a summary of the rulebooks seen so far: - before - instead - after - check taking, carry out taking, report taking - *and three similar rulebooks for each of the 90 or so actions* [comment to break to a new list]:: - persuasion - unsuccessful attempt - reaching inside - reaching outside - visibility - does the player mean - when play begins - when play ends - every turn [comment to break to a new list]:: - when Confrontation Scene begins - when Confrontation Scene ends - *and two similar rulebooks for each scene we create, if any* [comment to break to a new list]:: - before printing the name of - for printing the name of - after printing the name of - *and three similar rulebooks for each of the 20 or so activities* Which makes around 340 rulebooks before we even start to write. All the same, not everything in Inform belongs to a rulebook – timed events, for example, are rules which normally live outside of rulebooks; and other constructions, such as newly-created phrases, or definitions, may look vaguely like rules, but they aren't. So the following are not rulebooks: At 11:10 PM: ... To dislodge the shelf: ... Definition: ... ## Named rules and rulebooks ^^{rules: in rulebooks} ^^{rulebooks} ^^{names: of rules} ^^{rules: order in rulebooks} ^^{rulebooks: order of rules} ^^{precedence: of rules} ^^{disambiguation: of source text: precedence of rules} Most of the rules built into Inform have names. For instance, a rule called `the advance time rule` is the one which increments the number of turns and advances the clock, values which are usually not visible, but are ticking away behind the scenes. A rulebook is a list of rules to be followed in sequence until one of them makes a decision. For instance, when actions get to the `instead` stage, each `instead` rule is tried until one of them chooses to do something. If the source text contains the rules Instead of taking something: say "You have no particular need just now." Instead of taking a fish: say "It's all slimy." and a command to ``TAKE`` something is tried, then only one of these rules will have any effect. The `instead` rulebook contains: - Rule (1) to be applied if the action matches "taking a fish" - Rule (2) to be applied if the action matches "taking something" Inside their rulebook, the rules are not listed in the order of definition in the source text. Rule (1) comes before rule (2) because it applies in more specific circumstances. This is the main idea: a rulebook gathers together rules about making some decision, or taking some action, and sorts them in order to give the more specific rules first choice about whether they want to intervene. Only some rules have names — rules (1) and (2) are nameless — but every rulebook is named. (These are rules belonging to the `instead rulebook`.) When rules do have names, they always end in `rule`: the `can't go through closed doors rule`, for example. It's good style for rules to have quite verbose names like this, because they aren't referred to in source text very often, but when they are, clarity is much better than brevity. Rulebook names similarly end in `rulebook`, but Inform also recognises the name with `rules` at the end. So `instead rules` means the same thing as `instead rulebook`. The names of built-in rules have been chosen as descriptively as possible: the `can't go through closed doors rule`, for instance. Names for rules tend to be verbose, but this is a situation where clarity is very much better than brevity. ## New rules {PM_BadRulePreambleWhen} {PM_BadRulePreamble} {PM_RuleWithDefiniteArticle} {PM_RuleWithoutColon} ^^{rules: defining} ^^{defining: rules} ^^{rules: naming} ^^{names: of rules} ^^{this is the (name) rule...+assert+} ^^{punctuation: colon} ^^{|:} Stretching a point seasonally, we might write: Every turn, say "The summer breeze shakes the apple-blossom." This rule is nameless. It needs no name because it will never need to be referred to: by identifying it as an every turn rule we have already said enough to lodge it in the `every turn` rulebook. In fact, though, it is easy to create a named rule: This is the blossom shaking rule: say "The summer breeze shakes the apple-blossom." The name of a rule must always end with the word `rule`, for clarity's sake. (The phrasing `This is the ... rule` is used because `The ... rule` would be open to misinterpretation.) Previously we had a rule which had no name, but belonged to a rulebook: now we have the opposite, because although the `blossom shaking rule` has a name, it has not been placed in any rulebook. That means it will probably never be applied, unless we give specific instructions for that. Alternatively, it is possible to both name and place a rule in a single sentence: Every turn (this is the alternative blossom rule): say "The summer breeze shakes the apple-blossom." Now the `alternative blossom rule` is a named rule in the `every turn` rulebook. ## Listing rules explicitly {RLISTING} {PM_ImproperRulePlacement} {PM_BadRulePlacementNegation} {PM_UnspecifiedRulebookPlacement} {PM_NoSuchRuleExists} {PM_PlaceWithMissingRule} ^^{rules: order in rulebooks} ^^{rulebooks: order of rules} ^^{precedence: of rules} ^^{disambiguation: of source text: precedence of rules} ^^{(listed in / before / after / instead of), for placing rules in rulebooks+sourcepart+} ^^{(not listed in), for removing rules from rulebooks+sourcepart+} ^^{rules: removing} ^^{rules: replacing} ^^{(before), ordering for rules+sourcepart+} ^^{(after), ordering for rules+sourcepart+} ^^{(instead of), replacing rules+sourcepart+} ^^{(first), listed first in rulebook+sourcepart+} ^^{(last), listed last in rulebook+sourcepart+} If rules can manage perfectly well without, why bother to have names for rules? The answer is that although Inform contains an elaborate mechanism for placing rules into the correct rulebook at the correct position, and this happens automatically, Inform will sometimes get it wrong. It will use a rule we do not want, or place them in an order which does not suit us. To put this right, we can give explicit instructions which take precedence over Inform's normal practice. This is done with the `to list` verb, as in the following examples. 1. The simplest usage is to place a named rule, which currently has no home, in any rulebook of our choice. (This looks redundant, but just occasionally we want the same rule to appear in two different rulebooks.) The blossom rule is listed in the every turn rules. A rule can appear in more than one rulebook, but within any single rulebook it can only appear once. 2. We can also specify that the rule needs to appear before, or after, some other named rule in the same rulebook: The collapsing bridge rule is listed before the moving doorways rule in the instead rules. Instead of being placed in specificity order in the whole `instead` rulebook, the `collapsing bridge` rule would now be placed in specificity order only in the first half of the `instead` rulebook – the rules from the start up to (but not including) the `moving doorways` rule. To reiterate: that doesn't necessarily mean it will be immediately before the `moving doorways` rule; it will be placed according to Inform's usual sorting rules within that range. `Listed` sentences are obeyed by Inform in sequence, so if later ones issue instructions contradicting earlier ones, it's the later ones which win out. Thus if we say `A is listed before B in X` and then `B is listed before A in X`, the result is that B comes before A. 3. We can specify that a rule needs to appear first or last in a given rulebook: The collapsing bridge rule is listed first in the instead rules. Again, if we make several such instructions about the same rulebook then the most recent one wins: `A is listed first in X. B is listed first in X. C is listed first in X.` causes rulebook X to begin C, B, A. 4. We can also substitute one rule for another: My darkness rule is listed instead of the can't act in the dark rule in the visibility rules. If rule A is listed instead of rule B in rulebook X, and A was already a rule in rulebook X, then A will move from its previous position to occupy the place where B was, and B will disappear. (In particular rule A will not be duplicated, which would break the principle that no rule occurs twice in the same rulebook.) 5. And we can strike down existing rules, either specifically or in all their applications: The can't act in the dark rule is not listed in the visibility rules. The can't remove from people rule is not listed in any rulebook. This does not actually destroy the rules in question: they could still, for instance, be put into another rulebook, or even be applied explicitly, as we shall see. But unless we take deliberate action to the contrary, un-listing a rule amounts to abolishing it forever. This is a little drastic, and more subtle effects can be seen in the next section. ## Changing the behaviour of rules {rules_proc} ^^{rules: removing} ^^{rules: changing conditions of rules} ^^{rules: replacing} ^^{conditions: for rules} ^^{conditions: changing conditions of rules} Here is another way to abolish an already-existing rule: The print final score rule does nothing. The rule continues to be listed in any rulebook it would normally be listed in: but now it doesn't do anything. As a result, any responses it might have had no longer exist. As it happens, this one has no responses, but consider these two different ways to frustrate the normal operation of the same rule: The can't exit when not inside anything rule does nothing. The can't exit when not inside anything rule is not listed in any rulebook. The first way effectively deletes the content of a rule, as if its definition were: The can't exit when not inside anything rule: do nothing. As a result, the response `can't exit when not inside anything rule response (A)`, which is part of its normal contents, no longer exists. On the other hand, the second method for frustrating the rule takes it out of its normal rulebook, so that it will not normally take effect, but does not delete its definition. The `can't exit when not inside anything rule response (A)` then continues to exist. If we say that the rule does nothing only under under some `if` or `unless` condition, as here: The print final score rule does nothing if the score is 0. ...then the rule's response would once again continue to exist (as it must, because it might be issued if the score were _not_ 0). We can also substitute a rule of our own: This is the print fancy final score rule: say "Oh my, you scored a mammoth [score]!" The print fancy final score rule substitutes for the print final score rule. and once again a condition can be applied: The print fancy final score rule substitutes for the print final score rule when the score is greater than 100. ## Sorting and indexing of rules ^^{rules: order in rulebooks} ^^{rulebooks: order of rules} ^^{precedence: of rules} ^^{disambiguation: of source text: precedence of rules} ^^{laws for sorting rulebooks} ^^{Rules page of Index panel+ui+} ^^{user interface: Index panel: Rules page} ^^{Index panel+ui+: Rules page} The Rules page of the index for a project offers a view of the rulebooks and their contents, with two major exceptions: built-in rules for specific actions are left to the Actions page, and any rules for scene endings or beginnings are left to the Scenes page. As we have seen, we need to know the name of a rule before we can change its rulebook listing or alter its applicability. The Rules and Actions index pages show the names of the built-in rules, which are not worth memorising. (Typing can be saved by using the paste-into-source buttons, or by selecting a rule's name and copying and pasting it by hand.) In the Rules index, each rulebook is named and then followed by a list of the rules within it, one on each line: if nothing follows, then the rulebook is currently empty. The rules are given in order, and icons are used which indicate which rules are more specific than which others. Hovering the mouse over such an icon should bring up a "tooltip" which explains Inform's reasoning. As this suggests, Inform performs its automatic sorting using a precise collection of Laws (the term "rules" would be ambiguous here, so we call these guidelines Laws instead), and the tooltip shows which Law was applied. It is bad style to write source text which absolutely depends on detailed points of these Laws, but they are documented at the end of this chapter for those who do wish to see the full details. ## The preamble of a rule ^^{rules: preamble} ^^{rules: defining} ^^{defining: rules} ^^{rules: naming} ^^{names: of rules} ^^{this is the (name) rule...+assert+} ^^{(first), listed first in rulebook+sourcepart+} ^^{(last), listed last in rulebook+sourcepart+} ^^{during (scene)+sourcearg+} ^^{when (condition)+sourcearg+: arbitrary conditions for rules} ^^{while (condition)+sourcearg+: arbitrary conditions for rules} ^^{conditions: for rules} ^^{to (phrase name)...+assert+} ^^{at (time)...+assert+} ^^{definition+assert+} Not counting a few instructions (`Understand ...` or `Include ...`) and headings (`Section 2`), Inform source text is a mixture of two basic ingredients. There are "assertion sentences", which say that something is true. `A mammal is a kind of animal.`, or `The parcel is on the low table.`, are typical assertions. And then there is "imperative code", which tells Inform exactly what to do, step by step, in some situation. Here are some examples: Definition: A thing (called the item) is verbose: if the item is the Tolstoy novel, decide no; if the number of characters in the printed name of the item is greater than 10, decide yes; decide no. To dispel (illusory item - a thing): now the illusory item is out of play; say "[The illusory item] vanishes into nothingness." When play begins: showme the list of verbose things. Instead of taking the parcel, say "It's far too heavy to pick up." Instead of taking the parcel: dispel the parcel. At 11:02 am: say "The clock chimes, late as usual." Of these six examples, only four are rules. The first two, the `Definition` and the `To ...` phrase, are not rules. A definition is applied when Inform wants to know whether or not a given thing satisfies it. For example, the definition of `verbose` will be needed when Inform has to work out the `list of verbose things`. See [New conditions, new adjectives]. The `To dispel...` business will happen only if some other piece of imperative code explicitly calls for it, with a line like `dispel the parcel`. See [Phrases]. Although the `At 11:02 am` example _is_ a rule, we won't discuss it further in this section. As the wording suggests, it takes effect at a given time of day. That's very much an exception in the world of rules, which are almost all filed into rulebooks. The general shape of all of these clumps of imperative code is: preamble: phrase 1; phrase 2; ... phrase N. In a few common cases, where the preamble begins with `Before`, `After`, `Instead of`, `Every turn`, or `When`, and where there is only one phrase in the list, the colon can be replaced with a comma. So these are equivalent: Instead of taking the parcel, say "It's far too heavy to pick up." Instead of taking the parcel: say "It's far too heavy to pick up." With all of that said, the part before the colon (or the comma) is the so-called "preamble". The preamble can say what the rule's name is, or when it takes effect, or both. Here is a preamble giving only a name: This is the redraw the map rule: ... This gives no indication of when the rule should be used, and the answer is that it therefore won't be used, unless the author writes an assertion which places it explicitly into some rulebook which _will_ be used (`The redraw the map rule is listed in...`), or uses a special phrase to make it happen (`follow the redraw the map rule`). Here is a preamble which says when the rule should take effect, but does not give names: When play begins: ... And this is a preamble which does both: Carry out taking inventory (this is the print empty inventory rule): ... Note that if a name _is_ given, it must end with the word `rule`. Our remaining example rules tell Inform what rulebook they should be listed in, and in fact this is what almost all rules do. * `When play begins` places the rule into the `when play begins rulebook`, which Inform works through... well, you can guess. * `Instead of taking the parcel` places the rule into the `instead rulebook`, which Inform works through when processing actions. The rule takes effect only if the action matches the `taking the parcel` description. Inform allows a few extra words to be used in these preambles for clarity, or because the author prefers to. `A when play begins rule` would have had the same effect as just `When play begins`. `An instead rule for taking the parcel` would have been equivalent to `Instead of taking the parcel`. How does Inform read such an instruction about where to file a rule? It works through from left to right: 1) Optional: `a` or `the`. 2) Optional: the word `first` or `last`. 3) Required: a rulebook name, but without the word `rulebook` or `rules` at the end. 4) Optional: the word `rule`. 5) Optional: one of * the preposition `about` or `for` or `of` or `on` followed by some applicability text, _or_ * just the applicability text on its own. 6) Optional: `while` or `when` followed by a condition. 7) Optional: `during` followed by the name of a scene. For example, `instead of taking the parcel` contained (3) `instead` and then (5) `of` plus `taking the parcel`. `When play begins` contained just (3). `A last when play ends rule when the score is greater than 10` consists of (1) `a`, (2) `last`, (3) `when play ends`, (4) `rule`, (6) `when` plus `the score is greater than 10`. If the preamble begins `first`, it is placed early in the rulebook. It will literally be first if it's the only one asking for that, or will be among those which did if not. And similarly for `last`. Rules are designed to be highly flexible, which is why so much is optional. We could even define a rule with the one-word preamble `Instead` if we wanted — though its universal applicability would make it pretty disruptive, with every action stopped in its tracks. ## New rulebooks {NEWRULEBOOKS} ^^{defining: rulebooks} ^^{rulebooks: defining} ^^{rulebooks: invoking a rulebook} ^^{rules: invoking a rule} ^^{empty / non-empty+adj+: for rulebooks} ^^{non-empty / empty+adj+: for rulebooks} ^^{rulebooks: empty / non-empty+adj+} ^^{rulebooks: as a kind of rule} Creating a new rulebook is also straightforward, as we see in the following modest example story: {*}"Appraisal" The Passage is east of the Tomb. The green-eyed idol is in the Tomb. A Speak-Your-Progress machine is in the Passage. Appraisal rules is a rulebook. An appraisal rule: say "Click... whirr... the score is [the score in words] points." An appraisal rule: if we have taken the idol, say "Most importantly of all, the idol has been found." Instead of switching on the machine, follow the appraisal rules. The creation of the rulebook is all very well, but without the final sentence it would never be used. The crucial new phrase here is: > phrase: {ph_follow} follow (rule) > > This phrase causes the rule to be obeyed immediately (rather than simply at predetermined times such as when a particular action is being tried, or at the end of every turn, and such). Example: > > follow the advance time rule; > follow the appraisal rulebook; Like `number` or `text`, `rule` and `rulebook` are kinds of value built into Inform: `the blossom rule` is a value whose kind is `rule`, whereas `the every turn rules` is a value whose kind is `rulebook`. In fact, Inform considers a rulebook to be a special case of a rule, so that whenever a rule is required it is legal to name a rulebook instead, but not vice versa. The `follow` phrase here... Instead of switching on the machine, follow the appraisal rules. ...expects to be applied to a value of kind `rule`; `the appraisal rules` is in fact a rulebook, but since that counts as a rule the phrase makes sense to Inform. To follow a rulebook means to run through all its rules in turn, stopping when one rule reaches an outcome; to follow a single rule means just that one, of course. When created, a rulebook starts out with no rules in it – in this example, of course, we quickly defined a couple of rules to go into it. But it's often the case in Inform that a rulebook exists without ever being stocked up, especially if the rulebook is for some obscure purpose never needed. The built-in adjectives `empty` and `non-empty`, applied to a rulebook, test whether any rule is present or not. ## Basis of a rulebook ^^{basis of rulebook} ^^{rulebooks: basis of rulebook} ^^{rulebooks: rulebook parameters} ^^{parameters: of rulebooks} ^^{values: basis of rulebooks} Every rulebook works on a value supplied to it, though it doesn't always look that way. The kind of the value is called its "basis"; for example, if a rulebook works on a number, it's called a `number based rulebook`. Most of the rulebooks seen up to now have been action based rulebooks: Instead of eating the cake: ... `Instead` is an action based rulebook, and the action it works on is the one currently being processed. Besides before, after and instead, other action based rulebooks include the check, carry out, and report rules; general rulebooks such as every turn rules, the visibility rules, the turn sequence rules; and rules specially for dealing with the actions of other characters, such as the persuasion and unsuccessful attempt rules. But we have also seen object based rulebooks: Rule for reaching inside the flask: ... `Reaching inside` is an object based rulebook, and here we're giving it a rule which applies if the object is the flask. Inform would reject something like: Rule for reaching inside 100: ... because 100 has the wrong kind to fit – it's a number, not an object. There are many object based rulebooks, because most activities built-in to Inform act on objects. For example, the `printing the name of` activity has three rulebooks attached to it: before printing the name of, for printing the name of, after printing the name of. All of these are object based rulebooks. Finally, we've also seen scene based rulebooks (which is how rules like `when a recurring scene ends` worked, in the chapter on [Scenes]). If a rulebook is declared like so: Marvellous reasoning is a rulebook. then it is an action based rulebook. If we want something different, we must write something like this: Grading is a number based rulebook. Grading 5: say "It's five. What can I say?" instead. Grading an odd number (called N): say "There's something odd about [N]." instead. Grading a number (called N): say "Just [N]." instead. When play begins: repeat with N running from 1 to 10: say "Grading [N]: "; follow the grading rulebook for N. which produces: Grading 1: There's something odd about 1. Grading 2: Just 2. Grading 3: There's something odd about 3. Grading 4: Just 4. Grading 5: It's five. What can I say? Grading 6: Just 6. Grading 7: There's something odd about 7. Grading 8: Just 8. Grading 9: There's something odd about 9. Grading 10: Just 10. Here we needed a variation on `follow` which supplies the value to apply to: > phrase: {ph_followfor} follow (values based rule producing values) for (value) > > This phrase causes the rule to be obeyed immediately (rather than simply at predetermined times such as when a particular action is being tried, or at the end of every turn, and such), and applies it to the value given, which must be of a matching kind. Example: > > follow the reaching inside rulebook for the electrified cage; And here is an example based on objects: The flotation rules are an object based rulebook. A flotation rule for the cork: rule succeeds. A flotation rule for an inflated thing: rule succeeds. A flotation rule: rule fails. And we might use the flotation rules in a circumstance like this: After inserting something into the well: follow the flotation rules for the noun; if the rule succeeded: say "[The noun] bobs on the surface."; otherwise: now the noun is nowhere; say "[The noun] sinks out of sight." ## Rulebook variables {PM_RulebookVariableAnd} {PM_RulebookVariableTooSpecific} {PM_RulebookVariableBadKind} {PM_RulebookVariableVague} ^^{rulebooks: variables for rulebooks} ^^{variables: for rulebooks} ^^{defining: rulebook variables} ^^{|called: in defining rulebook variables} ^^{rules: very first and very last} ^^{very first rules} ^^{very last rules} We have already seen that actions can have named values which stay with them while the action is being processed, but do not exist at other times: the variable called `actor`, for example. And activities have a similar ability. See [Action variables] and [Activity variables], respectively. In fact even single rulebooks can have variables of their own. When a rulebook is intended to perform some complicated task or calculation, such variables can be a convenient way for earlier rules to be able to leave information which will help later ones. For instance, suppose we want a rulebook which is intended to print out the player's current aptitude. We will suppose that this is a number from 0 upwards: the higher, the apter. The player gets bonus aptitude marks for achievements, but marks deducted for accidents, and so on. Moreover, we want to design this system so that it's easy to add further rules. The natural solution is to have a number which varies (or 'variable') acting as the running aptitude total: it should start at 0 and be altered up or down by subsequent rules. First, we should make the rulebook, and then add a variable: Aptitude is a rulebook. The aptitude rulebook has a number called the aptitude mark. The new value 'aptitude mark' is shared by the rules of the rulebook: nobody else can see it. It is created at the start of the rulebook being followed, and destroyed at the end. (If the rulebook should be followed a second time inside of itself, a new copy is created which does not disturb the old one.) So, in this case, 'aptitude mark' is started as 0 (since it is a number) each time the aptitude rules run. We can then write whatever rules we please to modify it: An aptitude rule: if in darkness: decrease the aptitude mark by 3. An aptitude rule: if we have taken the idol: increase the aptitude mark by 10. And we had better do something with the result: The last aptitude rule: say "Your aptitude rating is [aptitude mark]." A rulebook can have any number of variables like this. They behave much like `let` values except that they last for a whole rulebook, not an individual rule or To phrase definition. (Well, strictly speaking they are accessible not just to the rules which belong to the rulebook, but also to any rules which previously belonged to the rulebook but were kicked out by means of an explicit rule-listing sentence. This is good because otherwise they will suddenly cause problem messages when unlisted.) Some rulebooks need to set up initial values for their variables, and a special kind of rule is provided as a convenient way to do that. For example: The very first aptitude rule: now the aptitude mark is 100. This rule is only special in its placement — it is guaranteed to be the first rule in the rulebook, come what may — and is otherwise just like any other rule. Because it always goes first, no other rule can ever use the value of `aptitude mark` before it is set up to its initial value. There are a number of deliberate restrictions on `very first` rules: - A rulebook can only have one `very first` rule. - It has to be written in the same extension as the rulebook it belongs to, or else they both have to be in the main source text and not in an extension at all. - No other rule can be listed instead of a `very first` rule with a `listed instead of` sentence. - A `very first` rule cannot be unlisted from its rulebook with a `not listed` sentence. The point of this is that a `very first` rule belongs to the person who created the rulebook, and cannot be tampered with by users. Similarly, if less usefully, a rulebook can have a `very last` rule, which is subject to the same restrictions. ## Success and failure {PM_DefaultOutcomeTwice} {PM_BadDefaultOutcome} ^^{rules: success of rules} ^^{rules: failure of rules} ^^{rulebooks: outcomes} ^^{rulebooks: stopping execution} ^^{success: for rules} ^^{failure: for rules} ^^{|no outcome} ^^{+to+stop the action} ^^{+to+continue the action} ^^{(instead), to stop the action+sourcepart+} ^^{default outcome of a rulebook} Though we have blurred over this point so far, each rule must ordinarily end with one of three outcomes: success, failure and neither ("no outcome"). When a rulebook is followed, what happens is that each of its rules is followed in turn **until one of them ends in success or failure** – if ever: it is possible that each rule is tried and each ends with no outcome, so that the rulebook simply runs out of rules to try. For some rulebooks, these are not useful ideas: `every turn` rules, for instance, by default never produce an outcome, which is why the `every turn` rulebook normally runs through all its rules at the end of each turn. (Use of the phrases below can change that, so it's best not to use them in `every turn` rules.) But for other rulebooks, such as `check taking`, it's important that a rule which fails will stop the whole rulebook. For instance, we might find that the `can't take yourself rule` produces no outcome (because we aren't trying to do that), and then likewise the `can't take other people rule` (ditto) but that the `can't take component parts rule` prints up a complaint, and fails the action: the rulebook stops, and never goes on to (for instance) the `can't take scenery rule`. This is good, because an impossible action often fails for several reasons at once, and we only want to print up one objection, not a whole list. To follow the working of this mechanism, we need to be able to predict the outcome of any given rule. Sometimes this is easy to spot. For instance, in a rule which works on actions: - `continue the action` means *end this rule with no outcome* - `stop the action` means *end this rule in failure* - `[...] instead` **or** `instead [...]` means *end this rule in failure* ("Success" and "failure" are technical terms here: they do not mean that the player has or hasn't got what they wanted.) This is why the rule: Before taking something: say "The sentry won't let you!" instead. ends in failure, and therefore stops the `before` rulebook. Another easy-to-spot case is when a rule makes use of the explicit phrases: > phrase: {ph_succeeds} rule succeeds > > This causes the current rule to end immediately, with its outcome considered to be a success. The rulebook being worked through also ends, and is also a success. > phrase: {ph_fails} rule fails > > This causes the current rule to end immediately, with its outcome considered to be a failure. The rulebook being worked through also ends, and is also a failure. > phrase: {ph_nodecision} make no decision > > This causes the current rule to end immediately, but with no outcome. That means the rulebook being worked through will continue to run on, beginning with the next rule. But what happens if a rule simply doesn't say whether it succeeds, fails or has no outcome? In that case **it depends on the rulebook**. For almost all rulebooks, a rule which doesn't make a choice has no outcome, as in the following example: Before taking something: say "The sentry looks at you anxiously!" This rule, if it takes effect, ends with no outcome – so the action continues. But other rulebooks have a different convention: the most important is `instead`, where a rule making no explicit choice is deemed to end in failure. For instance: Instead of taking something: say "The sentry prods you with his rifle!" This rule, if it takes effect, ends in failure and therefore stops the action. We call this the **default outcome** of a rulebook. The default outcome of `before` (and of almost all rulebooks, in fact) is no outcome; the default outcome of `instead` is failure; the default outcome of `after` is success. The few exceptional cases with default outcome success or failure are marked as such in the Rules index. When we create a rulebook, it will default to "no outcome". But we can specify otherwise with sentences like so: The cosmic analysis rules are a rulebook. The cosmic analysis rules have default failure. Finally, note that the default outcome for a rulebook is really the default outcome for any rule in that rulebook: if no rules in the rulebook ever apply, for instance if there aren't any and the rulebook is empty, then the rulebook ends with no outcome at all. We can test the latest outcome like so: > phrase: {ph_succeeded} if rule succeeded: > > This condition is true if the most recently followed rule or rulebook ended in success, though it should be used only with care, in circumstamces when it's clear what the most recent rule is. This, for example, is safe enough: > > follow the hypothetical clever rule; > if rule succeeded: > ... > > But if some text had been produced between the `follow` and the text, and if that text had named an object, for example, then an activity would have been run to perform the naming, and that involves rules running. > > Note that this is not the opposite of `rule failed`, because there's a third possibility: that it ended with no outcome. > phrase: {ph_failed} if rule failed: > > This condition is true if the most recently followed rule or rulebook ended in failure, though it should be used only with care, in circumstamces when it's clear what the most recent rule is. This, for example, is safe enough: > > follow the hypothetical clever rule; > if rule failed: > ... > > But if some text had been produced between the `follow` and the text, and if that text had named an object, for example, then an activity would have been run to perform the naming, and that involves rules running. > > Note that this is not the opposite of `rule succeeded`, because there's a third possibility: that it ended with no outcome. ## Named outcomes {PM_MisplacedRulebookOutcome} {PM_WrongEndToPhrase} {PM_BadOutcomeClarification} {PM_DefaultNamedOutcomeTwice} {PM_DefaultOutcomeAlready} {PM_DuplicateOutcome} {PM_NonOutcomeProperty} ^^{rulebooks: outcomes} ^^{default outcome of a rulebook} ^^{|no outcome} We have seen that the terms "success" and "failure" can be misleading – after all, it might be a good thing for a particular rulebook to "fail". At any rate, these are vague terms, and we don't want to have to remember the conventions used by every rulebook. This is why certain rulebooks have explicitly named outcomes instead. For instance, the `visibility` rules are allowed to have the outcomes: - `there is sufficient light;` - `there is insufficient light;` These look like phrases, but are in fact named outcomes which can only be used in visibility rules. (They would make no sense elsewhere, and Inform will not allow their use if they are clearly out of context.) Such named outcomes are listed in the Rules index. There can be any number of named outcomes. For instance, the Standard Rules define: The does the player mean rules are a rulebook. The does the player mean rules have outcomes it is very likely, it is likely, it is possible, it is unlikely and it is very unlikely. which makes five possible outcomes. Five outcomes seems to contradict the principle that there are only three possible outcomes for a rule: in fact, though, the five are counted as five different forms of "success", and any of them will cause a `does the player mean` rule to succeed. If we do not want this, we can instead specify explicitly how the named outcomes correspond to success, failure or "no outcome": Visibility rules have outcomes there is sufficient light (failure) and there is insufficient light (success). Again, see the Rules index for examples. The same named outcome can be used for more than one rulebook, and can have different meanings in the context of different rulebooks – "good news" could be defined as success in one rulebook and failure in another, for instance. (This means that rulebook creators need not worry about name clashes and is an important difference in behaviour between rulebook outcomes and kinds of value.) We can even name a specific named outcome as the default outcome for rules in this rulebook: Audibility rules have outcomes high background noise (failure), low background noise (success - the default) and absolute silence (success). After a rulebook using named outcomes has run, we can test which outcome occurred by using the phrase: > phrase: {ph_rulebookoutcome} outcome of the rulebook ... rulebook outcome > > This phrase produces the (named) outcome of the phrase most recently followed. Example: > > follow the audibility rules; > if the outcome of the rulebook is the absolute silence outcome: > say "You could hear a pin drop in here." Each named outcome is a value if followed by the word `outcome`, which is how `absolute silence` has become `the absolute silence outcome`. Named outcomes can be said, so we could use the text substitution `"[outcome of the rulebook]"`, for instance. A final caveat: it is perfectly legal to create a named outcome which means "no outcome", but if so then this will never be `the outcome of the rulebook` because "no outcome" is not an outcome. ## Rulebooks producing values ^^{rulebooks: outcomes} ^^{values: produced by rulebooks} ^^{rules: success of rules} ^^{success: for rules} ^^{|no outcome} ^^^{+to+(name of kind) produced by (rule producing values) --> produced by}^^^{+to+(name of kind) produced by (values based rule producing values) for (value) --> produced by} We have now seen two ways to write the outcome of a rule: as simple success or failure, with more or less explicit phrases like: - `rule succeeds;` - `rule fails;` - `continue the action;` - `stop the action;` and by using a named outcome for the current rulebook as if it were a phrase, as in: low background noise; There is still a third way: we can stop a rule and at the same time produce a value. Producing a value allows much greater flexibility than producing a named outcome: a rulebook producing a number can end in a more or less infinite number of possible ways, after all. The two cannot be combined: if a rulebook is to produce a value, it cannot also have named outcomes. As we've seen, every rulebook has one kind of value as its basis, and it also has another kind of value for it to produce. If we call these `K` and `L`, then we have altogether four ways to write down the kind of a rulebook: - `rulebook` - `K based rulebook` - `rulebook producing L` - `K based rulebook producing L` If we don't mention `K`, Inform assumes the rulebook is action based. If we don't mention `L`, Inform assumes `L` is `nothing`, that is, Inform assumes no value is ever produced. Thus Drum summons rules is a rulebook. is equivalent to Drum summons rules is an action based rulebook producing nothing. But let's now look at a rulebook which does produce something. The cat behavior rules is a rulebook producing an object. This rulebook works out which thing the cat will destroy next. We might have rules like this one: Cat behavior when Austin can see the ball of wool: rule succeeds with result the ball of wool. The value is produced only when a rule succeeds, using this phrase: > phrase: {ph_succeedswith} rule succeeds with result (value) > > This phrase can only be used in a rule which produces a value, and the value given must be of the right kind. It causes the current rule to finish immediately, to succeed, and to produce the value given. How are we to use the cat behaviour rulebook? If we write: follow cat behavior then the rulebook runs just as any other rulebook would, but the value produced is lost at the end, which defeats the point. Instead, we might write: Every turn: let the destroyed object be the object produced by the cat behavior rules; if the destroyed object is not nothing: say "Austin pounces on [the destroyed object] in a flurry."; now the destroyed object is nowhere. The key phrase here is object produced by the cat behavior rules which accesses the value this rulebook produces. In general, we write: > phrase: {ph_producedby} (name of kind) produced by (rule producing values) ... value > > This phrase is used to follow the named rule, and to collect the resulting value. > phrase: {ph_producedbyfor} (name of kind) produced by (values based rule producing values) for (value) ... value > > This phrase is used to follow the named rule based on the value given, and to collect the resulting value. ## Abide by ^^{rules: invoking a rule: and abiding by its outcome} ^^{rulebooks: invoking a rulebook: and abiding by its outcome} ^^{reason the action failed (- rule)+glob+} It often happens that one rule needs to invoke another one. Most of the time, the best way to do this is with `follow`: follow the magical mystery tour rule; More often, though, we want not only to invoke another rule, but also to be guided by its advice. For this, we use the otherwise identical phrase: > phrase: {ph_abide} abide by (rule) > > This phrase applies the given rule, and makes its result the result of the present rule. If the rule being abided by succeeds or fails then the original rule also stops, at once and without going on to any further instructions. Example: > > The omnibus rule: > abide by the first rule; > abide by the second rule; > abide by the third rule; > abide by the fourth rule. > > This duplicates the effect of a rulebook of four rules: the `omnibus rule` tries each in turn, and stops as soon as any of them stop. > phrase: {ph_abidefor} abide by (values based rule producing values) for (value) > > This phrase applies the given rule to the given value, and makes its result the result of the present rule. If the rule being abided by succeeds or fails then the original rule also stops, at once and without going on to any further instructions. Abide might be used in examples like this one: A thing can be fragile or robust. This is the can't handle fragile things roughly rule: if the noun is fragile, say "[The noun] is too fragile for such rough handling." instead. A check dropping rule: abide by the can't handle fragile things roughly rule. A check throwing it at rule: abide by the can't handle fragile things roughly rule. Had we used `follow` instead of `abide by`, then in the event of the player typing ``DROP ANGEL`` the text ``The glass angel is too fragile for such rough handling`` would be printed, which is correct – but then the action would continue as though no difficulty had occurred, which is definitely not correct. Finally, we can `anonymously abide`: > phrase: {ph_abideanon} anonymously abide by (rule) & anonymously abide by (values based rule producing values) for (value) > > This phrase applies the given rule, and makes its result the result of the present rule. If the rule being abided by succeeds or fails then the original rule also stops, at once and without going on to any further instructions. However, the rule deemed to have decided the outcome is the one abided by, not the one doing the abiding. This is only useful in complicated situations where one rulebook uses another which... and so on. Its effect is exactly the same as `abide`, except that the rule deemed to have decided the outcome is the one abided by, not the one doing the abiding. It thus allows a rule or rulebook to act purely as a middle-man, never getting the blame or the credit for what happens. The rule which made the decision is often not very relevant anyway, but it's used as the source of the value `reason the action failed` (see the chapter on [Advanced Actions]). ## The internal rulebooks which keep stories running {rules_internal} ^^{actions: processing sequence} ^^{turns: turn sequence} ^^{action processing+rb+} ^^{turn sequence+rb+} ^^{when play begins+rb+} ^^{rules: run at beginning of story} ^^{when play ends+rb+} ^^{rules: run at end of story} Rulebooks handle almost all of the important tasks which keep a story going. We have seen them used in clarifying the player's command, supplying missing ingredients, processing the action to see what should happen, responding, and so on: by this point in the documentation, it must look as if Inform uses rulebooks for everything. And in fact this is more or less true. The life cycle of an Inform story as it plays looks like this: 1) The `startup rulebook` runs. 2) The `turn sequence rulebook` is run repeatedly until the story ends. 3) The `shutdown rulebook` runs. Looking inside any complicated machinery can make it harder rather than easier to understand what is basically going on, and some of the rules run in the above process are quite unimportant for writers to know about — the `recover Glk objects rule`, for example. A full accounting can be seen in the Index for a project, but the following summary covers the most useful points to know. To begin with, the `startup rulebook` runs the following rules in turn: - `virtual machine startup rule` - `when play begins stage rule` - `fix baseline scoring rule` - `display banner rule` - `initial room description rule` The first of these rules runs the `starting the virtual machine` activity, and this is a highly technical business best left alone by authors. But the other four are quite simple to follow. In fact, these are their definitions, taken verbatim from the Standard Rules: Startup rule (this is the when play begins stage rule): follow the when play begins rulebook. Startup rule (this is the fix baseline scoring rule): now the last notified score is the score. Startup rule (this is the display banner rule): say "[banner text]". Startup rule (this is the initial room description rule): try looking. The fact that the startup rulebook is arranged in this sequence is why `When play begins` rules happen before the banner and then the first room description in a typical story. If we rearranged these rules, as is in fact possible for authors to do, that would no longer be true. The `shutdown rulebook` is also fairly straightforward, consisting at time of writing of the following: - `when play ends stage rule` - `resurrect player if asked rule` - `print player's obituary rule` - `ask the final question rule` Note that the `resurrect player if asked rule` can cause the story to go back into the turn sequence again, which happens only if a `When play ends` rule has requested this to happen. The `print player's obituary rule` in fact just runs the `printing the player's obituary activity`. So let's forget about the start and end of the story, and look at the `turn sequence rulebook`, a very important rulebook which is run round and around to make turn-based play happen. At time of writing, this is what it contains: - `parse command rule` - `declare everything initially unmentioned rule` - `generate action rule` - `early scene changing stage rule` - `every turn stage rule` - `timed events rule` - `advance time rule` - `update chronological records rule` - `late scene changing stage rule` - `adjust light rule` - `note object acquisitions rule` - `notify score changes rule` These names are mostly fairly self-explanatory. The `parse command rule` is the one inviting the player to type a command — say, ``SWITCH KETTLE ON`` — and understanding it to be an action. But that action is not yet acted on. This is what happens in the `generate action rule`, which tries the action. Action trying can in fact happen many times during a single turn: one action can cause another to be tried, even midway, as when an action like `wearing the felt hat` causes `taking the felt hat` to be tried silently first. It is even possible for actions to be tried at other points in the turn sequence rules, if the author wants to. For example, writing this: Every turn: try taking inventory. would cause the action `taking inventory` during the `every turn stage rule`, which of course is the rule which runs the `every turn` rulebook. So there is no one place in the turn sequence when actions are processed. But there is just one method used to process them, and it's called the `action processing rulebook`. This is the second of the two important internal rulebooks to know about. At time of writing, it looks like this: - `announce items from multiple object lists rule` - `set pronouns from items from multiple object lists rule` - `before stage rule` - `basic visibility rule` - `basic accessibility rule` - `carrying requirements rule` - `instead stage rule` - `requested actions require persuasion rule` - `carry out requested actions rule` - `descend to specific action-processing rule` - `end action-processing in success rule ` There's quite a lot to see there. The two rules mentioning multiple objects are used when commands like ``TAKE ALL`` have been typed, so that the action being processed is only one of a chain of similar actions happening in succession. For example, in: > TAKE ALL Geiger counter: Taken. screwdriver: Taken. it is the `announce items from multiple object lists rule` which prints up those helpful ``Geiger counter:`` and ``screwdriver:`` labels; and the `set pronouns from items from multiple object lists rule` takes care of setting pronouns like ``IT`` and ``HER`` from items in that list. (Pronouns are set automatically in the command parser when a name is more explicit, as in ``TAKE SCREWDRIVER``.) The `before stage rule` is the one running the `before rulebook`, and similarly for the `instead stage rule`. In between is where restrictions such as accessibility are considered. For example, if an action is `applying to one touchable thing`, then it's the `basic accessibility rule` which enforces this. The `carrying requirements rule` is the one which rejects an action if the noun should be held by the actor but is not, and which also triggers a silent attempt to take the item in order to make things right. The `requested actions require persuasion rule` is where requests like ``JANELLE, SWITCH MACHINE OFF`` are vetted. If this rule were removed, all requests would always be obeyed, which isn't very realistic. Characters in a story have their own agendas. So by default this rule blocks the action, but it runs the `persuasion rulebook` to see if the author wants the action to take place instead. The `carry out requested actions rule` similarly applies only to requests. This converts a request action like `asking Janelle to try switching the machine off` into an actual action `switching the machine off`, but where Janelle is the actor, not the player. That action is then tried, which means that the action-processing rulebook is run again. The original request action then ends, its work done. So, when we reach the `descend to specific action-processing rule`, we know that we are no longer dealing with what might be a request to somebody else to do something: we know that the actor intends to perform the action. What this rule does, for implementation reasons not worth going into here, is to run a second, inner set of rules, the `specific action-processing rulebook`. This looks like so: - `work out details of specific action rule` - `investigate player's awareness before action rule` - `check stage rule` - `carry out stage rule` - `after stage rule` - `investigate player's awareness after action rule` - `report stage rule` - `default action success rule` The `work out details of specific action rule` is an implementation trick best ignored. The rest of these rules mostly work through the remaining four of the six normal stages of action processing (i.e., before, instead, check, carry out, after and report). The two rules mentioning the "player's awareness" are used to decide whether to tell the player what has happened. Clearly an action like `taking the Geiger counter` must be reported to the player. But `Edward Teller taking the Geiger counter` must not be if Teller is somewhere else in the story, out of sight. The `specific action-processing rulebook` monitors this using a rulebook variable called `within the player's sight` (a `truth state`, i.e., which is `true` or `false`). The rules for setting this are found in still another rulebook, the `player's action awareness rulebook`, which contains: - `player aware of his own actions rule` - `player aware of actions by visible actors rule` - `player aware of actions on visible nouns rule` - `player aware of actions on visible second nouns rule ` And, that's about the whole story. But a brief summary would come down to this: there are lots of internal rulebooks which keep Inform stories running, and the two which advanced users might want to meddle with are the `turn sequence rulebook` and the `action-processing rulebook`. Even then, modifying their operation is a last resort. The story can evidently fall to pieces if they cease to work normally. ## The Laws for Sorting Rulebooks ^^{rules: order in rulebooks} ^^{rulebooks: order of rules} ^^{precedence: of rules} ^^{disambiguation: of source text: precedence of rules} ^^{laws for sorting rulebooks} ^^{Rules page of Index panel+ui+} ^^{user interface: Index panel: Rules page} ^^{Index panel+ui+: Rules page} ^^{room gone from/to (- object)+actvar+} Large works created by Inform are heaped high with rules, most of them instead rules, but with a leavening of befores and afters as well. What will happen if these conflict with each other? For instance: Instead of opening a container, say "Your mother-in-law looks on with such evident disappointment that you withdraw your hand again." Instead of opening an open container, say "Your daughter tuts in theatrical exasperation at your, like, lameness." And the general answer is that a more specific rule takes precedence over a less specific one, so that your daughter gets in before your mother-in-law: `an open container` is more specific than `a container`. But "more specific" is a slippery term, so the description below lays out exactly what Inform does. ### First, last, and being listed first or last Before getting into the details, note that Inform provides two ways to jump or hang back in the queue: 1) A rule can be said to be `first` or `last`. For example, `A first instead rule for opening: ...` will take precedence over any `instead` rule not marked as `first`. It's important to note that multiple `first` and `last` rules can be written for the same rulebook, so this particular rule might not literally be first. And similarly for `last`, at the back end, of course. 2) Rulebooks can be rearranged using sentences like `X is listed last in R.`, or `X is listed after Y in R.` In general, those instructions take precedence even over rules having been declared as `first` or `last` as in (1) above. ### The sorting rules So we will now see what happens if the normal ordering is _not_ changed. As sketched above, sorting is done by comparing rules in pairs to decide which is more specific. We shall call these rules X and Y. The Laws are tried in sequence; the first Law to distinguish X and Y gets to decide which is more specific. If no Law is able to decide, X and Y go into the rulebook in order of their appearance in the source text – that is, whichever is defined first appears earlier in the rulebook and therefore takes priority. **Law I – Number of aspects constrained**. For action-based rulebooks, rules are scored from 0 to 6 according to whether they constrain any of: (i) the exotic `going` clauses (pushing, by and through), (ii) the location of the action (in, from and to), (iii) the things directly involved (actor, noun, second noun, `nowhere` in the case of `going`), (iv) the presence of others (in the presence of...), (v) the time at which the action occurs (when, or `for the nth time` or `for the nth turn`), and/or (vi) the scene the action occurs in (during). For value based rulebooks, rules are scored from 0 to 3 according to whether they constrain: (i) the value parameter, (ii) the scene in which the rulebook is followed (when, during), and/or (iii) any condition which must hold or activities going on at the same time (when/while). A higher score is more specific than a lower one. **Law II – When/while requirement**. A rule with a when/while restriction beats one without. **Law III – Action requirement**. A rule with a more specific action requirement beats one with a more general action requirement. (Or similarly, for value based rulebooks, a rule with a more specific parameter requirement beats a more general one.) Details are given below. **Law IV – Scene requirement**. A rule with a scene restriction (`during`) beats one without. Details of Law III now follow: **Law III.1 – Object To Which Rule Applies**. For value based rulebooks only: the more specific value requirement wins. **Law III.2.1 – Action/Where/Going In Exotic Ways**. A more specific combination of `...pushing...`, `... by ...`, and `... through ...` clauses in a `going` action beats a less specific. (Placing conditions on all three of these clauses beats placing conditions on any two, which beats any one, which beats none at all.) In cases where X and Y each place, let's say, two such conditions, they are considered in the order `...pushing...`, `...by...` and then `...through...` until one wins. (The idea here is that pushing something from room to room is rarer than travelling in a vehicle, which in turn is rarer than going through a door. The rarer action goes first, as more specific.) **Law III.2.2 – Action/Where/Room Where Action Takes Place**. A more specific combination of conditions on the room in which the action starts, and in which it ends, beats a less specific. For all actions other than `going`, there is no combination to be considered, and what we do is to look at the specificity of the `... in ...` clause. (So `Before looking in the Taj Mahal` beats `Before looking`.) For `going` actions, there are strictly speaking three possible room clauses: `... in ...`, `... from ...` and `... to ...`. However, `... in ...` and `... from ...` cannot both be present, so that in practice a `going` rule constraining two rooms beats a `going` rule constraining only one. If both the room gone from (the `...in...` or `...from...` room, whichever is given) and the room gone to (the `... to...` room) are constrained, then the constraints are looked at in the order from-room followed by to-room, since an action which goes to room Z could start in many different places and thus is likely to be more general. Giving a place as a specific room beats giving only the name of a region; if region R is entirely within region S, then a rule applying in R beats a rule applying in S. (Note that regions can only overlap if one is contained in the other, so this does not lead to ambiguity.) **Law III.2.3 – Action/Where/In The Presence Of**. A more specific `...in the presence of...` clause beats a less specific one. (This is again a constraint on where the action can take place, but it's now a potentially a constraint which could be passed in many different places at different times, so it's the most likely to be achieved and therefore the last to be considered of the Laws on Where.) **Law III.3.1 – Action/What/Second Thing Acted On**. A more specific constraint on the second noun beats a less specific. Thus `putting something in the wooden box` beats `putting something in a container`. **Law III.3.2 – Action/What/Thing Acted On**. A more specific constraint on the first noun beats a less specific. Thus `taking a container which is on a supporter` beats `taking a container`. In the case of `going` actions, the first noun is a direction. The special constraint `going nowhere` (which means: a direction in which the actor's location has no map connection) is considered more general than any other constraint placed on the first noun, but more specific than having no constraint at all. Thus `Instead of going north` beats `Instead of going nowhere` which beats `Instead of going`. **Law III.3.3 – Action/What/Actor Performing Action**. A more specific constraint on the actor beats a less specific. **Law III.4.1 – Action/How/What Happens**. A more specific set of actions beats a less specific. For instance, `taking` beats `taking or dropping` beats `doing something other than looking` beats `doing something`. A named action pattern (such as `behaving badly`) is more specific than `doing something`, but considered less specific than any explicitly spelled out list of actions. **Law III.5.1 – Action/When/Duration**. An action with a constraint on its history (`for the fifth time`, say, or `for the fifth turn`) beats one without. If both rules place constraints on history, then the one occurring on the smaller number of possible turns wins (thus `for the third to seventh time` – 5 possible turns of applicability – beats `for less than the tenth turn` – 9 possible turns). **Law III.5.2 – Action/When/Circumstances**. A more specific condition under `...when...` beats a less specific one. These conditions could potentially be complex: Inform judges how specific they are by counting the clauses found in them. The more clauses, the more specific the condition, it is assumed. **Law III.6.1 – Action/Name/Is This Named**. A rule with a name (`the apple blossom rule`, say) beats a rule without. # Advanced Text ## Hazards to be aware of ^^{text: memory limits} ^^{text: Z-machine limitations} ^^{limits: for manipulating text} ^^{memory limits: for manipulating text} ^^{Z-machine: memory limits} ^^{Z-machine: character set limits} ^^{Glulx: memory limits} ^^{virtual machine: memory limits} ^^{use options: catalogue: |dynamic memory allocation} ^^{dynamic memory allocation+useopt+} ^^{use options: catalogue: |maximum text length} ^^{maximum text length+useopt+} ^^{text <-- indexed text, now the same as text} ^^{text: indexed text, now the same as text} ^^{characters (letters): in text values} So far, we have dealt with text as something which comes in little packets: we have printed it out, read it in from the keyboard, and compared it with other text. But we have never tried to open the packets and get at the contents, letter by letter, or to make any alterations, or look for certain combinations of letters. Inform can do all of these things. For example, character number 1 in "Jackson Pollock" word number 2 in "Jackson Pollock" produce `"J"` and `"Pollock"` respectively. This all good fun, and enables some spectacular textual tricks. So what makes it "Advanced", that is, why is this chapter called "Advanced Text"? The answer is that there are some unexpected hazards in dealing with text. The rest of this section is a sort of health warning, like the tiny print about side-effects on medicine bottles. ### The "when was this?" problem Features like `character number ... in ...` are easy to understand with straightforward pieces of text, but what if there are text substitutions in square brackets? Matters then become trickier. character number 1 in "[time of day]" now depends on what the time is: at 11:30 PM, for example, it is `"1"`. That too seems fair enough, but we have to remember that once text has a substitution in, it is not so much a string of characters as it is a machine for generating a string of characters. The process of turning `"[time of day]"` into, say, `"11:30 PM"` is called _substitution_, and it can be tricky to work out when substitution takes place, and if so, whether it happens just once or many times. Consider: The long-case clock is in the Observatory. "The clock shows [time of day]." The value `initial appearance of the long-case clock` does not change in play. It always evaluates to `"The clock shows [time of day]."`, an _unsubstituted_ text. In general, texts substitute as late as they can, and often only just before they are printed out. If we: say the initial appearance of the long-case clock; then something like ``The clock shows 11:30 PM.`` will be printed, because substitution happens just as we print. Similarly, if we try to extract characters or words from this text, substitution will occur first. All of which is reasonable. But now suppose this: The long-case clock is in the Observatory. "The clock shows [time of day]." The remembered view is a text that varies. When play begins: now the remembered view is the initial appearance of the long-case clock. Every turn: say "You remember thinking: [remembered view][paragraph break]". An author might assume that on every turn, ``You remember thinking: The clock shows 9:00 am.`` is printed. After all, what we're printing back is the contents of `remembered view`, a variable which was set at 9 a.m. So why does it in fact print ``You remember thinking: The clock shows 9:01 am.``, and then ``... 9:02 am.``, and so on, on subsequent turns? It's because `remembered view` holds the _unsubstituted_ form of the text. Substitution did not happen until printing. Since it was printed out once at 9:00 AM, then at 9:01 AM, then at 9:02 AM, ..., it was substituted many times, always with the current time of day. As it happens, there are ways to deal with this issue. For example: When play begins: now the remembered view is the substituted form of the initial appearance of the long-case clock. which uses a built-in `substituted form of` phrase to force substitution to happen earlier. With that done, at 9:00 AM, `remembered view` gets set to `"The clock shows 9:00 AM."`, an unsubstituted text, and now it will always print back that way, even ten minutes later. As another example, consider this: Every turn: let T be "[a random number from 1 to 10 in words]"; say "T is [T], and number of characters in T is [number of characters in T]." On some turns, this might say something like ``T is six, and number of characters in T is 3.``, which seems fair enough. But on other turns, maybe it will say ``T is nine, and number of characters in T is 5.`` The cause again is that `T` is unsubstituted text, and that it was substituted twice here. The first time, it substituted to `"nine"`, but the second time to `"seven"`, which has 5 characters. And so the moral is: Inform sometimes substitutes texts for purposes other than printing — in order to extract data from them, perhaps. Having seen cases where it might be easy to think that a text is substituted when it isn't, here's now a case of the opposite issue. Suppose: The cuckoo clock is in the Observatory. "The cuckoo clock is disused." When play begins: let T be "The cuckoo sings [time of day]."; now the initial appearance of the cuckoo clock is T. This sets the initial appearance to `"The cuckoo sings [time of day]."` That text is unsubstituted. So the appearance of the cuckoo clock will change as the minutes pass by, as we intended. All well and good. But suppose we added a line to the rule: When play begins: let T be "The cuckoo sings [time of day]."; replace the text "sings" in T with "chirps"; now the initial appearance of the cuckoo clock is T. This sets the appearance to the unsubstituted text `"The cuckoo chirps 9:00 a.m."` What happens is that `T` is initially unsubstituted... but that it has to substituted permanently in order for the change to be made to its wording. It was then an unchanging text when it became the appearance of the cuckoo clock. In short, the health warning is this: the fluid nature of text with substitutions, and the question of when it is substituted, sometimes means that funny things appear to be happening. ### The "it depends on what the meaning of the word 'is' is" problem Relatedly, once we begin dealing with text as data, we will need to make comparisons. It's easy to see what `is` means for numbers: 101 is 101, and is not 37. And in general, `A is B` ought to mean that the values `A` and `B` are equal. Again, though, text substitutions make this more nuanced. For example, does this print ``Yes.``? To say the word marble: say "marble". When play begins: if "[the word marble]" is "marble", say "Yes." The answer is that it does. The left-hand text is substituted before the comparison is made, so that Inform ends up testing whether `"marble"` is `"marble"`, and it is. And similarly, the initial appearance of the long-case clock is "The clock shows 9:00 a.m." is `true` at the start if play (i.e., when it is indeed 9:00 a.m.). On the other hand, the adjective `empty` does not always do what authors expect. For example: To say a Trappist vow: do nothing. When play begins: if "[a Trappist vow]" is "", say "The vow has no characters."; if "[a Trappist vow]" is empty, say "The vow is empty."; The text `"[a Trappist vow]"` is considered not to be empty, even though _if it were substituted_ it would be. The adjective `empty` is tested on texts as they stand, without forcing them to be substituted first. ### The "sorcerer's apprentice" problem Goethe's poem _Der Zauberlehrling_ (1797) is not perhaps the chief cause of his fame, but it did lead indirectly to an Atari 2600 video game cartridge in 1983 ("it's not a total disaster" — _Video Games_ magazine). In any case, the myth was an ancient one. The sorcerer goes out, leaving his apprentice in charge. The apprentice naively enchants a broom to mop the floor for him, and it works, until he realises he doesn't know the magic to stop it. He tries splitting the broom in half, but each half carries on mopping, and now his problem has doubled. And so forth. This is one of those "don't mess with what you don't understand" fables that parents of all nations approve of. The magic for us here is the ability to generate text, in a way which may cause it to grow. For example: When play begins: let T be "This is a magic broom. "; repeat with N running from 1 to 10: now T is "[T][T]"; say T. This looks innocent enough and indeed it works, but `T` doubles in length ten times and ends up 23,552 characters long: that's 5120 words. If the 10 repetitions had been 20, the result would have been much, much worse. The moral here is that it's sometimes easy to type instructions in a casual way which generate a _lot_ of text. Is that such a problem? Well, yes and no. Memory in a computer is finite, and texts like `T` have to be stored in memory. This tends not to be a problem on the Glulx virtual machine, which is the default setting for Inform projects, but if we are trying to fit into the very small Z-machine instead, then computations like the one above may fail. Texts on that machine are limited to 1000 characters in length, though this truncation limit can be raised: Use maximum text length of at least 2000. Moreover, any amount of heavy computation in the Z-machine is difficult, and juggling texts, lists or other flexible sorts of data will soon exhaust the small run-time memory available. By default the Z-machine provides 8192 bytes of such memory, and although this can be raised: Use dynamic memory allocation of at least 16384. ...it cannot be raised very far, because there are only 65536 bytes of addressable memory to play with in the Z-machine, and even most of those are needed for other purposes. These two memory limits are moot for most projects, since most projects use Glulx, which can claim large amounts of memory without too much trouble. All the same, time is still a limited resource. It's slow to deal with large texts. As the sorcerer could have told us, had we been in a listening mood, the art of this sort of computation to have at least a rough idea in mind of how large the texts we are making might be, in the worst case. ### The "what do you mean, I can't have emoji?" problem We now live in a world where computers routinely handle a super-alphabet called Unicode which contains more or less every letter-form of every written culture, past or present. Once again, the default Glulx setting enables Inform to do the same, but projects using the Z-machine, which is a much more basic platform, are heavily constrained on which characters they can display or recognise when typed. Under the Z-machine, text may only contain characters from the so-called ZSCII character set — standard numbers, letters, punctuation marks and the commonest West European accented letters. ## Characters, words, punctuated words, unpunctuated words, lines, paragraphs ^^{text: counting characters / words / paragraphs / lines} ^^{characters (letters): counting} ^^{counting: characters / words / paragraphs / lines} ^^{punctuation: in counting words} ^^{line breaks: counting lines in text} ^^{paragraph breaks: counting paragraphs in text} ^^{empty / non-empty+adj+: for texts} ^^{non-empty / empty+adj+: for texts} ^^{text: empty / non-empty+adj+} Inform can get at the contents of text in a variety of ways. The lowest-level is by character – a character is a letter, digit, punctuation symbol, space or other letter-form. (We use the term `character` rather than `letter` because otherwise we would have to call `5` a letter, and so on.) Characters number upwards from 1: character number 1, to repeat that, starts the text. We can get the Nth character with: > phrase: {ph_charnum} character number (number) in (text) ... text > > This phrase produces the Nth character from the text, counting from 1. Characters include letters, digits, punctuation symbols, spaces or other letter-forms. Example: > > character number 8 in "numberless projects of social reform" > > produces `"e"`. If the index is less than 1 or more than the length of the text, the result is an empty text, `""`. The maximum character number varies with the current length of the text, and can be evaluated as: > phrase: {ph_numchars} number of characters in (text) ... number > > This phrase produces the number of characters from the text. Characters include letters, digits, punctuation symbols, spaces or other letter-forms. Examples: > > number of characters in "War and Peace" > number of characters in "" > > produce 13 and 0 respectively. We can also use the adjective `empty`: if the description of the location is empty, ... The empty text, `""`, is the only one with 0 characters. But note that `if T is empty` is never true for text with a substitution in it (see [Hazards to be aware of]), so it is not quite the same test as `if T is ""`. We can also extract the contents by word, again numbered from 1. Thus: > phrase: {ph_wordnum} word number (number) in (text) ... text > > This phrase produces the Nth word from the text, counting from 1. Words for this purpose are what's left after breaking the text up at punctuation or spacing (spaces, line breaks, paragraph breaks) and then removing that punctuation or spacing. Example: > > word number 3 in "ice-hot, don't you think?" > > produces `"don't"`. If the index is less than 1 or more than the number of words in the text, the result is an empty text, `""`. > phrase: {ph_numwords} number of words in (text) ... number > > This phrase produces the number of words from the text. Words for this purpose are what's left after breaking the text up at punctuation or spacing (spaces, line breaks, paragraph breaks) and then removing that punctuation or spacing. Example: > > number of words in "ice-hot, don't you think?" > > produces `5`. Note that the contraction apostrophe in `"don't"` doesn't count as punctuation. Because this is not always quite what we want, Inform offers two variations: > phrase: {ph_pwordnum} punctuated word number (number) in (text) ... text > > This phrase produces the Nth word from the text, counting from 1. Words for this purpose are what's left after breaking the text up at punctuation or spacing (spaces, line breaks, paragraph breaks) and then removing the spacing, but leaving the punctuation as independent words. Example: > > punctuated word number 2 in "ice-hot, don't you think?" > > produces `"-"`. The punctuated words here are `"ice"`, `"-"`, `"hot"`, `","`, `"don't"`, `"you"`, `"think"`, `"?"`. If two or more punctuation marks are adjacent, they are counted as different words, except for runs of dashes or periods: thus `",,"` has two punctuated words, but `"--"` and `"..."` have only one each. If the index is less than 1 or more than the number of punctuated words in the text, the result is an empty text, `""`. > phrase: {ph_numpwords} number of punctuated words in (text) ... number > > This phrase produces the number of words from the text. Words for this purpose are what's left after breaking the text up at punctuation or spacing (spaces, line breaks, paragraph breaks) and then removing the spacing, but leaving the punctuation as independent words. Example: > > number of punctuated words in "ice-hot, don't you think?" > > produces `8`; see if you can find them all. > phrase: {ph_upwordnum} unpunctuated word number (number) in (text) ... text > > This phrase produces the Nth word from the text, counting from 1. Words for this purpose are what's left after breaking the text up at spacing (spaces, line breaks, paragraph breaks) but including all punctuation as if it were part of the spelling of the words it joins to. Example: > > unpunctuated word number 1 in "ice-hot, don't you think?" > > produces `"ice-hot,"`. The unpunctuated words in `"ice-hot, don't you think?"` are `"ice-hot,"`, `"don't"`, `"you"`, `"think?"`. If the index is less than 1 or more than the number of punctuated words in the text, the result is an empty text, `""`. > phrase: {ph_numupwords} number of unpunctuated words in (text) ... number > > This phrase produces the number of words from the text. Words for this purpose are what's left after breaking the text up at spacing (spaces, line breaks, paragraph breaks) but including all punctuation as if it were part of the spelling of the words it joins to. Example: > > number of unpunctuated words in "ice-hot, don't you think?" > > produces just `4`. Finally, on the larger scale still, we also have: > phrase: {ph_linenum} line number (number) in (text) ... text > > This phrase produces the Nth line from the text, counting from 1. Unless explicit use is made of line-breaking, lines and paragraphs will be the same – it doesn't refer to lines as visible on screen, because we have no way of knowing what size screen the player might have. Note that white space is trimmed from both sides of what Inform considers a `line` here. > phrase: {ph_numlines} number of lines in (text) ... number > > This phrase produces the number of lines in the text. Unless explicit use is made of line-breaking, lines and paragraphs will be the same – it doesn't refer to lines as visible on screen, because we have no way of knowing what size screen the player might have. Example: the number of lines in > > "Sensational news just in![paragraph break]The Martians have invaded Miranda.[line break](One of the moons of Uranus, that is.)" > > is `3`. > phrase: {ph_paranum} paragraph number (number) in (text) ... text > > This phrase produces the Nth paragraph from the text, counting from 1. > phrase: {ph_numparas} number of paragraphs in (text) ... number > > This phrase produces the number of paragraphs in the text. Example: the number of paragraphs in > > "Sensational news just in![paragraph break]The Martians have invaded Miranda.[line break](One of the moons of Uranus, that is.)" > > is `2`. (Attempting to make large enough texts to have a serious paragraph count is slightly risky if there is not much memory to play with, as on the Z-machine. But the facilities do exist.) ## Upper and lower case letters ^^{text: upper case} ^^{text: lower case} ^^{text: changing case} ^^{case sensitivity: checking texts} ^^{text: Z-machine limitations} ^^{Z-machine: character set limits} ^^{Glulx: no character set limits} ^^{virtual machine: character set limits}^^^{+to+(text) in lower case --> in lower case}^^^{+to+(text) in sentence case --> in sentence case}^^^{+to+(text) in title case --> in title case}^^^{+to+(text) in upper case --> in upper case} ^^{lower case: (text) in lower case+phr+} ^^{sentence case: (text) in sentence case+phr+} ^^{title case: (text) in title case+phr+} ^^{upper case: (text) in upper case+phr+} In most European languages the same letters can appear in two forms: as capitals, like "X", mainly used to mark a name or the start of a sentence; or in their ordinary less prominent form, like "x". These forms are called upper and lower case because, historically, typesetters kept lead castings of letters in two wooden cases, one above the other on the workbench. Lower case letters were in the lower box closer to hand, being more often needed. Human languages are complicated. Not every lower case letter has an upper case partner: ordinal markers in Hispanic languages don't, for instance, and the German "ß" is never used in upper case. Sometimes two different lower case letters have the same upper case form: "ς" and "σ", two versions of the Greek sigma, both capitalise to "Σ". Inform follows the international Unicode standard in coping with all this. We can test whether text is in either case like so: > phrase: {ph_inlower} if (text) is in lower case: > > This condition is true if every character in the text is a lower case letter. Examples: this is true for `"wax"`, but false for `"wax seal"` or `"eZ mOnEy"`. > phrase: {ph_inupper} if (text) is in upper case: > > This condition is true if every character in the text is in upper case. Examples: this is true for `"beeswax"`, but false for `"room 101"`. We can change the casing of text using: > phrase: {ph_lowercase} (text) in lower case ... text > > This phrase produces a new version of the given text, but with all upper case letters reduced to lower case. Example: `"a ticket to Tromsø via Østfold"` becomes > > "a ticket to tromsø via østfold" > phrase: {ph_uppercase} (text) in upper case ... text > > This phrase produces a new version of the given text, but with all upper case letters reduced to lower case. Example: `"a ticket to Tromsø via Østfold"` becomes > > "A TICKET TO TROMSØ VIA ØSTFOLD" > phrase: {ph_titlecase} (text) in title case ... text > > This phrase produces a new version of the given text, but with casing of words changed to title casing: this capitalises the first letter of each word, and lowers the rest. Example: `"a ticket to Tromsø via Østfold"` becomes > > "A Ticket To Tromsø Via Østfold" > phrase: {ph_sentencecase} (text) in sentence case ... text > > This phrase produces a new version of the given text, but with casing of words changed to sentence casing: this capitalises the first letter of each sentence and reduces the rest to lower case. Example:` "a ticket to Tromsø via Østfold"` becomes > > "A ticket to tromsø via østfold" Accents are preserved in case changes. So (if we are using Glulx and have Unicode available) title case can turn Aristophanes' discomfortingly lower-case lines ``` ἐξ οὗ γὰρ ἡμᾶς προὔδοσαν μιλήσιοι, οὐκ εἶδον οὐδ᾽ ὄλισβον ὀκτωδάκτυλον, ὃς ἦν ἂν ἡμῖν σκυτίνη "πικουρία ``` by raising them proudly up like so: ``` Ἐξ Οὗ Γὰρ Ἡμᾶς Προὔδοσαν Μιλήσιοι, Οὐκ Εἶδον Οὐδ᾽ Ὄλισβον Ὀκτωδάκτυλον, Ὃς Ἦν Ἂν Ἡμῖν Σκυτίνη "Πικουρία. ``` Title and sentence casing can only be approximate if done by computer. Inform looks at the letters, but is blind to the words and sentences they make up. (Note the way sentence casing did not realise `"Tromsø"` and `"Østfold"` were proper nouns.) If asked to put the name `"mckay"` into title casing, Inform will opt for `"Mckay"`, not recognising this as the Scottish patronymic surname "McKay". Given `"baym dnieper"`, the title of David Bergelson's great Yiddish novel of 1932, it will opt for `"Baym Dnieper"`: but properly speaking Yiddish does not have upper case lettering at all, though nowadays it is sometimes printed as if it did. And conventions are very variable about which words should be capitalised in titles: English publishers mostly agree that connectives, articles and prepositions should be in lower case, but in France almost anything goes, with Académie Française rules giving way to avant-garde book design. In short, we cannot rely on Inform's title casing to produce a result which a human reader will always think perfect. This discussion has all been about how Inform prints, not about how it reads commands from the keyboard, because the latter is done case-insensitively. The virtual machines for which Inform creates programs normally flatten all command input to lower case, and in any case Understand comparison ignores casing. Thus Understand "mckay" as the Highland Piper. enables the player to type any of the possible casings of "McKay" equally. The text of the player's command probably doesn't preserve the original casing typed in any event. One more caution, though it will affect hardly anyone. For projects using the Z-machine, only a restricted character set is available in texts: for more, we must use Glulx. A mad anomaly of ZSCII, the Z-machine character set, is that it contains the lower case letter "ÿ" but not its upper case form "Ÿ", so that "ÿ" in upper case produces `"Ÿ"` in Glulx but `"ÿ"` in the Z-machine. This will come as a blow to Queensrÿche fans, but in all other respects any result on the Z-machine should agree with its counterpart on Glulx. ## Matching and exactly matching ^^{text: matching} ^^{comparisons: of text} ^^{case sensitivity: in matching texts} Up to now, we have only been able to judge two texts by seeing if they are equal, but we can now ask more subtle questions. > phrase: {ph_matches} if (text) matches the text (text): > > This condition is true if the second text occurs anywhere inside the first. Examples: > > if "[score]" matches the text "3", ... > > tests whether the digit 3 occurs anywhere in the score, as printed out; and > > if the printed name of the location matches the text "the", ... > > tests to see whether `"the"` can be found anywhere in the current room's name. Note that the location `"Smotheringly Hot Jungle"` would pass this test – it's there if you look. On the other hand, `"The Orangery"` would not, because `"The"` does not match against `"the"`. We can get around this in a variety of ways, one of which is to tell Inform to be insensitive to the case (upper or lower) of letters: > > if the printed name of the location matches the text "the", case insensitively: ... > > Every text matches the empty text, thus > > if t matches the text "", ... > > is always true. > phrase: {ph_exactlymatches} if (text) exactly matches the/-- text (text): > > This condition is true if the second text matches the first, starting at the beginning and finishing at the end. Both texts are read in substituted form. We can also find exactly *where* in the text the match occurred. > phrase: {ph_textfirstindex} first index of the/-- text match ... number > > Following a successful text match, this produces the character number of where the match began. > > if "vacation" matches the text "cat": > let x be the first index of the text match; > > assigns `3` to `x`. > > If you're interested in these results, get and store them immediately after the match: the values will > > be overwritten when the next match operation happens. > > Always test for success before using this phrase: the result is undefined if the match failed. > phrase: {ph_textlastindex} last index of the/-- text match ... number > > Similarly, we can find the character number of the *last* character in the match. > > last index of "cat" in "vacation" > > produces `5`. > > As noted above, always test for success before using this phrase, and store or act on the > > result immediately before another match overwrites it. > phrase: {ph_textlength} length of the/-- text match ... number > > Finally, we can get the length of the match, i.e., `3` for the `"cat"` example, again with > > the caveats above regarding testing for a successful match and using or storing the result > > promptly. Every text (including `""`) matches the text `""`. In this case, the first index, last index, and length are all 0. Matching against `""` is the *only* time any of these values will be 0 after a successful text match. We can also see how many times something matches: > phrase: {ph_nummatches} number of times (text) matches the text (text) ... number > > This produces the number of times the second text occurs within the first. The matches are not allowed to overlap. Example: > > number of times "pell-mell sally" matches the text "ll" = 3 > number of times "xyzzy" matches the text "Z" = 0 > number of times "xyzzy" matches the text "Z", case insensitively = 2 > number of times "aaaaaaaa" matches the text "aaaa" = 2 In the next section we shall see that `matches` and `exactly matches` can do much more than the simple text matching demonstrated above. ^^{XYZZY} There's no `number of times ... exactly matches the text ...` phrase since this is by definition going to have to be 0 or 1. ## Regular expression matching ^^{regular expressions} ^^{text: regular expressions} ^^{comparisons: with regular expressions} ^^{characters (letters): special meanings in regular expressions} ^^{case sensitivity: in regular expressions} When playing around with text, we tend to get into longer and trickier wrangles of matching – we find that we want to look not for simple text like `"gold"`, but for `"gold"` used only as a separate word, or for a date in YYYY-MM-DD format, or for a seemingly endless range of other possibilities. What we need is not just for Inform to provide a highly flexible matching program, but also a good notation in which to describe what we want. Fortunately, such a notation already exists. This is the "regular expression" notation, named for a 1950s mathematical model by the logician ^{@Stephen Kleene}, applied to computing in the late 60s by ^{@Ken Thompson}, borrowed almost at once by the early Unix tools of the 70s, and developed further by ^{@Henry Spencer} in the 80s and ^{@Philip Hazel} in the 90s. The glue holding the Internet together – the Apache web-server, the scripting languages Perl and Python, and so forth – makes indispensable use of regular expressions. As might be expected from the previous section, we simply have to describe the "find" text as `regular expression` rather than `text` and then the same facilities are available: > phrase: {ph_matchesre} if (text) matches the/-- regular expression (text): > > This condition is true if any contiguous part of the text can be matched against the given regular expression. Examples: > > if "taramasalata" matches the regular expression "a.\*l", ... > > is true, since this looks for a part of `"taramasalata"` which begins with `"a"`, continues with any number of characters, and finishes with `"l"`; so it matches `"aramasal"`. (Not `"asal"`, because it makes the leftmost match it can.) The option `case insensitively` causes lower and upper case letters to be treated as equivalent. > phrase: {ph_exactlymatchesre} if (text) exactly matches the/-- regular expression (text): > > This condition is true if the whole text (starting from the beginning and finishing at the end) can be matched against the given regular expression. The option `case insensitively` causes lower and upper case letters to be treated as equivalent. And once again: > phrase: {ph_nummatchesre} number of times (text) matches the/-- regular expression (text) ... number > > This produces the number of times that contiguous pieces of the text can be matched against the regular expression, without allowing them to overlap. Since a regular expression can match quite a variety of possibilities (for instance `"b\w+t"` could match `"boast"`, `"boat"`, `"bonnet"` and so on), it's sometimes useful to find what the match actually was: > phrase: {ph_matchtext} text matching regular expression ... text > > This phrase is only meaningful immediately after a successful match of a regular expression against text, and it produces the text which matched. Example: > > if "taramasalata" matches the regular expression "m.\*l": > say "[text matching regular expression]."; > > says ``masal.`` Perhaps fairly, perhaps not, regular expressions have a reputation for being inscrutable. The basic idea is that although alphanumeric characters (letters, numbers and spaces) mean just what they look like, punctuation characters are commands with sometimes dramatic effects. Thus: if WHATEVER matches the regular expression "fish", ... if WHATEVER matches the regular expression "f.*h", ... behave very differently. The first is just like matching the text `"fish"`, but the second matches on any sequence of characters starting with an "f" and ending with an "h". This is not at all obvious at first sight: reading regular expressions is a skill which must be learned, like reading a musical score. A really complex regular expression can look like a soup of punctuation and even an expert will blink for a few minutes before telling you what it does – but a beginner can pick up the basics very quickly. Newcomers might like to try out and become comfortable with the features a few at a time, reading down the following list. **1. Golden rule**. Don't try to remember all the characters with weird effects. Instead, if you actually mean any symbol other than a letter, digit or space to be taken literally, place a backslash `\` in front of it. For instance, matching the regular expression "*A* of the Galactic Patrol" is the same as matching the text `"*A* of the Galactic Patrol"`, because the asterisks are robbed of their normal powers. This includes backslash itself: `\` means a literal backslash. (Don't backslash letters or digits – that turns out to have a meaning all its own, but anyway, there is never any need.) **2. Alternatives**. The vertical stroke `|` – not a letter I or L, nor the digit 1 – divides alternatives. Thus "the fish|fowl|crawling thing" is the same as saying match `"the fish"`, or `"fowl"`, or `"crawling thing"`. **3. Dividing with brackets**. Round brackets `(` and `)` group parts of the expression together. "the (fish|fowl|crawling thing) in question" is the same as saying match `"the fish in question"`, or `"the fowl in question"`, or `"the crawling thing in question"`. Note that the `|` ranges outwards only as far as the group it is in. **4. Any character**. The period `.` means any single character. So "a...z" matches on any sequence of five characters so long as the first is "a" and the last is "z". **5. Character alternatives**. The angle brackets `<` and `>` are a more concise way of specifying alternatives for a single character. Thus "bb" matches on `"bab"`, `"beb"`, `"bib"`, `"bob"` or `"bub"`, but not `"baob"` or `"beeb"` – any single character within the angle brackets is accepted. Beginning the range with `^` means "any single character so long as it is not one of these": thus "b<^aeiou>b" matches on `"blb"` but not `"bab"`, `"beb"`, etc., nor on `"blob"` or `"bb"`. Because long runs like this can be a little tiresome, we are also allowed to use `-` to indicate whole ranges. Thus "bb" matches a "b", then any lower case English letter, then another "b". In traditional regular expression language, square brackets rather than angle brackets are used for character ranges. In fact Inform does understand this notation if there are actual square brackets `[` and `]` in the pattern text, but in practice this would be tiresome to achieve, since Inform uses those to achieve text substitutions. So Inform allows `"bb"` rather than making us type something like "b[bracket]a-z[close bracket]b" to create the text `"b[a-z]b"`. **6. Popular character ranges**. The range `<0-9>`, matching any decimal digit, is needed so often that it has an abbreviation: `\d`. Thus "\d\d\d\d-\d\d-\d\d" matches, say, `"2006-12-03"`. Similarly, `\s` means "any spacing character" – a space, tab or line break. `\p` is a punctuation character, in the same sense used for word division in the previous section: it actually matches any of . , ! ? - / " : ; ( ) [ ] { } `\w` means "any character appearing in a word", and Inform defines it as anything not matching `\s` or `\p`. `\l` and `\u` match lower and upper case letters, respectively. These are much stronger than `` and ``, since they use the complete definition in the Unicode 4.0.0 standard, so that letter-forms from all languages are catered for: for example `δ` matches `\l` and `Δ` matches `\u`. The reverse of these is achieved by capitalising the letter. So `\D` means "anything not a digit", `\P` means "anything not punctuation", `\W` means "anything not a word character", `\L` means "anything not a lower case letter" and so on. **7. Positional restrictions**. The notation `^` does not match anything, as such, but instead requires that we be positioned at the start of the text. Thus "^fish" matches only `"fish"` at the start of the text, not occurring anywhere later on. Similarly, `$` requires that the position be the end of the text. So "fish$" matches only if the last four characters are `"fish"`. Matching `"^fish$"` is the same thing as what Inform calls exactly matching `"fish"`. Another useful notation is `\b`, which matches a word boundary: that is, it matches no actual text, but requires the position to be a junction between a word character and a non-word character (a `\w` and a `\W`) or vice versa. Thus "\bfish\b" matches `"fish"` in `"some fish"` and also `"some fish, please!"`, but not in `"shellfish"`. (The regular expression `"\w\*fish\b"` catches all words ending in `"fish"`, as we will see below.) As usual, the capitalised version `\B` negates this, and means "not at a word boundary". **8. Line break and tab**. The notations `\n` and `\t` are used for a line break ("n" for "new line") and tab, respectively. Tabs normally do not occur in Inform strings, but can do when reading from files. It makes no sense to reverse these, so `\N` and `\T` produce errors. **9. Repetition**. Placing a number in braces `{` and `}` after something says that it should be repeated that many times. Thus "ax{25}" matches only on `"axxxxxxxxxxxxxxxxxxxxxxxxx"`. More usefully, perhaps, we can specify a range of the number of repetitions: "ax{2,6}" matches only on `"axx"`, `"axxx"`, `"axxxx"`, `"axxxxx"`, `"axxxxxx"`. And we can leave the top end open: `ax{2,}` means `a` followed by at least two `x`s. Note that the braces attach only to most recent thing – so `ax{2}` means `a` followed by two of `x` – but, as always, we can use grouping brackets to change that. So `(ax){2,}` matches `"axax"`, `"axaxax"`, `"axaxaxax"`,... (It's probably best not to use Inform to try to match the human genome against `"{3000000000}"`, but one of the most important practical uses of regular expression matching in science is in treating DNA as a string of nucleotides represented by the letters `a`, `c`, `g`, `t`, and looking for patterns.) **10. Popular repetitions.** Three cases are so often needed that they have standard short forms: `{0,1}`, which means 0 or 1 repetition of something – in other words, doesn't so much repeat it as make it optional – is written `?`. Thus `"ax?y"` matches only on `"ay"` or `"axy"`. `{0,}`, which means 0 or more repetitions – in other words, any number at all – is written `*`. Thus `"ax*y"` matches on `"ay"`, `"axy"`, `"axxy"`, `"axxxy"`, ... and the omnivorous `".*"` – which means "anything, any number of times" – matches absolutely every text. (Perhaps unexpectedly, replacing `".*"` in a text with `X` will produce `"XX"`, not `"X"`, because the `".*"` first matches the text, then matches the empty gap at the end. To match the entire text just once, try `"^.*$"`.) `{1,}`, which means 1 or more repetitions, is written `+`. So `\d+` matches any run of digits, for instance. **11. Greedy vs lazy.** Once we allow things to repeat an unknown number of times, we run into an ambiguity. Sure, `\d+` matches the text `"16339b"`. But does it look only as far as the `1`, then reason that it now has one or more digits in a row, and stop? Or does it run onward devouring digits until it can do so no longer, so matching the `"16339"` part? These two strategies are called "lazy" and "greedy" respectively. Do we care? Well, the strategy used makes no difference to whether there is a match, but it does affect what part of the text is matched, and the number of matches there are. Unless we mark for it, all repetitions are greedy. Usually this is good, but it means that, for instance, "-.+-" applied to `"-alpha- -beta- -gamma-"` will match the whole text, because `.+` picks up all of `"alpha- -beta- -gamma"`. To get around this, we can mark any of the repetition operators as lazy by adding a question mark `?`. Thus: "-.+?-" applied to `"-alpha- -beta- -gamma-"` matches three times, producing `"-alpha-"` then `"-beta-"` then `"-gamma-"`. A logical but sometimes confusing consequence is that a doubled question mark `??` means "repeat 0 or 1 times, but prefer 0 matches to 1 if both are possibilities": whereas a single question mark `?`, being greedy, means "repeat 0 or 1 times, but prefer 1 match to 0 if both are possibilities". **12. Numbered groups.** We have already seen that round brackets are useful to clump together parts of the regular expression – to choose within them, or repeat them. In fact, Inform numbers these from 1 upwards as they are used from left to right, and we can subsequently refer back to their contents with the notation `\1`, `\2`, ... After a successful match, we can find the results of these subexpressions with: > phrase: {ph_subexpressiontext} text matching subexpression (number) ... text > > This phrase is only meaningful immediately after a successful match of a regular expression against text, and it produces the text which matched. The number must be from 1 to 9, and must correspond to one of the bracketed groups in the expression just matched. Example: after > > if "taramasalata" matches the regular expression "a(r.\*l)a(.)": > > the `text matching regular expression` is `"aramasalat"`, the `text matching subexpression 1` is `"ramasal"`, and `text matching subexpression 2` is `"t"`. For instance: "(\w)\w*\1" matches any run of two or more word-characters, subject to the restriction that the last one has to be the same as the first – so it matches `"xerox"` but not `"alphabet"`. When Inform matches this against `"xerox"`, first it matches the initial `x` against the group `(\w)`. It then matches `\w*` ("any number of word-characters") against `ero`, so that the `*` runs up to 3 repetitions. It then matches "\1" against the final `x`, because `\1` requires it to match against whatever last matched in sub-expression 1 – which was an `x`. Similar to the situation with text matches, we can find the starting and ending character numbers of where a given subexpression occurred in the original text, as well as the length. > phrase: {ph_refirstindex} first index of subexpression (number) ... number > > Following a successful regular expression match, this produces the character number in the original text of the beginning of a given subexpression. > > if "ham sandwich" matches the regular expression "a(.+)\b(.+)": > let x be the start index of subexpression 2; > > would set x to 5. For the first index of the match as a whole, including what is outside any groups, use `subexpression 0`. For the example above, the start index of subexpression 0 would be 2. > > As with the text case, use or store the result promptly. And as before, results are undefined in case of failure, but with an important additional caveat: even when a match succeeds, results are not guaranteed to be meaningful *for a given subexpression* if the text that matched that subexpression was empty. For instance, adding `(.*)` to the end of a regular expression won't make any of the texts that currently match it fail to match, but the results for first index, last index, and length for the corresponding subexpression number might not be meaningful. > phrase: {ph_relastindex} last index of subexpression (number) ... number > > Similarly, we can find the character number of the last character in the subexpression. For the "ham sandwich" example above: > > last index of subexpression 1 > > would be 4 (`.+` matches `"ham"` *and* the following space). The same caveats noted above apply. > phrase: {ph_relength} length of subexpression (number) ... number > > Finally, we can get the length of the match, e.g., for the above, > > length of subexpression 2 > > would be 8 (for `"sandwich"`). Similar to the text case, any time the empty string `""` matches a regular expression, the values of all of first index, last index, and length for subexpression 0 would be 0. Numbered groups allow wicked tricks in matching, it's true, but really come into their own when it comes to replacing – as we shall see. **13. Switching case sensitivity on and off.** The special notations `(?i)` and `(?-i)` switch sensitivity to upper vs. lower case off and on, mid-expression. Thus `"a(?i)bcd(?-i)e"` matches `"abcde"`, `"aBcDe"`, etc., but not `"Abcde"` or `"abcdE"`. **14. Groups with special meanings.** This is the last of the special syntaxes: but it's a doozy. A round-bracketed group can be marked to behave in a special way by following the open bracket by a symbol with a special meaning. Groups like this have no number and are not counted as part of `\1`, `\2`, and so forth – they are intended not to gather up material but to have some effect of their own. * `"(# ...)"` is a comment, that is, causes the group to do nothing and match against anything. * `"(?= ...)"` is a lookahead: it is a form of positional requirement, like `\b` or `^`, but one which requires that the text ahead of us matches whatever is in the brackets. (It doesn't consume that text – only checks to see that it's there.) For instance `"\w+(?=;)"` matches a word followed by a semicolon, but does not match the semicolon itself. * `"(?! ...)"` is the same but negated: it requires that the text ahead of us does not match the material given. For instance, `"a+(?!z)"` matches any run of "a"s not followed by a "z". * `"(?<= ...)"` and `"(? ...)"` is a possessive, that is, causes the material to be matched and, once matched, never lets go. No matter what subsequently turns out to be convenient, it will never change its match. For instance, `\d+8` matches against `"768"` because Inform realises that `\d+` cannot be allowed to eat the `8` if there is to be a match, and stops it. But `(>\d+)8` does not match against `"768"` because now the `\d+`, which initially eats `"768"`, is possessive and refuses to give up the `8` once taken. * `"(?(1)...)"` and `"(?(1)...|...)"` are conditionals. These require us to match the material given if `\1` has successfully matched already; in the second version, the material after the `|` must be matched if `\1` has not successfully matched yet. And the same for 2, 3, ..., 9, of course. * Finally, conditionals can also use lookaheads or lookbehinds as their conditions. So for instance: "(?(?=\d)\d\d\d\d|AY-\d\d\d\d)" means if you start with a digit, match four digits; otherwise match `AY-` followed by four digits. There are easier ways to do this, of course, but the really juicy uses of conditionals are only borderline legible and make poor examples – perhaps this is telling us something. ## Making new text with text substitutions ^^{text substitutions: when text is substituted} ^^{text: when text substitutions are substituted} ^^{substituted / unsubstituted (text)+adj+} ^^{unsubstituted / substituted (text)+adj+} ^^{text: substituted / unsubstituted+adj+} ^^{temporary variables: displaying} ^^{variables: temporary: displaying} Substitutions are most often used just for printing, like so: say "The clock reads [time of day]."; But they can also produce text which can be stored up or used in other ways. For example, defining To decide what text is (T - text) doubled: decide on "[T][T]". makes let the Gerard Kenny reference be "NewYork" doubled; set this temporary variable to `"NewYorkNewYork"`. There is, however, a subtlety here. A text with a substitution in it, like: "The clock reads [time of day]." is always waiting to be substituted, that is, to become something like: "The clock reads 11:12 AM." If all we do with text is to print it, there's nothing to worry about. But if we're storing it up, especially for multiple turns, there are ambiguities. For example, suppose we're changing the look of the black status line bar at the top of the text window: now the left hand status line is "[time of day]"; Just copying `"[time of day]"` to the "left hand status line" variable doesn't make it substitute – which is just as well, or the top of the screen would perpetually show `"9:00 AM"`. On the other hand, looking back at the phrase example: To decide what text is (T - text) doubled: decide on "[T][T]". `"[T][T]"` is substituted as soon as it is formed. That's also a good thing, because `T` loses its meaning the moment the phrase finishes, which would make `"[T][T]"` meaningless anywhere else. What's going on here is this: Inform substitutes text immediately if it contains references to a temporary value such as `T`, and otherwise only if it needs to access the contents. This is why `"[time of day]"` isn't substituted until we need to print it out (or, say, access the third character): `time of day` is a value which always exists, not a temporary one. Another case where that might be important is if we want to set a text to an elaborated version of itself. For example, suppose there is a variable (not a temporary one) called `the accumulated tally`, and consider this: now the accumulated tally is "[the accumulated tally]X"; The intention of the writer here was to add an "X" each time this happens. But the result is a hang, because what it actually means is that accumulated tally can only be printed if the accumulated tally is printed first... an infinite regress. The safe way to do this would be: now the accumulated tally is the substituted form of "[the accumulated tally]X"; Using the adjectives `substituted` and `unsubstituted`, it's always possible to test whether a given text is in either state, should this ever be useful. For example, now the left hand status line is "[time of day]"; if the left hand status line is unsubstituted, say "Yes!"; will say ``Yes!``: the `left hand status line` is like a bomb waiting to go off. Speaking of which: The player is holding a temporal bomb. When play begins: now the left hand status line is "Clock reads: [time of day]". After dropping the temporal bomb: now the left hand status line is the substituted form of the left hand status line; say "Time itself is now broken. Well done." This is making use of: > phrase: {ph_subform} substituted form of (text) ... text > > This takes a text and makes substitution occur immediately. For example, > > substituted form of "time of death, [time of day]" > > produces something like `"time of death, 9:15 AM"` rather than `"time of death, [time of day]"`. It's entirely legal to apply this to text which never had any substitutions in, so > > substituted form of "balloon" > > produces `"balloon"`. Note that there's no analogous phrase for `unsubstituted form of...`, because once text has substituted, there's no way to go back. > phrase: {ph_issubstituting} if substituting text for comparison purposes: > > This condition is true if a text is being expanded into its substituted form only temporarily, not in order for it to be printed on screen, but in order to make a comparison between two text values. This can be useful to know in situations where story side-effects are triggered by printing: we wouldn't want that trigger to be pulled just for an internal text comparison. For example, a rule called the `make named things mentioned rule` in the Standard Rules uses this phrase to prevent the `mentioned` property being given to any objects whose names are printed during such a comparison, since they have not been printed where a player would see them. ## Replacements ^^{text: replacing parts of a text} ^^{punctuation: in counting words} ^^{characters (letters): replacing in text} ^^{regular expressions} ^^{text: regular expressions} Suppose V is a text which varies – perhaps a property of something, or a variable defined everywhere, or a temporary `let`-named value. How do we change its contents? The easiest way is simply to assign text to it. Thus: let V be "It is now [the time of the day in words]." And, for instance, let V be "[V]!" adds an exclamation mark at the end of `V`. Otherwise, it is more useful (also a little faster) to modify `V` by changing its characters, words and so on. Thus: > phrase: {ph_replacechar} replace character number (number) in (text) with (text) > > This phrase acts on the named text by placing the given text in place of the Nth character, counting from 1. Example: > > let V be "mope"; > replace character number 3 in V with "lecul"; > say V; > > says ``molecule``. > phrase: {ph_replaceword} replace word number (number) in (text) with (text) > > This phrase acts on the named text by placing the given text in place of the Nth word, counting from 1, and dividing words at spacing or punctuation. Example: > > let V be "Does the well run dry?"; > replace word number 3 in V with "jogger"; > say V; > > says ``Does the jogger run dry?``. > phrase: {ph_replacepword} replace punctuated word number (number) in (text) with (text) > > This phrase acts on the named text by placing the given text in place of the Nth word, counting from 1, and dividing words at spacing, counting punctuation runs as words in their own right. Example: > > let V be "Frankly, yes, I agree."; > replace punctuated word number 2 in V with ":"; > say V; > > says ``Frankly: yes, I agree.``. > phrase: {ph_replaceupword} replace unpunctuated word number (number) in (text) with (text) > > This phrase acts on the named text by placing the given text in place of the Nth word, counting from 1, and dividing words at spacing, counting punctuation as part of a word just as if it were lettering. Example: > > let V be "Frankly, yes, I agree."; > replace unpunctuated word number 2 in V with "of course"; > say V; > > says ``Frankly, of course I agree.``. > phrase: {ph_replaceline} replace line number (number) in (text) with (text) > > This phrase acts on the named text by placing the given text in place of the Nth line, counting from 1. Lines are divided by paragraph or line breaks. > phrase: {ph_replacepara} replace paragraph number (number) in (text) with (text) > > This phrase acts on the named text by placing the given text in place of the Nth paragraph, counting from 1. Last, but not least, we can replace text wherever it occurs: > phrase: {ph_replace} replace the text (text) in (text) with (text) > > This phrase acts on the named text by searching and replacing, as many non-overlapping times as possible. Example: > > replace the text "a" in V with "z" > > changes every lower-case "a" to "z": the same thing done with the `case insensitively` option would change each "a" or "A" to "z". All very well for letters, but it can be unfortunate to try replace the text "Bob" in V with "Robert" if V happens to contain, say `"The Olympic Bobsleigh Team"`: it would become `"The Olympic Robertsleigh Team"`. What we want, of course, is for Bob to become Robert only when it's a whole word. We can get that with: > phrase: {ph_replacewordin} replace the word (text) in (text) with (text) > > This phrase acts on the named text by searching and replacing, as many non-overlapping times as possible, where the search text must occur as a whole word. Example: > > replace the word "Bob" in V with "Robert" > > changes `"Bob got on the Bobsleigh"` to `"Robert got on the Bobsleigh"`. > phrase: {ph_replacepwordin} replace the punctuated word (text) in (text) with (text) > > This phrase acts on the named text by searching and replacing, as many non-overlapping times as possible, where the search text must occur as a whole word or run of punctuation. But these are all just special cases of the grand-daddy of all replacement phrases: > phrase: {ph_replacere} replace the regular expression (text) in (text) with (text) > > This phrase acts on the named text by matching the regular expression and replacing anything which fits it, as many non-overlapping times as possible. Example: > > replace the regular expression "\d+" in V with "..." > > changes `"The Battle of Waterloo, 1815, rivalled Trafalgar, 1805"` to `"The Battle of Waterloo, ..., rivalled Trafalgar, ..."`. The `case insensitively` causes lower and upper case letters to be treated as if the same letter. > > When replacing a regular expression, the replacement text also has a few special meanings (though, thankfully, many fewer than for the expression itself). Once again `\n` and `\t` can be used for line break and tab characters, and `\\` must be used for an actual backslash. But, very usefully, `\1` to `\9` expand as the contents of groups numbered 1 to 9, and `\0` to the exact text matched. So: > > replace the regular expression "\d+" in V with "roughly \0" > > adds the word ``roughly`` in front of any run of digits in V, because `\0` becomes in turn whichever run of digits matched. And > > replace the regular expression "(\w+) (.\*)" in V with "\2, \1" > > performs the transformation `"Frank Booth"` to `"Booth, Frank"`. > > Finally, prefixing the number by "l" or "u" forces the text it represents into lower or upper case, respectively. For instance: > > replace the regular expression "\b(\w)(\w\*)" in X with "\u1\l2"; > > changes the casing of X to "title casing", where each individual word is capitalised. (This is a little slow on large texts, since so many matches and replacements are made: it's more efficient to use the official phrases for changing case.) ## Summary of regular expression notation ^^{regular expressions} ^^{text: regular expressions} ^^{characters (letters): special meanings in regular expressions} ^^{regular expressions: syntax reference} | Notation | Matches... | |------ | --- | | | **Positional restrictions** | | `^` | Matches (accepting no text) only at the start of the text| | `$` | Matches (accepting no text) only at the end of the text| | `\\b` | Word boundary: matches at either end of text or between a `\\w` and a `\\W` | | `\\B` | Matches anywhere where `\\b` does not match| | | **Backslashed character classes** | | `\\`_char_ | If _char_ is other than `a`-`z`, `A`-`Z`, `0`-`9` or space, matches that literal character | | `\\n` | Matches literal line break character| | `\\t` | Matches literal tab character (but use this only with external files)| | `\\d` | Matches any single digit| | `\\l` | Matches any lower case letter (by Unicode 4.0.0 definition)| | `\\p` | Matches any single punctuation mark: `. , ! ? - / " : ; ( ) [ ] { }`| | `\\s` | Matches any single spacing character (space, line break, tab)| | `\\u` | Matches any upper case letter (by Unicode 4.0.0 definition)| | `\\w` | Matches any single word character (neither `\\p` nor `\\s`)| | `\\D` | Matches any single non-digit| | `\\L` | Matches any non-lower-case-letter| | `\\P` | Matches any single non-punctuation-mark| | `\\S` | Matches any single non-spacing-character| | `\\U` | Matches any non-upper-case-letter| | `\\W` | Matches any single non-word-character (i.e., matches either `\\p` or `\\s`)| | | **Other character classes** | | `.` | Matches any single character| | `<...>` | Character range: matches any single character inside| | `<^...>` | Negated character range: matches any single character not inside| | | **Inside a character range** | | `e-h` | Any character in the run `e` to `h` inclusive (and so on for other runs)| | `>` | Starting with `>` means that a literal close angle bracket is included| | `\\` | Backslash has the same meaning as for backslashed character classes: see above| | | **Structural** | | `\|` | Divides alternatives: `fish\|fowl` matches either | | `(?i)` | Always matches: switches to case-insensitive matching from here on| | `(?-i)` | Always matches: switches to case-sensitive matching from here on | | | **Repetitions** | | `...?` | Matches "..." either 0 or 1 times, i.e., makes "..." optional| | `...*` | Matches "..." 0 or more times: e.g. `\s*` matches an optional run of space| | `...+` | Matches "..." 1 or more times: e.g. `x+` matches any run of `x`s| | `...{6}` | Matches "..." exactly 6 times (similarly for other numbers, of course)| | `...{2,5}` | Matches "..." between 2 and 5 times| | `...{3,}` | Matches "..." 3 or more times| | `....?` | `?` after any repetition makes it "lazy", matching as few repeats as it can| | | **Numbered subexpressions** | | `(...)` | Groups part of the expression together: matches if the interior matches| | `\\1` | Matches the contents of the 1st subexpression reading left to right| | `\\2` | Matches the contents of the 2nd, and so on up to `\\9` (but no further)| | | **Unnumbered subexpressions** | | `(# ...)` | Comment: always matches, and the contents are ignored| | `(?= ...)` | Lookahead: matches if the text ahead matches "...", but doesn't consume it| | `(?! ...)` | Negated lookahead: matches if lookahead fails| | `(?<= ...)` | Lookbehind: matches if the text behind matches "...", but doesn't consume it| | `(? ...)` | Possessive: tries to match "..." and if it succeeds, never backtracks on this| | `(?(1)...)` | Conditional: if `\\1` has matched by now, require that "..." be matched| | `(?(1)...\|...)` | Conditional: ditto, but if `\\1` has not matched, require the second part| | `(?(?=...)...\|...)` | Conditional with lookahead as its condition for which to match| | `(?(?<=...)...\|...)` | Conditional with lookbehind as its condition for which to match| | | **In replacement text** | | `\\char` | If char is other than `a`-`z`, `A`-`Z`, `0`-`9` or space, expands to that literal char| | `\\n` | Expands to a line break character| | `\\t` | Expands to a tab character (but use this only with external files)| | `\\0` | Expands to the full text matched| | `\\1` | Expands to whatever the 1st bracketed subexpression matched| | `\\2` | Expands to whatever the 2nd matched, and so on up to `\\9` (but no further)| | `\\l0` | Expands to \0 converted to lower case (and so on for `\\l1` to `\\l9`)| | `\\u0` | Expands to \0 converted to upper case (and so on for `\\u1` to `\\u9`)| # Lists ## Lists and entries {kind_listof} ^^{lists} ^^{kinds: of list} ^^{empty / non-empty+adj+: for lists} ^^{non-empty / empty+adj+: for lists} ^^{lists: empty / non-empty+adj+} ^^{lists: finding length} ^^{+to+number of entries in/of (list of values)} ^^{lists: adding entries} ^^{+to+add (value) to (list of values)} ^^{type-checking: in lists} Many sections in this book begin by introducing a new kind of value. Reading through in order, the possibilities mount up: numbers, times, texts, and so on. (See the Kinds page of the Index for a convenient list of the options.) This section is a little different: rather than showing a single new kind of value, it shows how to make a new kind out of any existing one. If K is any kind of value, then `list of K` is also a kind of value. For instance, we could write: let L be a list of numbers; and this would create a new `let` variable, called `L`, whose kind of value is `list of numbers`. On the other hand, we are not allowed to write: let L be a list; because `list` by itself is not a kind of value. (Inform always needs to know what kinds the values entered in a list are going to have.) Lists are like flexible-length table columns, but that probably makes them sound more mysterious than they really are. A list is simply a sequence of values, called its "entries", numbered from 1 upwards. The number of entries is called its "length". If we try let L be a list of numbers; say "L has [the number of entries in L] entries."; then we find ``L has 0 entries.`` This is because all lists start out empty when created: that is, they initially have 0 entries. Inform has two built-in adjectives `empty` and `non-empty` which can apply to lists, and they mean just what they ought to mean: a list is empty if its length is 0, and otherwise non-empty. We can add entries very easily: add 2 to L; add 3 to L; add 5 to L; We can now, for instance, try saying the list: say "L is now [L]."; with the result ``L is now 2, 3 and 5.`` Note that only numbers can be added to `L`: if we try add "clock" to L; Inform will produce a problem message, because `L` has kind `list of numbers`, whereas `"clock"` is text. In this way, Inform ensures that a list always contains values of the same kind throughout. So it's not possible to construct a list whose entries are `2`, `"fish"`, `4` and `Entire Game`. Such a list would be very hazardous to deal with, in any case. If what we need is a combination of different kinds of values, tables are a better option. Finally, note that since `list of numbers` is a kind of value in its own right, so is `list of lists of numbers`, and so on – though such lists are trickier to deal with, they are sometimes handy. ## Constant lists {PM_CantLetEmptyList} {PM_BadConstantListEntry} {PM_NonconstantConstantListEntry} {PM_IncompatibleConstantListEntry} ^^{lists: creating} ^^{defining: lists} ^^{lists: constant lists} ^^{empty / non-empty+adj+: for lists} ^^{non-empty / empty+adj+: for lists} ^^{lists: empty / non-empty+adj+} ^^{kinds: of list}^^^{punctuation: curly braces <-- braces <-- curly braces } ^^{punctuation: curly braces: for constant lists} ^^{|{ \}: for constant lists} ^^{punctuation: comma: in list constants, requiring spaces} ^^{spaces, in list constants, after commas} ^^{|,: in list constants, requiring spaces} It is convenient to have a concise way to write down a constant list. Just as we could write `231`, say, or `7:01 AM` to refer to particular number and time constants, so we can write list constants: let L be {1, 2, 3, 4}; Inform recognises that `{1, 2, 3, 4}` is a list because of the braces, and looks at the entries inside, sees that they are numbers, and deduces that it is a constant whose kind of value is `list of numbers`. `L` is then a temporary list variable and we can add to it, remove things, and so on as we please – `{1, 2, 3, 4}` is merely its initial value. When constructing lists, it is worth noting that Inform requires spaces after the commas (which seems a little harsh, but is necessary because otherwise many sensible literal specifications for units would be impossible – anyway, the reason isn't important here). So let L be {1,2,3,4}; would produce problem messages. But Inform does not require spaces round its braces. We call this way of writing a list "brace notation". In mathematics, braces are usually used for sets, and properly speaking these are sequences not sets – so that `{1, 2, 3, 4}` is different from `{4, 3, 2, 1}` – but it is still a familiar notation. Similarly, let L be {"apple", "pear", "loganberry"}; makes `L` a list of texts; and The marshmallow, the firework and the stink bomb are in the Scout Hut. The list of prohibited items is a list of objects that varies. The list of prohibited items is {the firework, the stink bomb}. makes a global variable (`list of prohibited items`) with kind of value `list of objects`, and whose initial value is to contain two things: the firework and the stink bomb. More exotically, if we need to make lists of lists: let L be {{1, 2}, {6, 7, 8}}; gives `L` the kind of value `list of lists of numbers`, with (initially) two entries: the list `{1, 2}` (a `list of numbers`), then the list `{6, 7, 8}` (ditto). Constant lists are convenient, too, when a column in a table needs to contain lists: The duck, the orange, the cider, the cinnamon and the orange are in the Kitchen. Table of Requirements recipe ingredients "duck à l'orange" {the duck, the orange} "spiced cider" {the cider, the cinnamon, the orange} A special word about the constant list `{ }`. This means the list with no entries – the empty list. If we try to create a new `let` variable `M` with let M be { }; then Inform will produce a problem message, because it cannot tell what sort of list `M` will be: a list of numbers, or texts, or times, or...? On the other hand, writing now M is { }; is fine if `M` already exists, and then does the obvious thing – empties `M`. Similarly, a table column in which every entry is `{ }` produces a problem message unless the heading for that column spells out the kind of value stored within it: for instance, `ingredients (list of texts)`. All of this is a notation for constant lists only, not some sort of gluing-things-together operation. So this, for instance: let L be {100, the turn count}; is not allowed, even though `the turn count` is a number: because it is a number that varies, the braces do not contain constants, and therefore this is not a list constant. ## Saying lists of values ^^{text substitutions: lists} ^^{lists: displaying} ^^{use options: catalogue: |the serial comma} ^^{serial comma+useopt+} ^^{definite articles: when displaying lists} ^^{indefinite articles: when displaying lists} ^^{brace notation: "[(list of values) in brace notation]"+sayphr+} Any list L can be said, provided that its contents can be said. For example: let L1 be {2, 3, 5, 7, 11}; say L1; produces the text ``2, 3, 5, 7 and 11`` – unless we have `Use serial comma.` set, in which case a comma appears after the 7. We also have the option of using the more formal notation: > phrase: {phs_listbraced} say "[(list of values) in brace notation]" > > This text substitution produces the list in the form of `{`, then a comma-separated list, and then `}`, which looks less like an English sentence but more mathematical. Example: > > "[list of people in brace notation]" > > might produce ``{ yourself, Mr Darcy, Flashman }``. If we say a list of lists, then the individual entry lists are always printed in brace notation: the ordinary sentence way would be incomprehensible. Of course, the values in `L1` are written out in number form because `L1` is a list of numbers: we could alternatively try let L2 be {the piano, the music stand}; say L2; which produces ``piano and music stand``. Lists of objects can be said in two additional ways: > phrase: {phs_listdef} say "[(list of objects) with definite articles]" > > This text substitution writes out the list in sentence form, adding the appropriate definite articles. Example: > > let L be {the piano, the music stand}; > say "[L with definite articles]"; > > says ``the piano and the music stand``. > phrase: {phs_listindef} say "[(list of objects) with indefinite articles]" > > This text substitution writes out the list in sentence form, adding the appropriate indefinite articles. Example: > > let L be {the piano, the music stand}; > say "[L with definite articles]"; > > says ``a piano and a music stand``. ## Testing and iterating over lists ^^{lists: finding entries} ^^{lists: repeating through} ^^{limits: on changing lists being repeated through} If `L` is a list, we can interrogate it to see whether it does or does not contain (at least one instance of) any compatible value `V`: > phrase: {ph_islistedin} if (value) is listed in (list of values): > > This condition is true if the given value, which must be of a compatible kind, is one of those in the list. For instance, if L is our list of the numbers 2, 3, 5, 7 and 11 then 5 is listed in it but 6 is not. > phrase: {ph_isnotlistedin} if (value) is not listed in (list of values): > > This condition is true if the given value, which must be of a compatible kind, is not one of those in the list. We can also repeat running through a list (just as we can with table rows). Thus: > phrase: {ph_repeatlist} repeat with (a name not so far used) running through (list of values): > > This phrase causes the block of phrases following it to be repeated once for each item in the given list, storing that value in the named variable. (The variable exists only temporarily, within the repetition.) Example: > > let L be {2, 3, 5, 7, 11, 13, 17, 19}; > repeat with prime running through L: > ... > > If the list is empty, nothing happens: the `...` phrase(s) are never tried. In the next sections, we shall see that it is possible to change, reorder and resize lists. But it's important never to change a list that's being repeated through. The following: let L1 be {1, 2, 3, 4}; repeat with n running through L1: remove n from L1; leaves `L1` containing `{2, 4}`, since the removals from the list cause it to shuffle back even while we repeat through it – a bad, bad idea. ## Building lists ^^{lists: adding entries} ^^{lists: removing entries} We have already seen `add... to...`. This in fact comes in two forms: > phrase: {ph_addtolist} add (value) to (list of values) > > This phrase adds the given value to the end of the list. Example: > > let L be {60, 168}; > add 360 to L; > > results in `L` being `{60, 168, 360}`. Note that the value is added even if it already occurs somewhere in `L`; this can be avoided with `if absent`. So: > > add 168 to L, if absent; > > would do nothing – it is already there. > phrase: {ph_addlisttolist} add (list of values) to (list of values) > > This phrase adds the first list to the end of the second. Example: > > let L be {2, 3, 5, 7}; > add {11, 13, 17, 19} to L; > > results in `L` being `{2, 3, 5, 7, 11, 13, 17, 19}`. If we don't want to add new entries at the end, we can instead say where they should go: > phrase: {ph_addatentry} add (value) at entry (number) in/from (list of values) > > This phrase adds the given value so that it becomes the entry with that index number in the list. Example: > > let L be {1, 2, 3, 4, 8, 24}; > add 12 at entry 6 in L; > > sets `L` to `{1, 2, 3, 4, 8, 12, 24}`. If there are N entries in `L`, then we can add at any of entries 1 up to N+1: adding at entry N+1 means adding at the end. The phrase option `if absent` makes the phrase do nothing if the value already exists anywhere in `L`. > phrase: {ph_addlistatentry} add (list of values) at entry (number) in/from (list of values) > > This phrase adds the first list to the second so that it begins at the given position. Example: > > let L be {1, 2, 3, 4}; > add {4, 8, 12} at entry 3 in L; > > results in L being {1, 2, 4, 8, 12, 3, 4}. A list is allowed to contain duplicates, and the order matters. For instance: let L be {2, 2, 3}; makes `L` into what a human would read as "2, 2 and 3". This is a different list to the one made by: let M be {2, 3, 2}; even though `L` and `M` have the same values, repeated the same number of times – for two lists to be equal, they must have the same kind of entry, the same number of entries, and the same entries in each position. We can also strike out values: > phrase: {ph_remfromlist} remove (value) in/from (list of values) > > This phrase removes every instance of the given value from the list. Example: > > let L be {3, 1, 4, 1, 5, 9, 2, 6, 5, 3}; > remove 1 from L; > > results in `L` being `{3, 4, 5, 9, 2, 6, 5, 3}`. Ordinarily `remove 7 from L` would produce a run-time problem, since `L` does not contain the value 7, but using the `if present` option lets us off this: the phrase then does nothing if `L` does not contain the value to be removed. > phrase: {ph_remlistfromlist} remove (list of values) in/from (list of values) > > This phrase removes every instance of any value in the first list from the second. Example: > > let L be {3, 1, 4, 1, 5, 9, 2, 6, 5, 3}; > remove {0, 2, 4, 6, 8} from L; > > results in `L` being `{3, 1, 1, 5, 9, 5, 3}`. If both lists are large, this can be a slow process, and we might do better by sorting them and trying a more sophisticated method. But this is convenient for anything reasonable-sized. Again, we can also remove from specific positions: > phrase: {ph_rementry} remove entry (number) in/from (list of values) > > This phrase removes the entry at the given position, counting from 1 as the first entry. (Once it is removed, the other entries shuffle down.) Example: > > let L be {3, 1, 4, 1, 5, 9, 2, 6, 5, 3}; > remove entry 3 from L; > > results in `L` being `{3, 1, 1, 5, 9, 2, 6, 5, 3}`. > phrase: {ph_rementries} remove entries (number) to (number) in/from (list of values) > > This phrase removes the entries at the given range of positions, counting from 1 as the first entry. (Once they are removed, the other entries shuffle down.) Example: > > let L be {3, 1, 4, 1, 5, 9, 2, 6, 5, 3}; > remove entries 3 to 6 from L; > > results in `L` being `{3, 1, 2, 6, 5, 3}`. ## Lists of objects ^^{lists: creating: by description} ^^{defining: lists: by description} Lists can be made of values of any kind (including other lists), but lists of objects are especially useful. We could always make these "by hand": let L be {the pot plant, the foxglove}; But it is usually easier and clearer to use descriptions. > phrase: {ph_listofdesc} list of (description of values) ... list of values > > This phrase produces the list of all values matching the given description. Inform will issue a problem message if the result would be an infinite list, or one which is impractical to test: for instance `list of even numbers` is not feasible. While that works nicely for many kinds of value (`list of recurring scenes`, say), it's particularly useful for objects: let L be the list of open containers; add the list of open doors to L; means that L now contains the open containers (if any) followed by the open doors (if any). Or, for example: let L be the list of things; remove the list of backdrops from L; makes a list of all non-backdrops. As mentioned above, lists of objects can be said in two additional ways: "[L with definite articles]" "[L with indefinite articles]" And as mentioned below, they can be sorted in property value order: sort L in P order; sort L in reverse P order; where P is any value property. In all other respects, lists of objects are no different to other lists. ## Lists of values matching a description ^^{lists: creating: by description} ^^{defining: lists: by description} The useful `list of ...` syntax can also be used to produce lists of the values matching a description, too. Thus: let L be the list of non-recurring scenes; let C be the list of colours; There is little to say here except for the usual warning that some kinds of value have a range which is too large to make this possible. For instance, Inform could not sensibly represent: let N be the list of even numbers; It would just be too large to hold. In general, if we can repeat through, or find the number of, values matching a description, then we can also use `list of` to bring them all together. See the chart of kinds of value in the Kinds index for a project for which kinds of value allow this. ## Sorting, reversing and rotating lists ^^{lists: sorting} ^^{lists: reversing} ^^{lists: rotating} ^^{randomness: sorting lists in random order} Any list L can be reversed: > phrase: {ph_reverselist} reverse (list of values) > > This phrase puts the list in reverse order. The old entry 1 becomes the new last entry, and so on: reversing an empty list or a list containing only one entry leaves it unchanged. Example: > > let L be {11, 12, 14, 15, 16, 17}; > reverse L; > > results in L being {17, 16, 15, 14, 12, 11}. And any list can similarly be sorted: > phrase: {ph_sortlist} sort (list of values) > > This phrase puts the list into ascending order. Example: > > let L be {6 PM, 11:13 AM, 4:21 PM, 9:01 AM}; > sort L; > > results in L being {9:01 AM, 11:13 AM, 4:21 PM, 6 PM}. > phrase: {ph_sortlistreverse} sort (list of values) in reverse order > > This phrase puts the list into descending order. Example: > > let L be {6 PM, 11:13 AM, 4:21 PM, 9:01 AM}; > sort L in reverse order; > > results in L being {6 PM, 4:21 PM, 11:13 AM, 9:01 AM}. > phrase: {ph_sortlistphrase} sort (list of values) with (phrase (value, value) -> number) > > This phrase sorts the list with a custom comparison phrase. A comparison phrase must accept two list elements, and then return a number which indicates the relative order of the two list elements: negative if the left value should come before the right, zero if they are equal, and positive if the left value should come after the right. For example to sort numbers you would use this phrase: > > To decide which number is the comparison of (X - a number) and (Y - a number) (this is numerical comparison): > decide on X - Y; > > You could then sort a list of numbers using the numerical comparison phrase: > > let L be {5, 1, 7, 2, 3}; > sort L with numerical comparison; > > Which results in L being {1, 2, 3, 5, 7}. > phrase: {ph_sortlistrandom} sort (list of values) in random order > > This phrase puts the list into a uniformly random order, shuffling it as if it were a pack of cards. Example: > > let L be {1, 2, 3, 4, 5, 6}; > sort L in random order; > > might result in L being {3, 1, 5, 6, 4, 2}. Or any of 719 other arrangements, including being left as it was. Lists of objects can also be sorted in property value order. For instance, > phrase: {ph_sortlistproperty} sort (list of objects) in (property) order > > This phrase puts the list into ascending order of the values of the given property for the items in the list; this is only allowed if all of those values do have the property in question. Example: > > let L be the list of people; > sort L in carrying capacity order; > > would arrange people with weaklings first, titans last. > phrase: {ph_sortlistpropertyreverse} sort (list of objects) in reverse (property) order > > This phrase puts the list into descending order of the values of the given property for the items in the list; this is only allowed if all of those values do have the property in question. Example: > > let L be the list of people; > sort L in reverse carrying capacity order; > > would arrange people with titans first, weaklings last. Rotating a list means moving all of its entries along by one place, and then moving the one on the end back to the start. For instance, if `L` is `{1, 2, 3, 4}`, then > phrase: {ph_rotatelist} rotate (list of values) > > This phrase shuffles the entries of the list forwards (to the right) by one place, so that the 1st becomes 2nd, the 2nd becomes 3rd, and so on until the last, which becomes the new first entry. Example: > > let L be { "cow", "heifer", "bullock" }; > rotate L; > > results in L being { "bullock", "cow", "heifer" }. > phrase: {ph_rotatelistback} rotate (list of values) backwards > > This phrase shuffles the entries of the list backwards (to the left) by one place, so that the 3rd becomes 2nd, the 2nd becomes 1st, and so on; the previous 1st entry becomes the new last entry. Example: > > let L be { "cow", "heifer", "bullock" }; > rotate L backwards; > > results in `L` being { "heifer", "bullock", "cow"}. (This achieves the same effect as `reverse L; rotate L; reverse L;` but is a little faster, and a lot less effort to read.) ## Accessing entries in a list ^^{lists: finding entries} ^^{lists: finding length} ^^{entry (number) of (list)+sourcearg+} ^^{+to+now (a condition): changing list entries} ^^{lists: changing entries} The length of a list can change as values are added or removed, and can in principle be any number from 0 upwards. A list with 0 entries is empty. We can find the length with: > phrase: {ph_numberentries} number of entries in/of/from (list of values) ... number > > This phrase produces the number of positions in the list. Example: > > the number of entries in {1, 1, 1, 3, 1} > > is 5, even though there are only two genuinely different items in the list. If the length is N then the entries are numbered from 1 (the front) to N (the back). These entries can be accessed directly by their numbers. For instance, entry 2 of L refers to the second entry of L: it can be used as a value, or changed, just as if it were a named variable. For instance, we could write: now entry 7 of L is "Spain"; say "The rain in [entry 7 of L] stays mainly in the plain."; which would (untruthfully) print ``The rain in Spain stays mainly in the plain.``, but only if `L` had an entry 7 to make use of: if `L` were a list of 5 entries, say, then a run-time problem results. (And if `L` cannot hold text, a problem message means that we never get as far as run-time.) Because entries number from 1, this is always incorrect: entry 0 of L and if `L` is currently empty, then there is no entry which can be accessed, so that any use of `entry ... of L` would produce a run-time problem. There are programming languages in the world where accessing entry 100 in a 7-entry list automatically extends it to be 100 entries long: Inform is not one of them. But see the next section for how to change list lengths explicitly. ## Lengthening or shortening a list ^^{lists: changing length} ^^{lists: extending} ^^{lists: truncating} ^^{lists: memory limits} ^^{lists: Z-machine limitations} ^^{limits: for extending lists} ^^{memory limits: for extending lists} ^^{Z-machine: memory limits} ^^{Glulx: memory limits} ^^{virtual machine: memory limits} We can explicitly change the length of a list like so: > phrase: {ph_changelength} change (list of values) to have (number) entries/entry > > This phrase alters the given list so that it now has exactly the number of entries given. Example: > > change L to have 21 entries; > > If `L` previously had more than 21 entries, they are thrown away (and lost forever); if `L` previously had fewer, then new entries are created, using the default value for whatever kind of value `L` holds. So extending a list of numbers will pad it out with 0s, but extending a list of texts will pad it out with the empty text `""`, and so on. We can also write the equivalent phrases: > phrase: {ph_truncate} truncate (list of values) to (number) entries/entry > > This phrase alters the given list so that it now has no more than the number of entries given. Example: > > truncate L to 8 entries; > > shortens `L` to length 8 if it is currently longer than that, trimming entries from the end, but would (for instance) leave a list of length 3 unchanged. Note that > > truncate L to 0 entries; > > empties it to `{ }`, the list with nothing in. > phrase: {ph_truncatefirst} truncate (list of values) to the/-- first (number) entries/entry > > This phrase alters the given list so that it now consists only of the initial part of the list with the given length. Example: > > truncate L to the first 4 entries; > > turns `{1, 3, 5, 7, 9, 11}` to `{1, 3, 5, 7}`. > phrase: {ph_truncatelast} truncate (list of values) to the/-- last (number) entries/entry > > This phrase alters the given list so that it now consists only of the final part of the list with the given length. Example: > > truncate L to the last 4 entries; > > turns `{1, 3, 5, 7, 9, 11}` to `{5, 7, 9, 11}`. But we don't have to truncate: we can also – > phrase: {ph_extend} extend (list of values) to (number) entries/entry > > This phrase pads out the list with default values as needed so that it now has at least the given length. (If the list is already at least that length, nothing is done.) Example: > > extend L to 80 entries; > > lengthens `L` to length 80 if it is currently shorter than that. For example, To check sorting (N - a number): let L be a list of numbers; extend L to N entries; repeat with X running from 1 to N: now entry X of L is X; say "L unrandomised is [L]."; sort L in random order; say "L randomised is [L]."; sort L; say "L in ascending order is [L]." builds a list of `N` numbers (initially all 0), fills it with the numbers `1`, `2`, `3`, ..., `N`, then randomly reorders them, then sorts them back again, recovering the original order. The text produced by `check sorting 10` depends partly on chance but might for instance be: ``` transcript L unrandomised is 1, 2, 3, 4, 5, 6, 7, 8, 9 and 10. L randomised is 6, 2, 9, 3, 10, 1, 7, 4, 8 and 5. L in ascending order is 1, 2, 3, 4, 5, 6, 7, 8, 9 and 10. ``` As with text in the previous chapter, [Advanced Text], a project which needs really long lists should use the Glulx virtual machine – `check sorting 10000`, for instance, would break the default memory environment on the Z-machine, which is very tight, but works fine (if not very rapidly) on Glulx. ## Variations: arrays, logs, queues, stacks, sets, sieves and rings ^^{lists: variations on use of lists} Lists are highly adaptable, and many other collection-like constructions can be made using them. This section introduces no new material, but simply suggests some of the variations which are possible. 1. The traditional computing term **array** means a list of values accessed by their entry numbers, often used in mathematical computations. The difference between an array and a list is mostly one of attitude, but usually arrays are fixed in length whereas lists can expand or contract. 2. A **log** is a list which records the most recently arrived values, but does not allow itself to grow indefinitely. In the following, which remembers the seven most recently taken items, new values arrive at the end while old ones eventually disappear from the front: The most-recently-taken list is a list of objects that varies. Carry out taking something (called the item): truncate the most-recently-taken list to the last 6 entries; add the item to the most-recently-taken list. After taking: say "Taken. (So, your recent acquisitions: [most-recently-taken list].)" Note that the most-recently-taken list begins play as the empty list, grows as the first few items are taken, but then stabilises at length 7 thereafter. If we need to remember recent history, but only *recent* history, then a log is better than a list which can grow indefinitely, because there is no risk of speed reduction or memory exhaustion in a very long story. 3. A **queue** is a list of values which are waiting for attention. New values join at the back, while those being dealt with are removed from the front (whereupon the whole queue moves up one). An empty queue means that nobody is waiting for attention: but there is, in principle, no upper limit to the size of a queue, as anyone who has tried to make a couchette reservation at Roma Termini will know. Queues typically form when two independent processes are at work, but going at different or variable speeds. An empty queue looks just like any other list: The queue is a list of objects that varies. (Invariably people, in what follows, but we'll make it a `list of objects` to allow for other possibilities too.) Once we identify a `new customer`, we can join them to the queue thus: add the new customer to the queue; The process of serving the customers needs to make sure there is actually somebody waiting in the queue before it does anything: Every turn when the number of entries in the queue is not 0: let the next customer be entry 1 of the queue; say "[The next customer] is served and leaves."; remove entry 1 from the queue. Of course queues can also be constructed which empty from other positions, rather than the front: or we could make what computer scientists sometimes call a **deque**, a "double-ended queue" where new values arrive at both ends. 4. A **stack** is like a queue except that values arrive at, and are removed from, the same end. Stacks are slightly faster if the active end is the back rather than the front, though this will only be noticeable if they grow quite large. To put a value `V` onto a stack `S` (which is known as "pushing") is simple: add V to S; And to remove a value from the top of the stack (which is known as "pulling"): let N be the number of entries in S; let V be entry N of S; remove entry N from S; Note that the middle line, accessing entry `N`, will fail if `N` is 0, that is, if the stack is empty: Inform's list routines will produce a run-time problem message. Stacks are useful if some long-term process is constantly being interrupted by newer and more urgent demands, but they can also be used in planning. If a character has a long-term goal, which needs various short-term goals to be achieved along the way, then a stack can represent the goals currently being pursued. The top of the stack represents what the character is trying to achieve now. If the character realises that it needs to achieve something else first, we put that new goal onto the top of the stack, and it becomes the new current goal. When the character completes a task, it can be removed, and we can go back to trying to finish whatever is now on top. When the stack is empty, the character has achieved the original goal. 5. Notoriously, **set** has 464 distinct meanings in the Oxford English Dictionary, making it the single most ambiguous word in the language. Here we mean not the home of a badger or the Egyptian god of the desert, but the mathematical sense: a collection of values (sometimes called "elements") without duplicates, and which is normally written in brace notation and in some natural order for the reader's convenience. The trick here is to maintain the principle that, at all times, our list is sorted in order and contains no duplicates. To provide an example, we start with two sets of numbers: let S be {2, 4, 8, 16, 32, 64}; let T be {2, 4, 6, 10}; Here we add an element to `T`: add 8 to T, if absent; sort T; The `if absent` clause ensures that no duplicate can occur, and by sorting `T` afterwards, we maintain the principle that a set must remain in order – so `T` is now `{2, 4, 6, 8, 10}`, not `{2, 4, 6, 10, 8}`. (Inform's sorting algorithm is fast on nearly-sorted lists, so frequent sorting is not as inefficient as it might look.) We next take the union of `T` and `S`, that is, the set containing everything which is in either or both: let U be S; add T to U, if absent; sort U; This makes `U` equal to `{2, 4, 6, 8, 10, 16, 32, 64}`, and once again no duplicates occur and we preserve the sorting. The intersection of `T` and `S`, the set of elements in both of them, is a little trickier: let I be T; repeat with the element running through T: if the element is not listed in S, remove the element from I. (Faster methods could be devised which exploit the sortedness of `T` and `S`, but are not worth it for shortish lists.) This results in `I` set to `{2, 4, 8}`. Lastly, we can form the set difference, consisting of those elements which are in `S` but not in `T`: let D be S; remove T from D, if present; Here, as with intersection, since all we do is to strike out unwanted elements, the surviving ones remain in order and there is no need to sort when we are finished. This sets `D` to `{16, 32, 64}`. 6. A **sieve** is used to make a complicated choice where there are many constraints, by ruling out impossible cases to see what is left. The term derives from the kitchen utensil (for sieving fine grains of flour), but via the name of the "sieve of Eratosthenes", an ancient Greek method for determining the prime numbers. Using a sieve is much like using a set, and the difference is mainly one of outlook – we are interested in what does not belong, rather than what does. 7. A **ring** is not so much a row of values, more a circle, with the last and first entries thought of as adjacent. One position is usually thought of as special, and is the place where new items are added: this may as well be entry 1. For instance, to add `new item` to the ring: add the item at entry 1 in the ring; To set `item` to the frontmost value and extract it from the ring: let the item be entry 1 of the ring; remove entry 1 from the ring; And we can rotate the ring in either direction, making a different entry the new entry 1 and therefore the new frontmost value: rotate the ring; rotate the ring backwards; A last note to conclude the chapter on lists. Lists, like almost all other values in Inform, can be passed to phrases as parameters. However, note that they are genuine values, not what some programming languages call "references" or "pointers". So the following: To mess with (L - a list of numbers): add 7 to L, if absent. does nothing, in practice. If given a list, it adds 7 to the list, but then throws it away again, so the longer list is never seen; it's exactly like To mess with (N - a number): now N is 3. which can never affect anything other than its own temporary value `N`, which expires almost immediately in any case. If we want a phrase which changes a list in a useful way and gives it back to us, we need a phrase which both takes in and gives back: To decide which list of numbers is the extended (L - a list of numbers): add 7 to L, if absent; decide on L. And then, for example – the extended { 2, 4, 6 }; produces: ``` transcript { 2, 4, 6, 7 } ``` # Advanced Phrases ## A review of kinds ^^{kinds} ^^{kinds: of kinds} ^^{values: kinds of kinds of value} ^^{kinds: kind variables} ^^{variables: kind variables} ^^{|arithmetic value} ^^{|enumerated value} ^^{|sayable value} ^^{text substitutions: sayable values} Most of the time, what's created in an Inform source text will have a name which can be used as a value – sometimes openly so, sometimes not. In this book, we haven't gone out of our way to make that point, because there was no real need to do so. It's possible to make heavy use of rulebooks and write large-scale Inform projects without ever needing to use a rulebook's name as a value in its own right, for example. But if we want to create sophisticated extensions to Inform, or to use modern techniques such as functional and generic programming, we need to be fluent in the language of kinds. Inform's language of kinds has four ingredients: base kinds, constructions, kind variables and kinds of kinds. **1. Base kinds.** Inform provides the following base kinds for values: object, number, real number, time, truth state, text, snippet, Unicode character, action, scene, table name, equation name, use option, action name, figure name, sound name, external file, rulebook outcome, parser error together with a few others, such as `response` and `verb`, to do with linguistic features. And Inform allows us to create new base kinds either by making more specialised kinds of object: A geographical layout is a kind of object. A marmoset is a kind of animal. Or by making new enumerations or arithmetical kinds: Distance is a kind of value. 10km specifies a distance. Colour is a kind of value. Red, green and blue are colours. **2. Constructions.** These are ways to make new kinds from existing ones. The construction most often used is `list of...`. For any kind `K`, there is a kind called list of `K`. So the range of possible kinds in Inform is actually infinite, because: number list of numbers list of lists of numbers list of lists of lists of numbers ... are all different from each other. Inform has nine constructions, as follows: list of K description of K relation of K to L K based rule producing L K based rulebook producing L activity on K phrase K -> L K valued property K valued table column Some of these have appeared in previous chapters, but in abbreviated form. For example, `rulebook` abbreviates `action based rulebook producing nothing`, and `either/or property` is a synonym for `truth state valued property`. The kinds of descriptions and phrases haven't been covered yet, but are coming up in the sections following. These constructions can of course be combined: phrase (relation of numbers to colours, number) -> list of colours Brackets can be used to clarify matters: phrase (phrase number -> (phrase number -> number)) -> nothing Nothing will make that a simple idea, but it's unambiguous and can be puzzled out with practice. **3. Variables.** In a way, that's everything: there are just base kinds and constructions on them, and those construct every possible kind in Inform. But the language we use to describe kinds is larger than that, because it allows us to describe many kinds at once, in the same way that Inform reads the word "something" as applying to many objects at once, not as a single object. Kind variables will be covered later in the chapter, but the idea is that: To hunt for (needle - value of kind K) in (haystack - list of Ks): ... allows us to describe the kinds acceptable in a phrase so that a wide range of possibilities are allowed. The above matches both: hunt for 4 in { 2, 3, 4, 5 }; hunt for "fish" in { "lemon sauce", "fish", "garden peas" }; The letter `K` in the definition stood for any kind; in the first use of `hunt` here, `K` turned out to be `number`, and in the second it was `text`. On the other hand Inform would reject: hunt for 4 in { containment relation, support relation }; because there is no kind `K` which can make this match the definition. There are potentially 26 kind variables, `A` to `Z`, though it's customary to use them in the order `K`, `L`, `M`, ..., and it's very rare to need more than two at a time. **4. Kinds of kind.** Inform understands several names which look as if they are kinds, but actually aren't: value, arithmetic value, enumerated value, sayable value (Again, these are built in to Inform.) They are not kinds because they're just too loose and vague. Instead, they can be used in phrase definitions to match against multiple possibilities: To announce (X - sayable value): say "I declare that [X] has arrived." This makes `announce X` work for any value `X` which can be said. All the same, `sayable value` is not a kind. It could never be safe for this to be the kind of a variable, because Inform would never know what could be done with the contents (except that it could be printed out). **5. Secret inner workings.** There isn't a fifth ingredient, but if there were, it would be a handful of names used in matching some of the core built-in phrases of Inform which have so-called inline I6 definitions. These are not intended for anyone else to use, and are just an internal convenience; they aren't publicly documented and might change without notice. They don't describe kinds at all, because they tell the matcher to look for something else instead. For instance, there's one called `condition`, which means `match a condition rather than a value`. They appear in red ink in the Phrasebook index. ## Descriptions as values {kind_description} ^^{values: descriptions as values} ^^{descriptions (references to things): as values} ^^{kinds: of description} ^^{member of (description)+sourcearg+} In the chapter on [Descriptions], we saw that a description can be any source text which describes one or more objects: it might be as simple as `the Corn Market`, or as complicated as `open containers which are in dark rooms`. More or less the only restriction is that it must be unambiguous as to what counts and what does not: `three containers` is ambiguous as a description because it does not say which three. We've now seen several interesting tricks with descriptions. In fact, if D is a description, then say "You gaze mournfully at [the list of D]."; let the tally be the number of D; let the surprise prize be a random D; repeat with item running through D: ... are all standard things to do. These examples make it look as if it must be possible to define phrases which act on descriptions, and in fact it is, because a description can be a value in itself. For example, even numbers open containers which are in dark rooms are values of kind `description of numbers` and `description of objects` respectively. In general, if `K` is any kind then `description of K` is also a kind. Here is how we might make use of that: To enumerate (collection - a description of objects): repeat with the item running through the collection: say "-- [The item]." This makes `enumerate lighted rooms` run off a list of lighted rooms in a textual format different from the standard one produced by `say the list of lighted rooms`. Inside the definition, `collection` can be used wherever a description might be used: here, for instance, we use it as the range for the repeat loop. (That's only possible because the range is limited in size: Inform wouldn't have allowed us to range through, say, all texts.) Purely as a convenience, we can also write `member of` or `members of` in this context. For instance, in the enumerate definition, it would have been just as good to write `...running through the members of the collection...` in the repeat. (Similarly, we could write `number of members of the collection` or `a random member of the collection`, which looks grammatically tidier than writing `number of the collection` or `random of the collection` – though in fact both of these do work.) Finally, it's sometimes useful in an abstract situation to test > phrase: {ph_valuematch} if (value) matches (description of values): > > This condition is true if the value matches the description; the kinds must be compatible, or Inform will issue a problem message. There is no point using this for cases where the description is given explicitly: > > if 4 matches even numbers, ... > > because it is easier to write just: > > if 4 is an even number, ... > > So this condition is only useful when the description is stored in some variable, and its identity is not known. ## Phrases as values ^^{values: phrases as values} ^^{phrases: as values} ^^{kinds: of phrase} ^^{|->: in phrase kinds} ^^{phrases: named phrases} ^^{names: of phrases} ^^{(this is), in naming phrases+sourcepart+} ^^^{+to+(phrase nothing -> value) applied --> applied}^^^{+to+(phrase value -> value) applied to (value) --> applied to}^^^{+to+(phrase (value, value) -> value) applied to (value) and (value) --> applied to}^^^{+to+(phrase (value, value) -> value) reduction of (list of values) --> applied to}^^^{+to+(phrase (value, value, value) -> value) applied to (value) and (value) and (value) --> applied to} Given any two kinds `K` and `L`, the kind `phrase K -> L` is now a kind. (This is meant to look like a mathematical function arrow.) For example, the phrase defined by To decide which number is the square of (N - a number): ... has the kind `phrase number -> number`. Brackets and commas are used if the phrase combines several values, so To decide which text is (T - text) repeated (N - a number) times: ... has the kind `phrase (text, number) -> text`. The word `nothing` is used if there are no values in, or no value out – thus To decide which number is the magic target: ... has kind `phrase nothing -> number`, and To dig (eastward - length) by (northward - length): ... has the kind `phrase (length, length) -> nothing`. But how are we to get at these values? The answer is that we need to give a phrase a name in order to do so. For example: To decide what number is double (N - a number) (this is doubling): decide on N plus N. This is the same syntax used to name rules, and the idea is the same. If we try `showme doubling`, the result is phrase number -> number: doubling The main thing we want to do with a phrase is to apply it. So: showme doubling applied to 2; produces ``` transcript "doubling applied to 2" = number: 4 ``` There are versions of `applied to` for phrases applied to 0 to 3 values: > phrase: {ph_applied0} (phrase nothing -> value) applied ... value > > This phrase produces the result of applying the given phrase, which must be one which takes no values itself. > phrase: {ph_applied1} (phrase value -> value) applied to (value) ... value > > This phrase produces the result of applying the given phrase, which must be one which takes one value itself. > phrase: {ph_applied2} (phrase (value, value) -> value) applied to (value) and (value) ... value > > This phrase produces the result of applying the given phrase, which must be one which takes two values itself. > phrase: {ph_applied3} (phrase (value, value, value) -> value) applied to (value) and (value) and (value) ... value > > This phrase produces the result of applying the given phrase, which must be one which takes three values itself. So for example: F applied F applied to V F applied to V and W F applied to V and W and X For phrases which do not produce a value, we use `apply`: > phrase: {ph_apply0} apply (phrase nothing -> nothing) > > This phrase causes the given phrase to be applied. It must be one which takes no values itself. > phrase: {ph_apply1} apply (phrase value -> nothing) to (value) > > This phrase causes the given phrase to be applied. It must be one which takes one value itself. > phrase: {ph_apply2} apply (phrase (value, value) -> nothing) to (value) and (value) > > This phrase causes the given phrase to be applied. It must be one which takes two values itself. > phrase: {ph_apply3} apply (phrase (value, value, value) -> nothing) to (value) and (value) and (value) > > This phrase causes the given phrase to be applied. It must be one which takes three values itself. Thus: apply F; apply F to V; apply F to V and W; apply F to V and W and X; ## Default values for phrase kinds ^^{kinds: of phrase: default values for} ^^{kinds: default values of kinds} ^^{phrases: as values: default values} The default value for `phrase K -> nothing` is a phrase which does nothing. For example, if we write: let S be a phrase numbers -> nothing; then S is created holding the default `phrase numbers -> nothing`, and if we then try it out with: apply S to 17; we will indeed find that nothing happens. The default value for `phrase K -> L` is a phrase which, no matter what value of `K` it applies to, always produces the default value of `L`. (It's a sort of equivalent of the zero function in mathematics – indeed that's exactly what it is, if `L` is `number`.) So: let Q be a phrase numbers -> times; showme Q; showme Q applied to 4; showme Q applied to -7; produces: ``` transcript "q" = phrase number -> time: default value of phrase number -> time "q applied to 4" = time: 9:00 am "q applied to -7" = time: 9:00 am ``` Here `Q` is set to the default phrase because we didn't give it any other value; it has the name we might expect (`default value of phrase number -> time`) and it works as advertised, producing `9:00 am` no matter what number is fed in. More ambitiously, and supposing that we have a kind called `colour` whose first possible value is `red`: let R be a phrase numbers -> (phrase numbers -> colours); showme R; showme R applied to 3; showme (R applied to 3) applied to 2; produces: ``` transcript "r" = phrase number -> (phrase number -> colour): default value of phrase number -> (phrase number -> colour) "r applied to 3" = phrase number -> colour: default value of phrase number -> colour "( r applied to 3 ) applied to 2" = colour: red ``` ## Map, filter and reduce ^^{lists: mapping (with a phrase)} ^^{lists: filtering (with a phrase or description)} ^^{lists: reducing (with a phrase, to a value)}^^^{+to+(phrase value -> value) applied to (list of values) --> applied to}^^^{+to+(phrase (value, value) -> value) reduction of (list of values) --> reduction of} When a mass of computations has to be done, the traditional approach is to work through them in a `repeat` loop. One modern alternative, growing in popularity, is to form a list of inputs; then apply the same computation to each input in turn to form a list of results (this is called "mapping"); throw out any bad or unwanted results ("filtering"); and then combine the surviving results into a single composite answer ("reducing", though some programming languages call this "folding" or "accumulation"; it's a much-reinvented idea). Inform provides all three of these fundamental list-processing operations. There is no special term for a "map", because Inform treats it as another case of `applied to`. > phrase: {ph_appliedlist} (phrase value -> value) applied to (list of values) ... list of values > > This phrase takes the list, applies the phrase to each entry in the list, and forms a new list of the result. Example: > > To decide what number is double (N - a number) (this is doubling): > decide on N plus N. > > Then `doubling applied to 2` produces 4, by the simpler definition of `applied to`, but also: > > doubling applied to {2, 3, 4} > > produces the list `{4, 6, 8}`. More divertingly, suppose we define: To decide what text is the longhand form of (N - a number) (this is spelling out): decide on "[N in words]". To decide what text is the consonant form of (T - text) (this is txtng): replace the regular expression "" in T with ""; decide on T. Then we can write a chain of three maps in succession: txtng applied to spelling out applied to doubling applied to {3, 8, 4, 19, 7} to produce the value `{"sx", "sxtn", "ght", "thrty-ght", "frtn"}`. Next, filtering. Here we make use of descriptions, in order to say what values will be allowed through the filter. So: > phrase: {ph_filter} filter to (description of values) of (list of values) ... list of values > > This phrase produces a new list which is a thinner version of the one given, so that it contains only those values which match the description given. Example: > > filter to even numbers of {3, 8, 4, 19, 7} > > produces `{8, 4}`, with the values `3`, `19`, and `7` failing to make it through. A sufficiently fine filter may well thin out a list to a single entry, or even no entries at all, but the result is always a list. To get the full effect of filtering, we probably need to define an adjective or two. For example: Definition: a text (called T) is lengthy if the number of characters in it is greater than 6. We can then write, for example: let L be the filter to lengthy texts of spelling out applied to {15, 2, 20, 29, -4}; showme L; which produces the list `{"fifteen", "twenty-nine", "minus four"}`. Lastly, reduction. In order to combine a whole list of values, we need a phrase to combine any two. Here are some samples: To decide what number is the larger of (N - number) and (M - number) (this is maximisation): if N > M, decide on N; decide on M. To decide what text is the concatenation of (X - text) and (Y - text) (this is concatenation): decide on "[X][Y]". And here are some sample reductions: let X be the maximisation reduction of {3, 8, 4, 19, 7}; let Y be the concatenation reduction of txtng applied to spelling out applied to doubling applied to {3, 8, 4, 19, 7}; sets `X` to `19`, the highest of the values, and `Y` to the text `"sxsxtnghtthrty-ghtfrtn"`. In each case a list has been reduced to a single value which somehow combines the contents. > phrase: {ph_reduction} (phrase (value, value) -> value) reduction of (list of values) ... value > > This phrase works through the list and accumulates the values in it, using the phrase supplied. Example: if we have > > To decide what number is the sum of (N - number) and (M - number) > (this is summing): > decide on N + M. > > then the summing reduction of `{3, 8, 4, 19, 7}` is the number `41`, obtained by (((3 + 8) + 4) + 19) + 7, so that the `summing` phrase has been used four times. Is map/filter/reduce always a good idea? Devotees point out that almost any computation can be thought of in this way, and in systems where the work has to be distributed around multiple processors it can be a very powerful tool. (There are programming languages without loops where it's essentially the only tool.) At its best, it reads very elegantly: one assembles all of the tools needed – definitions of doubling, lengthy, spelling out, concatenation and so on – and then each actual task is expressed in a single line at the end. On the other hand, there are also times when this is a needlessly complicated disguise for what could more easily be done with a `repeat` loop, and also more efficiently since assembling and dismantling lists in memory does take some overhead time. So these list operations are not a panacea, but it's good to have them available. ## Generic phrases ^^{kinds: of kinds} ^^{values: kinds of kinds of value} ^^{|arithmetic value} ^^{|enumerated value} ^^{|sayable value} ^^{text substitutions: sayable values} ^^{generic phrases} The following looks quite innocent: To say (V - value) twice: say "[V]. [V], I say!" It's clear at a glance what this is intended to do, but at a second glance things aren't so straightforward. "Value" is not itself a kind – it's too big and unspecific. For instance, if we were to allow a variable to be just `a value`, we could freely set it to `12` one minute and to `"dahlias"` the next, and such a variable would be dangerous since we would never know what could safely be done with its contents. A phrase like this one is called _generic_, because it's not so much a single, actual phrase as a recipe to make phrases. (Inform automatically works out which kinds we need the phrase for, and creates a version of the phrase for those kinds.) So `value` is not a kind, but a kind of kind. Inform has several of these: ``` value, arithmetic value, enumerated value, sayable value ``` These act as ways to say "a value of any kind matching this can go here". For example, `value` is a way to say "any kind at all"; `arithmetic value` is any kind which arithmetic can be performed on (any kind with the little calculator icon in the Arithmetic part of the Kinds index); and so on. If we write: To double (V - arithmetic value): say "[V times 2]." the restriction to `arithmetic value` means that although `double 3`, `double 6 kg`, etc., would be matched, `double the Entire Game` would not – you can't perform arithmetic on scenes. Similarly, it would have been tidier to write: To say (V - sayable value) twice: say "[V]. [V], I say!" because then Inform will make it clearer why `say X twice` won't work if `X` is one of those rare values which it can't say. The Kinds index shows which kinds match against which of these "kinds of kind". For instance, it shows that `time` > Matches: value, arithmetic value, sayable value which means that time is something we can do arithmetic on, and can say. ## Kind variables ^^{kinds: kind variables} ^^{variables: kind variables} ^^{characters (letters): capital letters as kind variables} The examples of generic phrases in the previous section were really only toy examples. Suppose we want a phrase which will take any arithmetic value and triple it. We could do something like this: To triple (V - arithmetic value): say "[V times 3]." But this only prints the answer. Suppose we want to be given the value back, instead: how can we write the phrase? The trouble is that, not knowing the kind of `V`, we can't say what kind will be produced. We need a way of saying "the same kind comes out as went in". Inform expresses that using kind variables: To decide which K is triple (original - arithmetic value of kind K): decide on 3 times the original. Here, `K` stands for any kind which matches `arithmetic value`. Inform supports exactly 26 of these symbols, which are written `A` to `Z`, but it's customary to use `K` and `L`. (They can be written in the plural if we like: e.g., `list of Ks`. But they must always use a capital letter: `list of k` is not allowed.) Each symbol we use has to be declared in exactly one of the bracketed ingredients for the phrase – here, the declaration is `arithmetic value of kind K`. That creates `K` and says that it has to be arithmetic; if we'd just said `value of kind K`, it could have been anything. (Alternatively, we could use any of the kinds of kind in the previous section.) For a more ambitious example, here is one way to define the mapping operation described earlier in the chapter: To decide what list of L is (function - phrase K -> value of kind L) applied to (original list - list of values of kind K): let the result be a list of Ls; repeat with item running through the original list: let the mapped item be the function applied to the item; add the mapped item to the result; decide on the result. Here we need two symbols to explain the complicated way that the values going in and out have to match up to each other. Note also the way that the temporary variable `result` is created: let the result be a list of Ls; Ordinarily, of course, `L` is not a kind. But within the body of a phrase definition, it means whatever kind `L` matched against. When a symbol occurs several times in the same definition, subtle differences can arise according to which appearance is the declaration. These are not quite the same: To hunt for (V - value of kind K) in (L - list of Ks): ... To hunt for (V - K) in (L - list of values of kind K): ... The difference arises – though very rarely – if `V` has some different kind compared to the list entries, but which can be used as if it were of that kind. For example, hunt for the player's command in {"take all", "wait"}; Here `V` is a `snippet`, but `L` is a `list of texts`; and a `snippet` can be used in place of a `text`, but not vice versa. So this will match the second definition, because `K` is set to `text`, but it won't match the first, where `K` is set to `snippet`. ## Matching the names of kinds ^^{kinds: in phrase parameters} ^^{phrases: phrase parameters: kind values} ^^{parameters: of phrases: kind values} Sometimes a phrase needs to know what kind it's to work on, but isn't going to be given any particular value of it. For example: To assay (name of kind of value K): repeat with item running through Ks: say "There's [item]."; say "But the default is [default value of K]."; Note that there's no hyphen, and no name for the bracketed token – it only sets `K`. We can then have, say: assay colours; assay vehicles; But `assay texts` would throw a problem message, because we can't repeat through all possible texts. For a different reason, assay open doors; would not be allowed – `open doors` is a description which applies to some doors and not others; it isn't a kind. It would make no sense to talk about `default value of open door`, for example. ## In what order? ^^{phrases: precedence of definitions} ^^{precedence: of phrase definitions} ^^{disambiguation: of source text: precedence of phrase definitions} Recall the definition: To slam shut (box - an open container): say "With great panache, you slam shut [the box].". Suppose we then try to `slam shut the wall safe` at a time during play when the wall safe is already closed. An error message will then be printed during play, since there must be a mistake in the design. The combination of checking both when Inform builds the story file and then continuously when the story file is played guarantees that, in all cases, a varying item such as `box` in the definition of `To slam shut (box – open container)` always satisfies the condition laid down. Instead suppose we also have the following definition: To slam shut (box - a container): say "You are unable to slam shut [the box], which is already closed.". We now have two definitions of `slam shut`. Sometimes the box it's applied to will be closed, in which case only the second definition fits, and will be the one used. But if the box is open, both definitions fit. Which will happen? The rule is: 1. A narrower condition takes precedence over a broader one; 2. If neither condition is narrower than the other, then whichever phrase was defined later in the source code is the one taking precedence; 3. Except that if the phrase is being used in the definition of phrase P, then P is always last in precedence order, so that recursion is always the very last possibility considered. This allows more specific or later definitions to make use of less specific or earlier ones in a natural way. Rule 1 ensures that a definition involving `open container` takes priority over one which merely involves `container`, for instance. And therefore when the box is open, it's the more specific phrase to do with open containers which is invoked: so, with great panache, the box is slammed shut. On the other hand, neither of these patterns is narrower than the other: To describe (something - transparent): ... To describe (something - container): ... Some containers are transparent, some not; some transparent things are containers, some not. Rule 1 therefore does not apply, so it is the later of the two phrases which takes effect. ## Ambiguities ^^{phrases: precedence of definitions} ^^{precedence: of phrase definitions} ^^{disambiguation: of source text: precedence of phrase definitions} Another possible ambiguity occurs when a phrase might match two lexically different possibilities using the same words. say the dishcloth; could be construed as a usage of either of these cases: say the (something - a thing) say (something - a thing) These of course have different effects – one produces the name with a definite article, the other just the name, so the difference is important. The rule here is that whichever possibility contains the most words, in this case `say the (...)`, takes precedence, because it's assumed to be a more specific form of the less wordy version. # Screen and Keyboard ## Virtual machines, story files, and I/O {PM_UnknownVirtualMachine} ^^{virtual machine} ^^{Glulx <-- virtual machine: Glulx} ^^{Z-machine <-- virtual machine: Z-machine} The many chapters so far in this book have talked about creating an interactive fiction as if it lived in an abstract world of its own. The inner life of the story takes place in that same abstract world whatever needs to be done, whether that's working out how the characters move around in a murder mystery, or sorting lists of numbers. As for how the story communicates with the outside world, there has only been the ability to `say` text, and in some mysterious way to receive commands. > EXAMINE LAMP It's a typical Linux-Apache-MySQL-Perl server dating from the late 1990s. Up to now, that has been the only sort of _input/output_, or _I/O_, available. The typed command was input, and the reply back was output. The player might not have a traditional keyboard or screen at all, and could be using anything from a palm-sized phone to a Braille display the size of a loom — and yet it is as if the story plays out on an old teletype machine, where text is chattered out and then pauses for typed commands. Many classic interactive fictions have been written that way, like dialogues with a typewriter, but finding creative new styles of interaction is just as much part of the art form. To make those possible, authors need further ways for an Inform story to interact with the outside world. Not just by text, but images, sound effects, and music. Not just keyboard input, but mouse clicks. Not just scrolling text, but a screen divided up into windows. Different hardware handles all of that quite differently. But clearly it would be impractical for Inform, when the user clicks the Release button, to produce thousands of variant programs, one for each sort of computer a player might want to use. What Inform does instead is to generate a _story file_. A story file is a program, but for a _virtual machine_, or VM. The VM is an idealised computer. It has no physical existence. In effect, it is the abstract world mentioned above. But a wide range of real-world computers can be made to behave like this imaginary one using an app called an _interpreter_ — one which can play any Inform story file. Or, more commonly nowadays, Inform releases a website, which contains both the story file and the interpreter all bundled up within it: and once this is hosted online, anybody with a modern web browser can play. So by producing programs for the VM, Inform can make stories which can be played almost anywhere. Another advantage of the VM is that those story files have only very limited access to the computers they run on. They can show an image, or play music, but not rummage through the user's file system looking for crypto wallets: they cannot steal credentials, or vandalise. Because of that, story files belong in the "mostly harmless" category of files – like images – rather than the "how far do you trust this person?" category – like apps. When running on web browsers, they are safer still. The two VMs which Inform can work with are called the Z-machine and Glulx. The Settings panel of an Inform project allows authors to choose between these, but the default nowaways is Glulx, which is much the more capable. Glulx removes many size limits: stories can be have more text, numbers can be larger, and so on. Inform takes advantage of that automatically. But Glulx also offers another sort of extra capacity: it gives story files more access to hardware features beyond the printing and typing of text, through its system for input/output, which is called Glk. This chapter, and the next two, are about how Inform authors can access these hardware features in a safe and portable way. Most of those will be for Glulx only, but some simpler features (such as boldface lettering) will work on the Z-machine too. ## Glulx features and Glk features A recurring issue throughout these three chapters is that not every feature of Glk is available on every Glulx interpreter. For some authors this may not be a concern: if a story is intended to run only on a website, then its author can choose exactly which Glulx interpreter will run it, and will therefore know in advance what will and will not work. > [!IMPORTANT] > With that said, note that the Story pane in the Inform app is also a Glulx interpreter, and — not being web-based — has different capabilities than website interpreters. Because of that, testing some Glk features intended for web use can only really be done by releasing a project to a website and then trying it out in a web browser. If a story is released not as part of a website but as a downloadable story file for use on many platforms, then the author will have to think: what if, say, pictures or coloured text are not available? One solution is to provide alternatives: To say emphasise (T - text): if the text formatting feature is supported: say "[basic red letters][T][default colours]"; otherwise: say "[bold type][T][roman type]". Or there is always the more draconian solution: When play begins: if the glk unicode feature is unsupported: end the story saying "This interpreter does not support Unicode." As this suggests, when a project is running on Glulx, Inform knows the names of various possible features, and can test whether they are `supported` or `unsupported`. These features are divided into two sets: - Features of the Glulx virtual machine itself belong to the kind `glulx feature`, and - Features of the Glk input/output system used by Glulx belong to the kind `glk feature`. For example, `double precision real numbers feature` is a `glulx feature`, since computation is all done inside the VM itself, whereas the `sound volume feature` is a `glk feature`, since sound effects are a form of output. Giving a full list of these features here would not be very enlightening, but the curious could always try running this to find out: When play begins: say "Good news about the VM: [list of supported glulx features]."; say "Bad news: [list of unsupported glulx features]."; say "And on the I/O front, good news: [list of supported glk features]."; say "Bad news: [list of unsupported glk features]."; > [!TIP] > The test made by `supported` is very rapid, so there need not be any performance concerns over performing it frequently. Nothing is really gained by storing the result in a variable to avoid having to test a second time, and indeed that might not be a good idea, because the abilities of the interpreter might change during play (and particularly after restoring a game). It is also possible to access three version numbers: > phrase: glulx version number ... version number > > The version of the Glulx interpreter which the story is running in. This is a phrase, not a variable: it cannot be set by the story. On the other hand, it can conceivably change, if a story is saved mid-play on one platform and then restored on another. > phrase: {ph_glkversion} glk version number ... version number > > The version of the Glk interface used by the interpreter. This is a phrase, not a variable: it cannot be set by the story. On the other hand, it can conceivably change, if a story is saved mid-play on one platform and then restored on another. > phrase: interpreter version number ... version number > > The version of the interpreter itself which the story is running in. This is a phrase, not a variable: it cannot be set by the story. On the other hand, it can conceivably change, if a story is saved mid-play on one platform and then restored on another. Interpreter version numbers do not correspond to anything in the Glulx specification, and each interpreter uses its own numbering system. When Inform stories on Glulx respond to the command ``VERSION``, they normally produce a chubby banner of text like so: ``` transcript Exemplum An Interactive Fiction Release 1 / Serial number 260419 / Inform 7 v10.2.0+6X97 / D Identification number: A7A885DC-1187-4D85-9550-F2DC02B2BD90 Interpreter version 0.6.0 / VM 3.1.3 ``` So on that day, the story was running with `interpreter version number` equal to `v0.6.0`, and `glulx version number` equal to `v3.1.3`. > [!TIP] > On the whole, it is better not to use these version numbers. For example, real-number arithmetic only arrived in Glulx v3.1.2. But this test: > > if the glulx version number is at least v3.1.2: > > is not telling us whether we can safely use real numbers: we might be on a current interpreter which has opted out of that feature, or is on hardware making it impossible to provide. The safe way is: > > if the real numbers feature is supported: ## Basic text formatting ^^{proportional-spaced text} ^^{monospaced text} ^^{fonts: fixed-width / variable-width <-- variable-width <-- fixed-width} ^^{fonts: italic / bold / roman <-- italics <-- bold <-- roman} Inform does not go in for the use of fonts: a work of IF will be rendered with different fonts on different machines anyway, from tiny personal organisers up to huge workstations. However, it does allow for a modest amount of styling. Unusually, the features of this section work on both our virtual machines. > phrase: {phs_bold} say "[bold type]" > > This text substitution produces no text. It's used only for a side-effect: to make the text following it appear in bold face. `"[roman type]"` should be used to switch back to normal. Example: > > "Jane looked down. [bold type]Danger[roman type], the sign read." > phrase: {phs_italic} say "[italic type]" > > This text substitution produces no text. It's used only for a side-effect: to make the text following it appear in italics. `"[roman type]"` should be used to switch back to normal. Example: > > "This is [italic type]very suspicious[roman type], said Peter." > phrase: {phs_roman} say "[roman type]" > > This text substitution produces no text. It's used only for a side-effect: to return to ordinary Roman type after a previous use of `"[bold type]"` or `"[italic type]"`. Two other effects can be employed: > phrase: {phs_fixedspacing} say "[fixed letter spacing]" > > This text substitution produces no text. It's used only for a side-effect: to make the text following it appear with fixed letter spacing. In variable letter spacing, a lower case "m" is much wider than an "l", which is natural to the eye since it has been printing practice since the Renaissance. Fixed letter spacing is more like typewriting, and it is best used to reproduce typewritten text or printed notices; it can also be convenient for making simple diagrams. Example: > > "On the door is written: [fixed letter spacing]-J45--O-O-O[variable letter spacing]." > phrase: {phs_varspacing} say "[variable letter spacing]" > > This text substitution produces no text. It's used only for a side-effect: to return to ordinary letter spacing after a previous use of `"[fixed letter spacing]"`. Whichever effect we use, we should be careful to ensure that we return to normal – roman type and variable letter spacing – after any specially-treated text has been printed. Combining these effects (for, say, bold fixed-spaced lettering) is not guaranteed to work, though on some platforms it will. > phrase: say "[reverse mode]" > > This text substitution switches to "reverse" mode, where the foreground and background colours are reversed. > phrase: say "[reverse mode off]" > > This text substitution switches reverse mode off. > [!CAUTION] > Reverse-mode text is a feature of the Z-Machine. On Glulx, it is available only if the `text formatting feature` is `supported`. See [Glulx features and Glk features] for more on features. ## Coloured text ^^{coloured text} Inform's two virtual machines support colour differently, so this section will have be divided in two. **The Z-Machine**. Here there are just eight colours, which Inform represents in a kind of value called `basic colour`. The colours are: basic black basic red basic green basic yellow basic blue basic magenta basic cyan basic white These colour names are each prefixed with `basic` because authors often want to use colour-words like "red" in their own definitions or names of things. `basic red` is less likely to clash with such definitions. > phrase: {phs_colourletters} say "[(basic colour) letters]" > > Sets the foreground colour for text to a basic colour. > phrase: {phs_colourbackground} say "[(basic colour) background]" > > Sets the background colour for text to a basic colour. This is not the way to, for example, turn the whole play area background green; it only affects the background of subsequent printed text from the point at which the change is made. If lengthy text is then produced, the effect is likely to look ragged, since the background tint extends only under the letters themselves, not all the way to the right-hand margin. > phrase: {phs_defaultcolours} say "[default colours]" > > Resets both the foreground and background colours to their usual setting. The American spelling `say [default colors]` can also be used. **Glulx**. Direct styling of colours is not part of the Glulx/Glk specification, and there are principled reasons for that. Glulx was designed both for portability and also accessibility, with the needs of partially-sighted players kept always in mind. The model was intended to be more like that of a Kindle ebook, where it is (largely) for the reader to choose how the text will appear: the author of the book just writes the words. However, the Glk specification is extensible, and some though not all interpreters today do support an extension to Glk providing for coloured text. Not every author will want to use this feature. It is mainly intended for stories which will only be played on web browsers, where we can be fairly confident that the colours will come out as intended, and where (on good browsers, at least) accessibility features are provided so that readers can indeed choose how text appears to them. Still, in for a penny, in for a pound: if we do want colours on Glulx, we can have 16 million of them, because we have the entire 24-bit RGB colour range available, which provides far more shades than most people can actually distinguish. These colours are values of the kind `RGB colour`, where RGB stands for red-green-blue, because they are specified in terms of how much red light, green light, and blue light goes to make them up. RGB colour values in Inform look like those in the ubiquitous web-styling language CSS, or at least the commonest six-digit form of those. The notation is `#RRGGBB` using six hexadecimal digits. `RR` is the amount of red, from `00` (none) to `ff` (full on), and similarly for `GG` and `BB`: thus, `#000000` is black, and `#ffffff` is white. `#ff00ff` is an in-your-face fuchsia, `#ccff99` is a fairly zingy light lime, `#73264d` a muddy dark reddish-purple, and so on, and so on. Many websites provide handy tools for finding these hexadecimal values: a good one is [https://www.w3schools.com/colors/colors_picker.asp](https://www.w3schools.com/colors/colors_picker.asp). The phrases used for foreground and background colour selection are exactly as for the Z-machine above. > [!TIP] > `basic colour` values like `basic magenta` remain available on Glulx, so they can also still be used, and can also be converted: > > > phrase: (basic colour) as a/an/-- RGB colour ... RGB colour > > > > Converts a `basic colour` to an `RGB colour`. For example, `basic red as RGB colour` evaluates to `#ff0000`. > [!CAUTION] > Foreground and background colours on Glulx are available only if the `text formatting feature` is `supported`. See [Glulx features and Glk features] for more on features. ## The main screen and the status window For Inform, the _screen_ is the rectangular area in which an Inform story can display text or pictures. That rectangle is unlikely to be the whole physical screen which the user can see: maybe it's the Story panel in the Inform app, or a portion of a browser tab, or the play area in an IF app like Spatterlight, or even a tab in a Unix terminal app, partying like it's 1979. In short, the _screen_ is a rectangular space we can use. We cannot control its size, and must live within what we're given. That size might change at any time during play, for example if the player drags the corner of a browser window to resize it. What we can control is how the screen is divided up into panels called _windows_. These are not quite like the windows which Mac or Windows users are accustomed to. They do not necessarily have visible boundaries, and if two windows have positions which overlap, one has to be entirely inside the other. For many decades the conventional layout of an IF work has had just two windows: - A main screen area in which commands are typed, and replies scroll upwards. - A short status window on top, often drawn in contrasting colours, which holds some state-of-play information — a score, or a location, for example. This occupies a fixed position and does not scroll away. Since it is often just one line high, it is sometimes called the status line. This one does not receive keystrokes: it's for output only. That main window/status window arrangement is the screen layout used by default in Inform stories. Running on the Z-machine, it's almost the only layout possible, and although Glulx can support much more complicated setups, many Glulx stories continue to use it too. On both VMs, the following phrases can be used: > phrase: clear the screen > > This phrase clears both the main window and the status window (and, if a boxed quotation is being displayed currently, that as well). On Glulx, it is possible to create multi-window layouts with additional elements (e.g., graphical panels): those would not be cleared, so this phrase is best thought of as clearing the main textual part of the play area. > phrase: the screen height ... number > > The height of the screen in characters, that is, in lines of text. This includes the status line or lines. On Glulx, properly speaking, it's the height of the main window plus that of the status window. In the default page layout, this is the same thing, but it would be possible to construct more elaborate multi-window layouts (for example where a graphics area is above the text) where `the screen height` is measuring the height of the main textual part of the play area. > phrase: the screen width ... number > > The width of the status window in characters. Since the status window almost always runs across the whole width of the textual play area, this is in effect the screen width. > > > [!IMPORTANT] > > The reason that this phrase measures the status window, not the main window, is that the status window has a grid format in which all characters have equal width; in the main window, proportional text is usually used, so that a run of 100 letter `i`s might be the same width as 50 letter `w`s. In short, this can be used as an exact measurement when preparing material to be displayed on the status window, but is only a rough approximation of what fits below it. ^^{Custom status window columns} The default Inform usage for the status window is to have just a status line, that is, a single line at the top of the screen. This is generally used for the location, perhaps with a score or time of day: the variables `left hand status line` and `right hand status line` allow the content to be changed, since one is printed left-aligned in this line, and the other right-aligned. But more elaborate arrangements are possible. The window can have additional rows, and/or can accommodate a third, centred, column, using the following: > phrase: draw the status window with (table name) > > This phrase is intended for use within a rule for the `constructing the status line` activity, and redraws the status window using the contents of a table. The table can have any number of rows, and the status window will adjust its height accordingly — though of course players on smaller devices may not be pleased by a huge status window consuming their limited screen space. The table should have one to three columns: > > - If the table has 1 column, material in it is centred. > - If the table has 2 columns, column 1 is left-aligned and column 2 is right-aligned. > - If the table has 3 columns, they are left-aligned, centred, and right-aligned respectively. > > The contents of the table can be changed during play. Note that blank entries count as if they were empty text, i.e., they leave a blank area in the status window; in particular, a blank row in the table makes a blank line in the status window. > > > [!WARNING] > > On a narrow screen, it's possible for these columns to overlap each other, especially if all three columns are used. The table-based phrase above is convenient, but not compulsory, and the following low-level phrases may be useful in rules for the `constructing the status line` activity (see [Constructing the status line]) which go their own way: > phrase: set the status window to (number) row/rows > > Sets the status window to be this many rows high. > phrase: move the status window cursor to row (number) and column (number) > > Moves the cursor to the specified row and column number. Note that these begin with 1; the top left is (1, 1). > [!CAUTION] > While the descriptions of the phrases above refer to the main window, what they really mean by that is the "active window", that is, the one to which text is normally being output. In Inform's normal setup, that is always the main window, but some extensions allow this to be changed. ## Dividing the screen into windows On Glulx, but not the Z-machine, the screen can be divided up in many different ways. The windows into which it is divided must all be declared explicitly in the source text, except that three are declared for us already in Basic Inform. Readers of the previous section might have expected just two, the main window and the status window, but there's also an ephemeral window to hold boxed quotations, which sometimes pops up for a while and then scrolls away. That counts as an `IO window`, too. So by default, `showme the list of IO windows` produces: ``` transcript "list of IO windows" = list of IO windows: {main window, status window, boxed quotation window} ``` In fact, `IO window` has three subkinds, which represent the different sorts of window we might need: `text buffer window`, `text grid window` and `graphics window`; and it is itself a kind of `abstract object`, which is a kind of `object`. Thus we have: - `object` ▸ `abstract object` ▸ `IO window` ▸ `text buffer window` ▹ main window, boxed quotation window - `object` ▸ `abstract object` ▸ `IO window` ▸ `text grid window` ▹ status window So we could write, say, `if W is a text grid window` to test which kind the window `W` is. But it's also sometimes convenient to use a property of `IO window` called `glk window type`. If we run: repeat with W running through IO windows: say "[W]: [window type of W]."; then we get, assuming we haven't created any extra windows, ``` transcript main window: text buffer window type. status window: text grid window type. boxed quotation window: text buffer window type. ``` So, what goes on here? - The `main window` is a `text buffer window`. This is where the bulk of textual input and output goes on. This is where room descriptions are printed, where commands are typed, and so on. Being a `text buffer window` means that characters (letters, digits and such) do not have to appear on grid positions. Glk is free to write this text in a pleasantly legible font in which a "w", for example, is wider than an "i". - The `status window` is a `text grid window`. This is traditionally a bar across the top line or two of the screen, which is a sort of summary of the situation. In an IF story it might show the current room name, and/or the score, number of turns played, or time of day. Being a `text grid window` means that text appears on it at regularly-spaced grid positions, rather like typewritten letters. Here a "w" will be the same width as an "i", or a space, or anything else. - The `boxed quotation window` is a `text buffer window`. This can overlay the `main window` for a time, and was historically used to display an apposite quotation, which is why it's so named. (See [Displaying quotations].) There's also a third glk window type, `graphics window`, but in the default setup stories are pure textual and no window exists with this type. That doesn't mean that the main window can't display pictures, or emoji: but only a `graphics` window can plot arbitrary shapes or designs. Inform doesn't provide phrases for doing that in its basic installation, but extensions do. > phrase: {ph_glkwindowheight} height of (IO window) ... number > > The current height of the window. For an open `graphics window` this is measured in pixels, and for `text grid window` or `text buffer window` in characters, though in the latter case the value will only be approximate because characters vary in size. > > If the window is closed, this returns 0 whatever the type. > > Unlike most phrases to do with IO windows, this one works on the Z-machine as well as Glulx. > > > [!WARNING] > > A known bug in the MacOS Inform app's Story panel version of Glk means that it reports `text buffer window` widths in pixels, not characters. That likely affects the story only when running in the app, not when Released. > phrase: {ph_glkwindowwidth} width of (IO window) ... number > > The current width of the window. For an open `graphics window` this is measured in pixels, and for `text grid window` or `text buffer window` in characters, though in the latter case the value will only be approximate because characters vary in size. > > If the window is closed, this returns 0 whatever the type. > > Unlike most phrases to do with IO windows, this one works on the Z-machine as well as Glulx. > > > [!WARNING] > > A known bug in the MacOS Inform app's Story panel version of Glk means that it reports `text buffer window` widths in pixels, not characters. That likely affects the story only when running in the app, not when Released. The basic installation of Inform does not contain phrases to open or close windows. The `main window` and `status window` are open throughout play, and the `boxed quotation window` is opened automatically if needed. So Inform does not, out of the box, provide ways to open or close other windows at other times. This is not because Glk can't do that: Glk contains elegant mechanisms for creating a cascade of Glk windows, panelling the screen in a variety of different ways. But since most users never need that, the functionality is left for extensions to provide for. In particular, see Flexible Windows. However, even an unextended Inform allows the following: > phrase: {ph_glkwindowclear} clear (IO window) > > If the window is closed, nothing happens. If it is open, then what happens depends on the window type. A text grid is erased to a grid of spaces. A graphics window is filled with its background colour. Exactly what happens to a text buffer depends on the platform. In most modern situations that too will be erased, but a story playing in a so-called dumb terminal may do something more primitive, such as throwing many blank lines of output. > > Unlike most phrases to do with IO windows, this one works on the Z-machine as well as Glulx. Thus, `clear main window` and `clear status window` behave similarly on both platforms. > phrase: {ph_glkwindowfocus} focus (IO window) > > When a `say` text is printed, which window is it printed into? The answer is whichever window has the _focus_. That's normally the `main window`, of course, but this phrase allows a switch. (For example, this is used when updating the status window.) The window must be open, or a run-time problem will be thrown. > > While it is technically legal to focus a `graphics window`, any text sent to it will be humanely destroyed, so in practice this phrase should be used only with `text grid windows` or `text buffer windows`. > phrase: {ph_glksetcursor} set (IO window) cursor to row (number) and column (number) > > The window must be open and must be a `text grid window`, or else run-time problems are thrown. The _cursor_ for such a window is the position where the next character is printed, and like all cursors, it moves forward with each printing. > > The top left position in a grid is row 1, column 1. For example, if the grid is, say, 80 characters wide by 3 characters high then the top right is row 1, column 1, and the bottom right is row 3, column 80. If the row and column supplied lie within the rectangle, that's where the cursor moves to. If not: > > - if the column is a negative value or zero, it's rounded up to 1, the leftmost position; > - if the column exceeds the width of the grid, the cursor moves to column 1 on the _next_ row; > - if the row is a negative value or zero, a run-time problem is thrown; > - if the row exceeds the height of the grid, the cursor is allowed to occupy this off-the-bottom position, but any text printed there is thrown away without being displayed. IO windows have two `number` properties, `rock number` and `glk window handle`: see the Glk reference documentation for what they mean. `glk window handle` is what the Glk spec calls the window ID, and it therefore exists only for open windows. An IO window has handle 0 if and only if it is closed. > [!NOTE] > The Z-machine supports very little of the above, so a project for the Z-machine cannot use it. There _is_ still a kind called `IO window`, but it is a fixed enumeration, not an abstract object: it has just two values, `main window` and `status window`. ## Pausing for keystrokes or commands ^^{Key presses} Inform stories ordinarily pause at the same point in each turn to wait for the player to type something which will be parsed as a command and turned into actions. But it's possible to pause at other times, or to get typed input for other reasons. The following phrases work on both Glulx and the Z-machine. > phrase: {phnextpressedkey} next pressed key ... unicode character > > This phrase pauses and waits for the player to press a single key. For more on the `unicode character` kind, see [Unicode characters]. In particular, see the list there of named values for keys which do not correspond to symbols as such: navigation keys like `page up key`, or function keys like `f5 key`. > phrase: {phnexttypedline} next typed line ... text > > This phrase pauses and waits for the player to enter a whole line of text followed by the enter key. It does not parse the player's response, and simply returns what was typed in (without a final newline character). Inform includes a few utility phrases to handle pausing the game and waiting for the player to respond. > phrase: wait for any key > > Wait for the player to press (almost) any key. It actually excludes the up/down/page up/page down keys in order to let the player read the transcript without the story progressing. > phrase: wait for the space key > > Wait for the player to press the space or enter/return key. > phrase: pause the game/story > > This phrase will say "Please press SPACE to continue." and then wait until the player presses the space key (or enter/return); after which, the screen is cleared, and then play resumes. > > Note that this is done by following the `standard pause the game rule`, and that the text "Please press SPACE to continue." is response (A) of that rule, and can therefore be changed as desired. > phrase: stop the game/story abruptly > > Mostly useful in Basic Inform projects, this phrase will tell the virtual machine to stop immediately. It does not invoke any of the end of play systems — the `shutdown rules`, the `when play ends` rules, and so on. # Events and Hyperlinks ## Glk events An Inform story is always in control of what it outputs. It decides what to say, and when to say it. Input is not as predictable. Somewhere outside of the story is a player, pressing keys or clicking on links. The Glk input/output system handles those situations as _events_. Events are values, of the kind `Glk event`: and being values, they can be put into variables, they can have phrases or rulebooks act on them, and so on. Events come in quite a variety, but are sorted out by type: > phrase: {ph_glkeventtype} type of (glk event) ... glk event type > > Every `glk event` falls into one of (currently) 10 types, which are the possible values of `glk event type`. Besides having a type, events usually have details attached. For example, if `E` is the event arising when the player presses the X key, then `type of E` will be `character event`, and `character value of E` will be the Unicode character for X. > [!CAUTION] > Events can really only be handled by the phrases appropriate for their type. For example, taking `character value of` what turns out to be a `volume event` would make no sense. But Inform would compile this happily enough: it wouldn't go wrong until run-time, when a run-time problem would result. Here is the complete list of event types: Value of `glk event type` | Meaning ---------------------------- | --------------------- `null event` | Nothing happening. `character event` | A key has been typed. `line event` | A line of text ending with a RETURN or ENTER has been typed. `hyperlink event` | A web-style link has been selected. `mouse event` | A mouse has been clicked, or a touch-screen touched. `screen resize event` | The screen has been resized. `graphics window lost event` | A graphic window needs redrawing from scratch. `timer event` | A timer has run out. `sound notification event` | A sound effect has finished playing. `volume event` | A change in sound volume has completed. Note that some of these are our own fault, so to speak. If we set a timer to run for, say, ten seconds, it will in due course lead to a `timer event`. The story deals with Glk events using the `glk event handling rulebook`, which is a `glk event type based rulebook`. This rulebook has a variable called `event`, which contains the full details within it, and has the kind `glk event`. The story can react to Glk events as they arise by providing rules for this rulebook. For example, this logs each event as it comes in: A glk event handling rule: say "Newsflash: [event]." Exactly what events come in may depend on which Glk interpreter is running the story, and what capabilities it has. For example, on the MacOS Inform app the first event logged when the story starts up is: ``` transcript Newsflash: screen resize event. ``` But on the Parchment website interpreter, we find: ``` transcript Newsflash: graphics window lost event. Newsflash: screen resize event. Newsflash: graphics window lost event. ``` So it may be advisable to remember that no two implementations of Glk are exactly the same, and no two environments for the story have exactly the same capacities. Typed commands do produce the same event on all platforms, though: ``` transcript > WAIT Newsflash: line event ("wait") in the main window. Time passes. > LOOK Newsflash: line event ("look") in the main window. ``` The Newsflash rule ran twice there, once after each typed command, with two different values of `event`. But though they were different values of the `glk event` kind, they both had the same type, `line event`. Event types are useful because most of the time we want to write a rule applying to all events of a given type. This is why the rulebook is based on `glk event type` and not `glk event`. So, for instance: A glk event handling rule for a timer event: say "Time out! [event]." Events of different event types work differently, and have to be handled in different ways. The next few sections cover how to handle particular event types, but there is one more phrase which can usefully be applied to glk events of several different types. What these have in common is that they take place in or on a given window. Inform provides the adjective `windowed` to determine whether a `glk event` (or a `glk event type`) is associated with a window: at present the windowed events are the character events, line events, hyperlink events and mouse events. > phrase: {ph_glkeventwindow} window of (glk event) ... IO window > > For a windowed event, this gives the window where the event is taking place. If used on events which are not windowed, a run-time problem is issued. So for example, the following uses the phrase safely: > > A glk handling rule for a windowed glk event type: > if the window of the event is the status line: > say "Status line update! [event]." ## Character and line events There are times when individual key-presses matter — for example, if the user presses a cursor key to navigate a menu, and we have to react immediately — and then there are times when we don't care what is being typed until an entire command has been entered. That's why there are two different types of keyboard event: `character event` and `line event`. * A `character event` is the pressing of a key, or strictly speaking, the input of a character from the keyboard. If the user presses and releases the shift key, for example, that won't generate a character event. Typing the 7 key will do, however, as will typing shift-7, which on most keyboards will lead to a character event with the ``&`` symbol. Most function keys other than shift or alt will result in a character event. * A `line event` marks when a complete line has been fully typed in, and the user has indicated that it's finished by pressing the RETURN or ENTER key. (That end-marker does not become part of the text of the command.) ### How to request these events Glk sends us these events only if we have requested them. By default, an Inform story never requests character events. Traditionally, turn-by-turn command parser stories only care about entire commands, not individual keypresses. If the player is typing ``EAT CAKE``, we don't want to receive a stream of character events (E, A, Y, delete, T, space, ...). An Inform story requests a line event only when it has, in effect, halted waiting for a command to be typed in. But since Inform stories usually print quickly and spend most of their time waiting for player input, this means they are almost always requesting line events. But you can also request them at other times: see [Keyboard input]. ### Details for these events Both character and line events are tied to windows, because players who type are always typing into whichever window currently has the focus. Given a character or line event, `window of (glk event)` can be used to find which window it came from. > phrase: {ph_glkeventcharactervalue} character value of (glk event) ... unicode character > > For a character event, this returns the character in question. For any other event, a run-time problem is issued. > phrase: {ph_glkeventtextvalue} text value of (glk event) ... text > > For a line event, this returns the text of the line. For any other event, it throws a run-time problem. ### Fictitious character and line events Some types of event can be created even though they haven't happened yet, and the two keyboard types are a case in point. It may seem peculiar to create fictitious Glk events, but it turns out be very useful in order to, say, treat mouse clicks as if they were keypresses or commands, as we shall see. Here are the phrases to create such events: > phrase: {ph_glkcharacterevent} character event with (unicode character) in (IO window) ... glk event > > This produces an event value exactly like that which would have been generated by glk if a key with the given character had been typed in the given window. > > The `in (IO window)` can be omitted, in which case the event is in the `main window`. > phrase: {ph_glklineevent} line event with (text) in (IO window) ... glk event > > This produces an event value exactly like that which would have been generated by glk if the given whole command had been typed in the given window. There's no necessity for the text to be in upper case, or for that matter in lower case. These all produce different events: > > line event with "GATHER YE ROSEBUDS" in main window > line event with "GATHER YE ROSEBUDS" in main window > line event with "gather ye rosebuds" in main window > > Though the Inform command parser would treat all three commands just the same, that all happens much higher up than in this input-output layer. The texts are different, so the events are different. > > The `in (IO window)` can be omitted, in which case the event is in the `main window`. ## Timer events ^^{timer events} Glk contains a real-time timer. This is more like a pulse than a magazine subscription: it is intended for regular pings at short intervals — for example, to move the game state on every five seconds — rather than to make something happen after an hour of play. Bearing in mind that a player might save the game in between pulses of a timer, and that we cannot reliably assume that the restored game would continue the timer at the same exact moment, it's probably best to use this feature for rapid updates. Glk has just one timer, and it is either running or not: and even so, the feature is available only if `timers feature` is `supported`. When the timer pings, a timer event is issued. ### How to request these events Glk sends us these events only if we have requested them. By default, an Inform story never requests character events. > phrase: {ph_requesttimer} request timer events every (N - number) milliseconds > > `N` should be positive. This tells Glk to send timer events once every `N` milliseconds until further notice, that is, until we either `cancel timer events` or use this phrase again with a different frequency. Does nothing if the `timers feature` is not `supported`. > phrase: {ph_canceltimer} cancel timer events > > Causes Glk to stop sending timer events, if in fact it was. Does nothing if the `timers feature` is not `supported`. ### Details for these events None, really. For example: A glk event handling rule for a timer event: say "Ping! [event]." prints back only ``Ping! timer event.``, because there are no other details attached to the event. It is not associated with any window, and carries no information. ## Hyperlinks "Hypertext" is a term coined in 1965 for a text which contains "hyperlinks" to other passages of text. This idea, long nascent, led directly to technologies like _The Interactive Encyclopaedia System_ ("HyperTIES", 1983), the creative playground _HyperCard_ (1987), the world wide web (1989), and _Wikipedia_ (2001). In all these systems, clicking on a "linked" button or phrase moves the reader to a new part of the text. But Inform stories are interactive, and non-linear. They are not divided up into pages in the way that Wikipedia, for example, is. In an interactive story, links are instead active gadgets. Clicking on them does something to change the state of the story, and that then has the effect of moving the reader along. Whereas links in Wikipedia are almost all "go to new page X", Inform links might want to do all sorts of things: behave like commands, behave like typed characters, behave like rules firing, and so on. Inform's system for handling hyperlinks aims to make them easy and flexible to use, but at the same time to work in a way which extensions can build on. ### The story of a hyperlink This is the story of a typical hyperlink, which we can tell at three levels. **A top level explanation**. This is how things look to the author of an Inform story: Professor Chromo's Paint Machine is in the Laboratory. "The sinister machine hums, just waiting for someone to press the [link to follow splash rule]big red button[end link]." This is the splash rule: say "The world goes red, or anyway the part of the world nearest the paint-throwing machine." The idea here is that the player sees that the words "big red button" are highlighted in some way, and may want to click on them. If so, the `splash rule` will run. **A mid-level explanation**. Under the hood, this is how that same hyperlink looks inside Inform's run-time facilities. When Inform says `"[link to follow splash rule]big red button[end link]"`, it generates a value of a kind called `hyperlink token` to represent the "destination" of the link: that is, to represent what should happen if the link is clicked on. This is called a token it represents a value which is used when creating the actual hyperlink and which is returned when the player clicks on it. A hyperlink token consists of both a "tag", meaning what to do, and a "value", meaning what to do it with. In this case, the hyperlink token is a combination of: - the tag `rule hyperlink`, which is an instance of the kind `hyperlink tag`, with - the value `splash rule`, which is an instance of the kind `rule`. Inform provides four built-in `hyperlink tag` possibilities, of which `rule hyperlink` is only one. The others correspond to different ways that links can cause effects, and will come up later. Because Inform authors and extension writers can create new `hyperlink tag` values, this system is flexible enough to be built on in new ways. If the tag is clicked on, Inform receives a `hyperlink event` from Glk and handles it. What it does is to retrieve the hyperlink token and take the necessary action — in this case, to run the rule. **A low-level explanation**. Still further under the hood, from the point of view of the Glk I/O system, all that happens is that Glk is told that certain printed words are part of a link with a given identification number — say, 17. If the player ever clicks on those words, Glk sends a `hyperlink event` with number 17 attached to it. Glk never knows what this number means, and never needs to know. ### Making hyperlinks So, then, whereas Inform authors need to write handling rules to take care of other types of Glk event, there is no need to think about a `hyperlink event` because Inform takes care of it automatically. To create a link, all that is necessary is to use `[link to ...]` and `[end link]` text substitutions: > phrase: say "[link to (hyperlink token)]" > > Starts a hyperlink with the given "destination", that is, with the given instruction on what to do if the link is clicked or tapped. No text will be printed yet, but anything said after this substitution will be part of the hyperlink. The link will continue until the next `[link to ...]` or `[end link]`, either of which will end it. So it is impossible for one piece of hyperlinked text to contain another. > phrase: say "[end link]" > > Ends the current hyperlink. Any subsequent printed text will just be regular text. The four forms of link built in to Inform are: - **Command replacement**. For example, say "Your eyes stray to the [link to command `PRESS BUTTON`]pretty red button[end link]."; > phrase: say "[link to command (text)]" > > A link given this outcome replaces an entire pending line input with the specified text and then submits it, as if the player had typed it themselves and then pressed enter. The text must not contain a line break: if it does, a run-time problem will be issued. - **Command appendment**. For example, say "Your eyes stray to the [link to type `BUTTON`]pretty red button[end link]."; > phrase: say "[link to type (text)]" > > A link given this outcome suspends line input, adds its text to the current line input, and then resumes line input. It's as if the player had typed the text in question. The text must not contain a line break: if it does, a run-time problem will be issued. - **Keypress**. For example, say "[link to press space]Press SPACE to begin.[end link]"; wait for the space key; makes clicking on the text "Press SPACE to begin" as good as pressing SPACE. > phrase: say "[link to press (unicode character)]" > > A link given this outcome issues a `character event` with the specified unicode character. - **Rule or rulebook**. An example with a rule was given earlier. The same mechanism can just as easily link to a whole rulebook: When play begins: say "Wow! Just look at the [link to follow sky rules]clear blue sky[end link]."; The sky rules are a rulebook. Sky rule: say "So blue!". > phrase: say "[link to follow (rule)]" > > A link given this outcome follows the specified rule or rulebook. Any result of the rule (success or failure) is ignored. ## New types of hyperlink Inform's system of hyperlinks is designed to be _incomplete_. The forms of link above will cover many common needs, but inevitably authors and extension writers will want to create others. As a first example, this section will create a sort of examine-this hyperlink: one where clicking on the link causes something in the room to be examined. Of course, the built-in system can already imitate this, more or less: Professor Chromo's Paint Machine is in the Laboratory. "The sinister machine hums, just waiting for someone to press the [link to follow examine-me rule]big red button[end link]." The big red button is part of the Paint Machine. "So shiny!"; This is the examine-me rule: try examining the big red button. But this is clumsy. What we want is this: Professor Chromo's Paint Machine is in the Laboratory. "The sinister machine hums, just waiting for someone to press the [link to examine button]big red button[end link]." The big red button is part of the Paint Machine. "So shiny!"; Firstly, since this will mean a new type of hyperlink, we will have to assign a fresh tag to hyperlinks of this type: Examination hyperlink is a hyperlink tag. Now we need a way to create hyperlinks of this type: To say link to examine (X - thing): say link to hyperlink token of examination hyperlink with X. Internally, a hyperlink token consists of a _tag_ plus (usually) a _value_. Here, the tag was `examination hyperlink` and the value was `X`, except that of course in the case of the Paint Machine, that will end up being the object `big red button`. We've used one of these creation phrases: > phrase: hyperlink token of (hyperlink tag) for/of/with (value) ... hyperlink token > > Creates a new hyperlink token by combining a tag with a value. > > > [!CAUTION] > > Hyperlink tokens can contain values of many of the kinds found in Inform, but there are exceptions (such as `real number`), and authors must be careful not to try to put an ephemeral value into a hyperlink, such as some local variables. It is not enough for the value to exist when a hyperlink is created: it must still exist when the link is clicked. This phrase produces a run-time problem if it is asked to attach such a value to a token. > phrase: hyperlink token of (hyperlink tag) > > Creates a new hyperlink token which has a tag, but no value. We want to give Inform the ability to say tokens like this: Hyperlink printing rule for examination hyperlink: say "examination hyperlink token for [value of current hyperlink token as a thing]". The `hyperlink printing rulebook` is run whenever Inform wants to print out a hyperlink token as text. There's actually not very need to do this, except perhaps as a debugging aid (for example, adding the line `showme the outcome` to a handling rule like the ones below); but in general all Inform values ought to be sayable whenever possible. In this rulebook, the variable `current hyperlink token` is the token to be printed: the focus of the rulebook is just the tag part, which is why the rule above applies to all hyperlink tokens whose tag is `examination hyperlink`. By convention, though it is not compulsory, the textual representation produced by the `hyperlink printing rulebook` should be Inform source text which, if used somewhere in the story source, would recreate the same token. Now, the rule above produces text such as ``examination hyperlink token for big red button``: so it would be good to be able to recognise that... To decide what hyperlink token is examination hyperlink token for (X - thing): decide on hyperlink token of examination hyperlink with X. Lastly, Inform needs to know what to do when a link of this type is clicked. In general, when any link is clicked, Glk sends a `hyperlink event`, but Inform handles this by then following the `hyperlink handling rules`. The basis of this rule book is the hyperlink tag of the event. To handle our new action links, all we need to do is write a new rule for this rulebook: Hyperlink handling rule for examination hyperlink: let the item be the value of outcome as a thing; try examining the item; rule succeeds. This rulebook has a variable called `outcome`, which is the token belonging to the link which was clicked. In the same way that an address in a link on a web page tells a web browser where to go next, the token contains information within it which tells the handling rule what should happen. Firstly, it contains a tag saying broadly what kind of link this is: > phrase: tag of (hyperlink token) ... hyperlink tag > > Extracts the hyperlink tag from a token. For example, in the body of the `Hyperlink handling rule for examination hyperlink` above, `tag of the outcome` would always be `examination hyperlink`. > phrase: value of (hyperlink token) as a (name of kind of value K) ... K > > Extracts the value out of a hyperlink. > > > [!CAUTION] > > This must be used with great care so that the kind of value matches the kind used when the token was created, since Inform cannot check that the value is of that actual type. For example, if the token `T` was created by `hyperlink token of command replacement with "EXAMINE WALL"`, and then Inform is later asked for `value of T as an object`, a crash will likely ensue. So, for example, this rule would not be safe: Hyperlink handling rule: showme value of the outcome as a thing. This rule casually assumes that the value attached to the hyperlink clicked is a thing, and it might not be. On the other hand, this _would_ be safe: Hyperlink handling rule for examination hyperlink: showme value of the outcome as a thing. because now the rule applies only to links tagged as `examination hyperlink`, and we know that all of those links have tokens with things attached. In effect, hyperlinks bypass and sometimes replace the usual way that commands are typed in. Because of that, they work best if the usual command prompt is removed. Inform normally prints the prompt each time it waits for keyboard input, but that means it's still present if the player clicks on a link which enters a command instead, like a question forever left unanswered. So stories making heavy use of hypertext normally remove the prompt, like so: When play begins: now the command prompt is "". On the other hand, that may mean that the textual transcript of play contains no evidence that a command has taken place at all. So this amendment might be wise: Hyperlink handling rule for examination hyperlink: let the item be the value of outcome as a thing; say "(examining [the item])[command clarification break]"; try examining the item; rule succeeds. Which would result in a transcript like so: ``` transcript Churchyard You can see a sturdy oak here. (examining the sturdy oak) You see nothing special about the sturdy oak. ``` Although no prompt or typing is visible, it's now clear that the story was given a command, and what that command was. ## Suspending text input while handling events ^^{Suspend and resume text input} Sometimes when a Glk event arrives we will want to respond. But how can we do that if we're currently waiting for the player to submit line input? We cannot simply print text; the interpreter may even crash if we try. The Glk interface allows us to instead _suspend_ text input. We can then output whatever we like, before we resume text input. > phrase: {ph_suspendtextinput} suspend text input > > Suspends any text input in the currently active window. The phrase option `without input echoing` can be used to prevent the partially typed input from being printed into the window. > > > [!CAUTION] > > By default if we suspend line input then whatever the player has already typed will remain visible. Altering that can produce quite a messy transcript. It is to avoid this that the `without input echoing` option is provided here, but note that a special use option must also be enabled for this to work properly: > > > > Use manual line input echoing. > phrase: suspend text input in (IO window) > > Suspends any text input in the specified window. Again, this supports the `without input echoing` phrase option. > phrase: {ph_resumetextinput} resume text input > > If text input in the currently active window was suspended, this resumes it. If not, this does nothing. > phrase: resume text input in (IO window) > > If text input in the given window was suspended, this resumes it. If not, this does nothing. Suspended character input is simple enough, but what about line input: what happens to what the player has already typed? This can be accessed and even changed, provided input is suspended: > phrase: current line input of (IO window) ... text > > Extracts the current line input of a suspended Glk window and returns it to the player. > phrase: set the current line input of (IO window) to (text) > > Updates the current line input of a suspended IO window. A run-time problem is issued if the window has either never requested line input, or is currently not suspended. ## Other Glk event types Glk supports several other event types, though most will be of limited use to Inform authors. Extensions may make more use of them: at present, core Inform does not. * A `screen resize event` is generated whenever the size of the interpreter window is changed. Inform has a screen resize event handling rule that redraws the status window because if the width has changed then part of the status window might have been erased, or it might not be correctly aligned anymore. * Similarly a `graphics window lost event` is generated when a graphics window needs to be redrawn. * A `mouse event` can be generated when you click in a grid window or graphics window. * The `sound notification event` and `volume event` types both concern advanced sound channel features which extensions can implement. # Figures, Sounds and Files ## Beyond text ^^{Glulx: required for multimedia} ^^{Z-machine: no support for multimedia} ^^{virtual machine: multimedia support} In this chapter, we explore a number of ways to go beyond the traditional text-only, one-story-file-only model for IF. These relatively exotic features are more demanding of the interpreter which a player uses than a plain text story file would be. They can only be used if the project is being compiled to the Glulx story file format (see the Settings panel for the project), and even then, the player will need to have a good Glulx interpreter – one which is reasonably up to date and well-written, that is – to be sure of everything working as intended. ## How IF views pictures ^^{figures <-- pictures <-- graphics}^^^{figures <-- images} Looking around a bookshop, perhaps half of all the books published have illustrations. The proportion may be lower for novels, but if we count maps or other occasional diagrams, even the fiction section turns out to be surprisingly pictorial. Illustrations do not suit every book, but they are an option we would like to have available. In the cultural history of IF, graphics in text adventures have sometimes been looked at with suspicion. Mostly this is because attempts in the 1980s were not very successful, because computer graphics were so poor then (by modern standards). It may be that some people also felt that the takeover of computer games by graphical interfaces was the death knell of IF. But pictures are now rendered in superb quality by computers, and the death of IF turned out to be an exaggeration, so it is time to move on. Whether to have illustrations ought to be an artistic choice, like whether to include a romantic sub-plot or how much of the back story is revealed. But there are practical considerations too. The most successful illustrated books are those whose pictures are well-chosen, have a sense of design to them, and above all are consistent. Consider how much worse off *Winnie the Pooh* would have been if a selection of random teddy-bear drawings had been used, instead of E. H. Shepherd's beautifully conceived world; or a cookery book in which the recipes are all photographed at different distances and light levels. IF writers may want to look for collaborators with a visual eye, just as most novelists do not draw their own illustrations. Another consideration is that displaying images is more complicated for computers than displaying text. Not all devices can show pictures (consider handheld gadgets) and if they do, they may use different colour ranges or resolutions. So IF with pictures is always just a bit less portable than IF without, and because of that we must next look again at IF story file formats. ## Gathering the figures {kind_figurename} {FIGURES} ^^{figures: placing in materials folder} ^^{figures: formats allowed} ^^{materials folder: figures}^^^{materials folder <-- files (compiling): materials folder} Inform provides basic support for displaying pictures and leaves more exotic effects for Extensions to provide. But either way, for reasons explained in the previous section, **we can only have pictures if the Settings for the project are set to the Glulx story file format**. Inform calls these pictures _figures_, following the usual Inform analogy with books. We will think of our work of IF as being like a mostly textual book which in broken up with illustrations here and there – Figure 1, Figure 2, and so on. These might be used to mark each new chapter of the plot, or each new location: whatever the author would like. So the first thing we need to do is decide when pictures should appear. The second thing to do is to get hold of the pictures we want to use. These might be photographs, or artwork, or diagrams: anything, really, but we will need them to be in either JPEG or PNG format. Inform does not itself try to be an image editor, or an artwork program – there are many such programs already which do these things much better than Inform could. The pictures then need to be put in a special place where Inform can reach them. Suppose the Inform project is called Example.inform. Then we need to create a folder alongside it called `Example.materials`, and create a further folder inside that called `Figures`. The actual images go inside `Figures`. So we might then have files like so: ``` Example.inform Example.materials Figures Woodlands.png Blackberry.jpg Red Admiral Butterfly.png ``` The `.materials` folder for an Inform project will turn out to have many other uses in the chapter on [Publishing], and will be explained further there. ## Declaring and previewing the figures {PM_PictureDuplicate} {PM_PictureNotTextual} ^^{figures: declaring} ^^{defining: figures} ^^{defining: previewing} ^^{Contents page of Index panel+ui+} ^^{user interface: Index panel: Contents page} ^^{Index panel+ui+: Contents page} Inside Inform, the source text for a project always tries to avoid talking about filenames – we need a better way to refer to the individual figures. We do this by declaring each figure with a sentence like the following examples: Figure of Woodlands is the file "Woodlands.png". Figure 2 is the file "Red Admiral Butterfly.png". Figure names can consist of any text provided that text starts with the word `Figure`. So `Figure 3 – Woodlands`, for instance, or even `Figure W` would have been just as good as `Figure of Woodlands`. Books tend to number figures, but then, in a book the order in which they appear is known in advance – which might not be true in IF. The file names must be exactly those used in the Figures folder. We need not declare every image kept there, but those we don't declare – remember Blackberry.jpg? – cannot be displayed. We can preview the stock of figures by going to the table of figures in the Contents index for a project (once the project has been built, that is, so that its index is up to date). This preview shows thumbnail forms of the pictures, the names, the formats and the image sizes in pixels. A warning triangle is shown for any images in the wrong format, or which are missing from the Figures folder. ## Displaying the figures ^^{figures: displaying} ^^{blorb file <-- files (compiling): blorb file} Inform's basic picture support simply allows figures to be shown at particular times. Once seen, they scroll away, just as text does once it has been printed. These pictures are really part of the stream of narrative. (If we would like icons or other images to be permanently present on screen, and divide the screen up in pictorial ways to achieve interesting layouts, we need to use special extensions to access Glulx's more exotic features.) Displaying a picture is therefore like printing some text. Rather than say "The woodlands stretch from here to the horizon."; we would use: > phrase: {ph_displayfigure} display (figure name) > > This phrase causes the figure to be displayed in a way visible to the player. If the option `one time only` is used, it will have no effect if the figure has been displayed before. Example: > > display the Figure of Woodlands; Once again, note that the `display` phrase does nothing unless the Settings for the project are set to the Glulx story file format. When a Glulx work is released as a blorb (the default setting for the way releases occur: see the chapter on [Publishing]), all the images used are automatically included. ## Recorded sounds {kind_soundname} {SOUNDS} ^^{sounds <-- audio <-- music} ^^{sounds: formats allowed} Inform also supports the playing back of recorded sounds, which might be anything from a three-second sound effect for a creaking door to an epic orchestral symphony. **Sound support is very newly added to the system and work is still in progress. In particular, sounds are not played by Inform for OS X (although it does produce valid blorbed Glulx story files), though they should be audible from within the Inform application for Windows.** Once again, sound effects are supported by Inform 7 only on the Glulx platform, and even then we must be prepared for the fact that not all interpreters will be able to play them back. We must also bear in mind that a sound recording is a large pile of bits, and that adding any kind of sounds will greatly increase the size of the Blorb file for the released Glulx story file. The sound files provided must have one of two formats: AIFF or Ogg Vorbis. AIFF is a traditional format in the recording industry, though it is more familiar to Mac OS X users than Windows users. It is uncompressed, giving what can be excellent audio quality, but at the cost of sometimes enormous file sizes – perhaps as much as 10 MB per minute, though this can be greatly reduced by lowering the sampling frequency, and halved again by dropping from stereo to mono. Except for very short sound effects, we recommend using **Ogg Vorbis** instead. This is a compressed format whose file sizes will typically be more like 1 MB per minute. Inform uses Ogg Vorbis as the only format safe from licensing and patent disputes. (We would very much have liked to provide MP3 support, but this is no longer legally possible for free software.) Support for Ogg Vorbis is not built in to either Windows or Mac OS X, and any sound recording you make will probably have to be made first to another format (perhaps AIFF or WAV), and then converted. See [xiph.org/vorbis](https://xiph.org/vorbis/) for encoding software which can convert from other sound formats to Vorbis. Lastly, it must be remembered that recording industry bodies are very hostile to established copyright law covering fair use, parody, quotation of insubstantial passages, etc., when it comes to mixing or using commercially released music. They are well-resourced and highly litigious. If you use sound effects not originated by yourself, you do so at your own risk, even if what you do is perfectly legal on any reading of the statutes. ## Declaring and playing back sounds {PM_SoundDuplicate} {PM_SoundNotTextual} ^^{sounds: declaring} ^^{defining: sounds} ^^{sounds: placing in materials folder} ^^{materials folder: sounds} Sound effects are accommodated on the same basis as illustrations. The relevant media files need to be placed in a subfolder of the project's `.materials` folder, but this time called Sounds rather than Figures, so for instance: ``` Example.inform Example.materials Figures Woodlands.png Blackberry.jpg Red Admiral Butterfly.png Sounds Rustling leaves.ogg ``` Again, these must be declared in the source text: Sound of rustling leaves is the file "Rustling leaves.ogg". And they can be played using a special phrase: > phrase: {ph_playsf} play (sound name) > > This phrase causes the sound effect to be played. If the option `one time only` is used, it will have no effect if the sound effect has been played before. Example: > > play the sound of rustling leaves; ## Providing accessibility text ^^{accessibility text for figures and sounds} ^^{text: accessibility text for figures and sounds} ^^{figures: accessibility text} ^^{sounds: accessibility text} It's conventional for web pages to provide "alt-text" for significant images displayed, so that partially sighted or blind users can get an idea of what is being shown. Inform allows figures to be given these short descriptions like so: Figure 2 is the file "butterfly.jpg" ("A red admiral butterfly."). As we'll see, the same can be done for the cover image: Release along with cover art ("A cathedral at sunset."). And also for sounds: Fugue is the file "Bach.ogg" ("A church organ playing a Bach fugue."). ## Some technicalities about figures and sounds ^^{blorb file} ^^{values: figures as values} ^^{figures: as values} ^^{|figure name} ^^{values: sounds as values} ^^{sounds: as values} ^^{|sound name} ^^{resource IDs} (i) Names for figures, such as `Figure of Woodlands`, are values for a special kind of value called `figure name`. This can in turn be used to define variables, properties and phrases: The turn card image is a figure name that varies. An Old Master is a kind of thing. An Old Master has a figure name called appearance. Figure 1 is the file "Giaconda.jpg". The Mona Lisa is an Old Master. The appearance of the Mona Lisa is Figure 1. To place (F - a figure name) in the gallery: [...] (ii) Similarly, names for sound effects, such as `Sound of rustling leaves`, are values for the kind of value `sound name`. (iii) In the released, blorbed-up Glulx file, figures and sound effects are internally given resource ID numbers which count upwards from 2 in order of their declaration. (Figure and sound numbers can thus be intermingled, if their declarations are.) Resource ID number 1 is reserved for the image of the cover art, if there is any. (See the chapter on [Publishing].) To obtain these numbers, if we need them, we can use: > phrase: {ph_figureid} Glulx resource ID of (figure name) ... number > > This phrase produces the ID number used in the eventual Glulx file for the given figure. > phrase: {ph_soundid} Glulx resource ID of (sound name) ... number > > This phrase produces the ID number used in the eventual Glulx file for the given sound effect. (iv) Glulx hackers may also like to know that whenever Inform 7 builds a project for Glulx, the Inform 6 code it generates always contains a full copy of ^{@John Cater}'s definitive header file `infglk.h`. ## Files {EFILES} ^^{files (data files) <-- data files <-- external files}^^^{files (data files) <-- text files} Once an Inform project is released, it is playable as a "story file", which is in effect a computer program for a specially IF-adapted design of computer. Story files run in what in computing is sometimes called a "sandbox", a kind of safe play area where it can be guaranteed that they cannot do any harm. This is good, because it means a story file can't be infected with viruses or other malware. If the project's Settings panel has the story file format set to the Z-machine, the story file is so thoroughly boxed in that it cannot even see the bigger computer beyond: it lives in a world of its own. But the Glulx format opens the door a crack, allowing the story file to read and write a small number of data files, which live in a single folder on the bigger computer's hard drive. Why might we want this? Among the reasons are – - to remember what has happened in previous attempts by the player; - to store the player's preferences; - in a two-part story, where each part is an independently released story file, to allow Part I to save some information about its ending which Part II could then pick up and make use of; - to communicate with some external program, such as an Internet service. ## Declaring files {kind_externalfile} {PM_BadFileIFID} {PM_BadFileOwner} {PM_FilenameDuplicate} {PM_FilenameNotTextual} {PM_FilenameUnsafe} ^^{files (data files): declaring} ^^{defining: data files} ^^{IFID+biblio+} ^^{(binary), when declaring data files+sourcepart+} ^^{files (data files): exchanging with other programs} ^^{>VERSION} Like figures and sounds, files must be declared before they can be used. For instance: The File of Glaciers is called "ice". This creates a new named constant `File of Glaciers` to refer to the file, throughout the source text. We use this name for it whether or not the actual disc file exists yet: it might be one that will only be created if something unusual happens in play, for instance. Quoted filenames should contain only letters and digits, should be 23 characters or fewer, and should begin with a letter. (In particular they can contain no slashes or dots – no subfolders or extensions can be indicated.) The actual filename this translates to will vary from platform to platform, but `ice.glkdata` is typical, stored in some sensible folder. Every file has an "owner" – not a person, but the project which normally writes to it. This is nothing to do with ownership or permission rules about files which the host computer might have, where a file might be owned by another user account or by the system itself, and so on. It's simply that when Inform writes a file, it marks it with the identity of the story which caused this to happen. Ownership in the Inform sense is used to prevent one story from reading a file which only makes sense to a different story, because that won't end well. Inform assumes that the current project will be owning any file which it declares – the File of Glaciers, for instance. But we can optionally specify that it is owned by somebody else: The file of Boundaries (owned by another project) is called "milnor". The file of Spectral Sequences (owned by project "4122DDA8-A153-46BC-8F57-42220F9D8795") is called "adams". Inform uses ownership to make sure that we do not accidentally read in a file which has nothing to do with us, but merely happens to use the same name. Thus it is an error to read a file whose ownership does not agree with our declaration. Saying that a file is owned by "another project" allows us to read it whatever the owner is (so this can be used for files shared between multiple projects); specifying exactly where it needs to come from allows us to pass information from one project to another. Note that we identify projects using the IFID number – this can be found in the Contents index for a project, or by typing ``VERSION`` during play; see the chapter on [Publishing] for more about IFIDs. Files are indexed in the Contents index, alongside figures and sound effects. Two technicalities. First, constants such as `File of Glaciers` are of a kind of value called `external file` (compare `figure name` and `sound name`). Second, Inform's file-handling is provided for the Glulx machine, which in turn uses the Glk interface. This allows for either text or binary files. Inform's higher-level phrases to do with files, described in this chapter, all use text files, and all declared files are text files by default. But we can optionally add the keyword `binary` to declare a binary file, if needed: The binary File of Glaciation Data is called "icedata". ## Writing and reading tables to external files ^^{files (data files): reading / writing tables} ^^{tables: reading / writing to data files} The main use for files is to store and retrieve data, and the most flexible form of data used by Inform is the Table, so facilities are provided which make it as easy as possible to write and read the contents of a table to files. If so, the file must contain just one single table: so to write multiple tables, we need to write multiple files, one for each. To save the contents of a table to a file, we use the phrase: > phrase: {ph_writetable} write (external file) from (table name) > > This phrase causes the entire contents of the given table to be written out to the given file. Note that files must have been declared, and must be referred to by their Inform names, not by textual filenames. Example: > > write File of Glaciation Data from the Table of Antarctic Reserves > > Any blank rows in the table are automatically moved to the bottom, and only the non-blank rows are written. To load a file back into a table, > phrase: {ph_readtable} read (external file) into (table name) > > This phrase causes the entire contents of the given table to be read in from the given file. Note that files must have been declared, and must be referred to by their Inform names, not by textual filenames. Example: > > read File of Glaciation Data into the Table of Antarctic Reserves > > Any rows left spare at the foot of the table are automatically blanked. On the other hand if the file is too large to fit into the table – with too many columns or too many rows – a run-time problem is produced. We can check if a file already exists using: > phrase: {ph_fileexists} if (external file) exists: > > This condition is true if the file-system used by the player appears to contain a file with the right name. For example, if we declared: > > The binary File of Glaciation Data is called "icedata". > > and then tested > > if the File of Glaciation Data exists, ... > > then Inform would search for a file called `icedata`. (The arrangements for where this might be stored, and its filename extension, vary from platform to platform.) One unfortunate restriction must be kept in mind. Some of what is stored in tables is solid information whose meaning never changes: the number 342, for instance, means the same to everyone. But other information depends entirely on the current location of certain structures in memory – for instance, a rule is internally referred to by its memory location. This potentially changes each time Go or Replay is clicked, and so it is not safe to pass it from one copy to another, or from one project to another. The only tables which Inform allows us to write into files are those containing "safe" data: numbers, units, times of day and kinds of value with named alternatives. Scenes, rules or rulebooks, in particular, are not allowed. ## Writing, reading and appending text to files ^^{files (data files): reading / writing / appending text} ^^{text: reading / writing / appending to data files} Text can also be saved to a file, and again all file-handling is automatic: > phrase: {ph_writetext} write (text) to (external file) > > This phrase makes the given text become the entire contents of the named file. Note that files must have been declared, and must be referred to by their Inform names, not by textual filenames. Example: > > write "Jackdaws love my big sphinx of quartz." to the file of Abecedary Wisdom; > phrase: {ph_appendtext} append (text) to (external file) > > This phrase adds the given text to the end of the current contents of the named file (creating it if it does not exist on disc). Note that files must have been declared, and must be referred to by their Inform names, not by textual filenames. Example: > > append "Jinxed wizards pluck ivy from the big quilt." to the file of Abecedary Wisdom; The quoted text can, of course, contain substitutions, so can be long and complex if need be. Text from a file is printed back with the text substitution: > phrase: {ph_saytext} say "[text of (external file)]" > > This text expands to the contents of the named file. Note that files must have been declared, and must be referred to by their Inform names, not by textual filenames. Example: > > "[text of the File of Abecedary Wisdom]" To copy one file to another, for instance, write "[text of the file of Abecedary Wisdom]" to the file of Secondary Wisdom; ## Exchanging files with other programs ^^{files (data files): exchanging with other programs} ^^{IFID+biblio+} Provided we declare the files in the right way, it is easy for one project to read a file created by another project. But if we want more rapid communication, between two projects which are each playing at the same time, we need to be more careful. What if project A tries to read the file at the same moment that project B is writing it? To avoid this, we have a condition of files as _ready to read_ or not. A file is ready to read if it exists, and is completely written, and not in use elsewhere. We have already seen: if the file of Invariants exists... But now we want a stronger condition: > phrase: {ph_fileready} if ready to read (external file): > > This condition is true if the file exists and is marked as being ready to read; that is, it is not in a state where another program is currently writing it. Example: > > if ready to read the file of Invariants, ... A file cannot be ready to read if it does not exist, so this is a stronger condition. If A and B are attempting communication in real time, both running at once, then Project A should check that an external file owned by B is ready before it tries to read it. Files can also be marked as ready or not ready, in effect claiming them, thus: > phrase: {ph_markfileready} mark (external file) as ready to read > > This phrase marks that we have finished writing to the given file, so that any external program is welcome to read it now. Example: > > mark the file of Invariants as ready to read; > phrase: {ph_markfilenotready} mark (external file) as not ready to read > > This phrase marks that we are about to start writing to the given file, so that any external program should wait until we're finished if it wants to read the file. Example: > > mark the file of Invariants as not ready to read; Possibilities really begin to open up when project A is our story file, but B is not another story file at all: it is some external program such as a Web service, say. (Of course this is harder to set up, since the player needs to have both A and B running at the same time, but for stories running on an Internet server this can all be made seamless.) When Inform begins writing a table, or text, to a file, it initially marks the file as not ready: only when the table or text is completely written and the file about to close is the file marked as ready. In order to write non-story-file programs as B, communicating with story files as A, we need to know the file format used by Inform. An Inform file is currently a Unix text file (with 10 as the line division character), encoded as ASCII Latin-1. (We would like to use Unicode at some point in the future, but the Glk and Glulx layers are still not fully converted to Unicode.) It opens with a single header line in the form: ``` * //IFID// leafname ``` The opening character is an asterisk if the file is currently ready, a hyphen if the file is currently not ready. The IFID between the slashes is the IFID number of the project which last wrote to the file. (Marking "ready" or "not ready" does not count as a write for this purpose.) If an external program wrote the file, it should call itself something which will not clash with any story file's IFID. The leafname is the filename text used inside the story file where the file was declared. For instance: ``` * //4122DDA8-A153-46BC-8F57-42220F9D8795// ice ``` # Testing and Debugging ## A recap on TEST and showme ^^{TEST+testcmd+} ^^{testing commands: >TEST} ^^{test (test name) with (commands)+assert+} Testing the story is such a basic part of writing it that we have already seen small tests many times in this manual. In particular, the ``TEST`` command is invaluable. This needs the source text to have set up a script already, say like this: Test dinner with "eat bread / eat soup / eat butter" in the Ship Cafeteria. And then ``TEST DINNER`` will shift the player to the Ship Cafeteria and run through the three typed commands ``EAT BREAD``, ``EAT SOUP`` and ``EAT BUTTER`` in turn. Something else already seen is the ability to have phrases or rules log the current value of something into the transcript of the story. Many of the most annoying bugs come about because we're making some assumptions about what's true in the story world that differ from Inform's assumptions. When that happens, we may need to add something to the source to check that the variables are set to what we think, that certain parts of the source are being reached, and so on. For instance, suppose we have a phrase like this: To say key score: let count be the number of keys which are not carried by the player; if count is greater than 2 and the player is timid: say "You're still missing a lot of keys, bucko!" Now, we expect this to print something, but perhaps it's not doing so when we had anticipated that it would. At some point when we think the `count` is greater than 2 and the player is `timid`, at least one of those things is not true. An easy way to check up on this is to add a showme line to the source, like so: To say key score: let count be the number of keys which are not carried by the player; showme count; showme whether or not the player is timid; if count is greater than 2 and the player is timid: say "You're still missing a lot of keys, bucko!" and this will then check the relevant number and print it to screen when this phrase is called, like so ``` transcript "count" = number: 1 "whether or not the player is timid" = truth state: true ``` In this case, it looks as if there's no problem over timidity, but that the `count` is not high enough to trigger the text, so we can concentrate on working out why that might be. Maybe we didn't correctly define something as a `key`, for instance. ### See Also - [The TEST command] for the full story on this. - [The showme phrase] for more on `showme`. ## Checking against the Index ^^{user interface: Index panel: checking story correctness} ^^{Index panel+ui+: checking story correctness} ^^{testing commands: checking story correctness in the Index} Testing a story – and indeed writing a story so that it is easy to test consistently – is an art in itself. We should expect that we'll do some preliminary testing, both by running test commands and by playing through the story ourselves, and that we'll then hand on the story to beta-testers who will tell us about faults in the play experience that we haven't been able to see. Every time Inform builds a new story file, it assembles a vast amount of information about that world, in the form of the Index. Often a visit to the Index is all that's needed to explain a piece of undesired behaviour. Is travel not working as it should? Check the World index and see whether the map shows the rooms arranged the way you thought. Are objects not showing the behaviour you'd expect based on their kind? Check the Kinds index and make sure they've been defined as the kind of thing you expected. For instance, we might find that we've written The red door is west of Foo and east of Bar. but not The red door is a door. A human reader wouldn't make this mistake, but Inform hasn't actually registered the red door as belonging to the door kind, and consequently has treated it as a room instead. All we need to do is add the kind declaration. The Kinds index will make that obvious. When an error appears in the Index, there is often a link back to the source text that defined that room or object. If not, there's often at least some information about what rule or phrase might be responsible for it. ## Testing commands to inspect the situation ^^{SHOWME+testcmd+} ^^{testing commands: >SHOWME} ^^{ACTIONS+testcmd+} ^^{testing commands: >ACTIONS} ^^{Actions page of Index panel+ui+} ^^{user interface: Index panel: Actions page} ^^{Index panel+ui+: Actions page} ^^{RULES+testcmd+} ^^{testing commands: >RULES} ^^{SCENES+testcmd+} ^^{testing commands: >SCENES} ^^{RELATIONS+testcmd+} ^^{testing commands: >RELATIONS} ^^{RESPONSES+testcmd+} ^^{testing commands: >RESPONSES} ^^{responses (library messages): listing during development} ^^{magic words} In this and the following sections, we run through the testing commands which authors can use, but which are not present in a released story. ``TEST`` has already been covered: see [The TEST command]. We'll begin with some ways to inspect what is happening in the story, but without changing it, using ``SHOWME``, ``ACTIONS``, ``RULES``, ``SCENES``, ``RELATIONS`` and ``RESPONSES``. ``SHOWME``. We can find our current location and the things around us by typing > SHOWME Boudoir - room four-poster bed - supporter yourself - person pillow and similarly we can inquire about the status of a particular object during play by typing ``SHOWME`` and the object's name: > SHOWME BAT bat - thing location: on the table in Locker Room singular-named, improper-named; unlit, inedible, portable, patterned printed name: "bat" printed plural name: none indefinite article: none description: none initial appearance: none This will work even if we're not in the same location as the object we want shown. ``ACTIONS`` is intended to help with a common type of problem: we type a command but Inform does not perform the action that we were expecting. In some cases, this is because the command we're typing is actually triggering some other action. An easy way to check on this is to type ``ACTIONS`` before issuing the command that is behaving unsatisfactorily. Thus: > ACTIONS Actions listing on. > JUMP [jumping] You jump on the spot. [jumping - succeeded] This tells us how Inform interpreted our input and whether the action was successful or failed for some reason. If the command is being understood as a different command than we expected, that may mean that we have made a mistake in our Understand instructions, and need to double-check these. ``ACTIONS OFF`` stops this logging again. ``RULES`` tends to produce rather more output, because it shows exactly which rules are run. Actions are processed with a long series of rules, and it can be helpful to know exactly which ones run and in what order. For example: > RULES Rules tracing now switched on. Type "rules off" to switch it off again, or "rules all" to include even rules which do not apply. > JUMP [Rule "announce items from multiple object lists rule" applies.] [Rule "set pronouns from items from multiple object lists rule" applies.] [Rule "before stage rule" applies.] [Rule "instead stage rule" applies.] [Rule "investigate player's awareness before action rule" applies.] [Rule "player aware of his own actions rule" applies.] [Rule "check stage rule" applies.] [Rule "carry out stage rule" applies.] [Rule "after stage rule" applies.] [Rule "investigate player's awareness after action rule" applies.] [Rule "report stage rule" applies.] [Rule "report jumping rule" applies.] You jump on the spot. [Rule "last specific action-processing rule" applies.] [Rule "A first turn sequence rule" applies.] [Rule "every turn stage rule" applies.] [Rule "A last turn sequence rule" applies.] [Rule "notify score changes rule" applies.] > As we can see, ``RULES`` produces a lot of output, much of which is probably irrelevant. Nonetheless, knowing exactly which rule is printing undesirable output is helpful, especially if that rule comes out of an extension or some other source that we did not write ourselves: this output has told us that the text we saw came from the `report jumping rule`. To find out more about what is going on in specific rules, we can also turn to the Index tab under Actions and click through to that specific action. From there we will be able to see which rules are included, what responses they're writing, and where they were defined in the source text. ``SCENES`` lists which scenes are currently playing and which are complete. This is valuable if scene-triggered events are not happening when we expect them to. ``RELATIONS`` lists all the relations defined in the story, except for things like support and containment that are part of the world model and are so numerous that the output would be overwhelming. ``RESPONSES`` lists all the named responses established by all the extensions currently included. This can be informative, or it can be a bit overwhelming. Except where responses have been changed at runtime, the same information is available in a different form in the Index on Actions. If we're interested in a particular single response, digging into the actions index is probably the easiest way to find it. If, however, we want a rapid overview of all the responses provided by a given extension (perhaps an extension we are ourselves writing), the ``RESPONSES`` command can be a help. ## Testing commands for cheating ^^{PURLOIN+testcmd+} ^^{testing commands: >PURLOIN} ^^{BANISH+testcmd+} ^^{testing commands: >BANISH} ^^{ABSTRACT+testcmd+} ^^{testing commands: >ABSTRACT} ^^{GONEAR+testcmd+} ^^{testing commands: >GONEAR} Inform also provides testing commands which allow the author to "cheat", that is, to make things happen in the story which are outside the usual rules. It often happens that we just want to check one point, deep inside the story, and would like to get there without wasting any time replaying everything else which is working fine. For cheating, then, non-release versions of Inform stories offer the commands ``GONEAR``, ``PURLOIN``, ``ABSTRACT``, ``BANISH``, ``GONEAR`` transports the player instantly to the room which encloses the named object. For a door or a backdrop, multiple rooms may do, and gonear then usually chooses the first room one. For example: > GONEAR GRAIN Fertile Plain You can see some grain here. Of course this relies on the grain being somewhere specific in the story. It's possible to type ``GONEAR NORTH`` and produce a run-time problem, ``You can't move the player off-stage.``, because the `direction` object for north has no specific location to be near. The same will happen if we try ``GONEAR`` on something off-stage. ``PURLOIN`` moves an object to your possession, no matter where it is on the map, like so: > PURLOIN TABLE [Purloined.] > I You are carrying: a table Note that ``PURLOIN`` does not consider the usual rules about whether something can be taken. In this case, we've just moved the table to our inventory even though it is a `fixed in place supporter` that could not be taken in the normal course of events. Because ``PURLOIN`` works on things that are far away as well as things that are close, it has to do a lot of extra parsing work and may take a moment or two to complete if we try it in a very large story. It is generally more efficient to give the player the relevant object using a testing command, like this: Test me with "drop table" holding the table. Nonetheless, there are occasionally times when we're halfway into a 2000-move story and suddenly realise we implemented a vital object in the wrong room, making the story unsolvable. We could fix the bug, press replay and return to this story state fairly quickly, but if we don't feel like waiting even that long, ``PURLOIN`` will resolve the issue. ``ABSTRACT`` is ``PURLOIN``'s less useful cousin, allowing the player to move an object from one place to a specified other place, as in ``` transcript Bar You can see a table here. > ABSTRACT KEY TO TABLE [Abstracted.] > LOOK Bar You can see a table (on which is a key) here. ``` ``BANISH`` removes something from play, and is one way to bulldoze through obstacles. For example: > EAST The bearded guy wants to be paid his winnings first. > BANISH GUY [Banished.] > EAST Main Street Of course, there is no guarantee that any of these commands will make life better or that they won't crash the story or put it into an unwinnable state. ## Low-level testing commands ^^{RANDOM+testcmd+} ^^{testing commands: >RANDOM} ^^{randomness: seeding the generator} ^^{>VERIFY} ^^{SHOWTREE+testcmd+} ^^{testing commands: >SHOWTREE} ^^{SCOPE+testcmd+} ^^{testing commands: >SCOPE} ^^{SHOWHEAP+testcmd+} ^^{testing commands: >SHOWHEAP} ^^{SHOWVERB+testcmd+} ^^{testing commands: >SHOWVERB} ^^{TRACE+testcmd+} ^^{testing commands: >TRACE} The remaining commands are for expert users only, and are very miscellaneous. ``RANDOM`` sets the random number generator to a predictable seed. If we include this in a test command, it will guarantee that the subsequent behaviour of the story is consistent across multiple playthroughs, which is helpful if we're trying to test something to do with, say, randomly wandering non-player characters. ``VERIFY`` checks that the story file is intact rather than damaged, but it is hard to think of an occasion when this would be likely to arise within the Inform application. The command is a holdover from a time when data transfer was much slower and more error-prone, and it was plausible to have a story file of just a few hundred KB corrupted during transmission. ``SHOWTREE`` creates a list of object containment. It is similar to ``SHOWME``, but less elegant and thorough. (At one time, this command was ``TREE``, but that proved to be too ambiguous a word to use for a debugging command.) ``SCOPE`` lists the objects that are currently in scope for the player, which is to say, things that could be referred to when we're typing a typical command. Thus: ``` transcript Bar You can see a table here. > SCOPE 1: yourself (574631) 2: a table (574759) ``` The bracketed numbers are object IDs for these objects, which can distinguish items with identical names. It is likely that the output of this will not be terribly interesting or different from checking ``SHOWME``, except in cases where the author is deliberately changing the scope to be something other than `the set of things that are visible in the room with the player right now`. This usually involves the `Deciding the scope of something` activity (see the chapter on [Activities]). ``SHOWHEAP`` shows how many bytes are currently free. This can sometimes to be helpful to tell when memory is slowly leaking due to a bug. ``SHOWVERB [VERB]`` lists the Understand information associated with a particular verb: for example, ``SHOWVERB TAKE``. Similar information, in a vastly more palatable form, is available in Index / Actions / Commands, so the one time ``SHOWVERB`` becomes useful is when Inform is considering the understand lines in the wrong order and producing a result we didn't want: ``SHOWVERB`` will show us the order in which the lines are being assessed. The challenge will then be to add conditions to the `Understand` lines to move them into the correct order. Finally, ``TRACE`` (and its more advanced stages ``TRACE 2``, ``TRACE 3`` and so on up to ``TRACE 6``) will reveal things, more things than we ever wanted to know, about the assumptions being made by the command parser when it takes in a command. In practice this information is almost never useful to an Inform author. ## Adding new testing verbs and Release for Testing ^^{testing commands: defining} ^^{test version (of the story) <-- debug version (of the story)} ^^{omitting code, for release version} ^^{|not for release} As we saw in the chapter on [Source Text], we can mark some of our source text so that it will not be included in a finished story. This means that we can add special testing commands available to the author but not available to our eventual players. This is a good way to add our own suite of testing verbs to a story beyond the `Test me with...` features already described. Here are some types of testing verbs that can be useful to add: Chapter jumps. We might create test commands that took us to a later stage of the story (perhaps doing more setup than `Test me...` alone can handle). Status information. We might create a test command that would show us status information beyond what's covered in the Standard Rules. For instance, if we had a story that heavily modeled the moods of other characters and we wanted to be able to check those moods at any time, we might add a ``SHOWMOOD`` command that would tell us about a character's emotional state. Puzzle satisfaction lists. Some simulation-rich stories offer puzzles that can be solved in a variety of ways: for instance, a sealed glass box that can be smashed with any object that has been marked with the properties `hard` and `heavy`. Later, we might want to be able to check which in-story objects would work as a solution to this puzzle, so we might create a command like Listing hammers is an action out of world applying to nothing. Understand "list hammers" as listing hammers. Carry out listing hammers: say "These things can break the glass: [line break]"; repeat with item running through portable hard heavy things: say "[item][line break]"; so that we can review that there are enough objects available and that the list doesn't include anything it shouldn't. In a small story this kind of thing is pretty easy to keep track of in the author's head. Large stories can contain thousands of objects, however, at which point it becomes valuable to have an automated method of verification. Just occasionally, we might also want to build a version of a story that will allow beta-testers access to the debugging commands. This is especially relevant for long stories: if we're testing a story with a lot of playtime and the testers have already thoroughly reviewed the first portion of the story, we might want to let them have access to testing commands that fast-forward to later sections. To do this, we can use the Release for Testing feature. Release for testing builds a version of the story that *does* include testing commands and any sections labelled `Not for release`. To sum up these three methods for compiling: Compile how? | `for release only` sections | `not for release` sections | testing verbs | Writes to `Release` ----------------------------- | --- | --- | --- | --- Go button | no | yes | yes | no Release button | yes | no | no | yes Release for testing menu item | no | yes | yes | yes ## Testing for thoroughness ^^{Object Response Tests+ext+} ^^{extensions: specific extensions: Object Response Tests} The presence of actual bugs or defects is not the only thing we want to consider when testing a story. We may also want to check whether we have built the story with a consistent amount of depth. Are there descriptions for everything the player might look at? If we've implemented special verbs, do they have appropriate reactions for all the different objects? If most objects in a story about restaurant reviewing have a special response to being tasted, for instance, it might be disappointing for the player to encounter late-added objects that don't. Checking implementation thoroughness can be a laborious process, but there are a few things we can do to automate it. For instance, we might add to a not-for-release section a rule that checks for certain properties: When play begins (this is the run property checks at the start of play rule): repeat with item running through things: if description of the item is "": say "[item] has no description." This will confront us with a reminder of what we still need to fill in every time we start up the story. There are also some extensions that are designed to assist with this, notably the massive Object Response Tests by ^{@Juhana Leinonen}. Object Response Tests allows us to try out a long list of commands against any object in the story, so that we can quickly identify ones with nonsensical replies. ## Commands for beta-testers ^^{>TRANSCRIPT ON/OFF <-- >SCRIPT ON/OFF} ^^{testing commands: comments in transcripts from beta testers} ^^{comments: in transcripts from beta testers} Inform includes a command that is especially designed to help beta-testers report flaws: namely, ``TRANSCRIPT``. A tester can type ``TRANSCRIPT`` (or just ``SCRIPT``) at the beginning of the story in order to start generating a recording of everything that happens. She can then add her own annotations when something buggy or otherwise notable occurs. When she then sends us the completed transcript, we can look through for these symbols and note the problems the tester found in the context of the rest of the story's behaviour. Having information about how she reached that position typically makes it much easier to reproduce the problem than if she gave only a general account of it. ## Help from the user community ^^{intfiction forum+web+} Sometimes we get really stuck on a problem and despite all our best efforts cannot figure out how to solve it. Fortunately, Inform has a lively and helpful community of users who are often willing to assist other authors. The easiest way to reach these users is to make a post at the [IntFiction forum](https://intfiction.org/), and in particular to post Inform-related problems under [IntFiction's Inform 7 category](https://intfiction.org/c/authoring/inform-7/19). Where possible, it's a good idea to post the example source that is causing trouble, and to make it as short as possible so that prospective helpers will not have to read any more than necessary in order to pinpoint the problem. The user community is also a good place to find beta-testers who can try out our work and give feedback. ## Source control, git and GitHub In recent years, "source control" has gone from being something which only professional programmers use to being more mainstream. The idea is to safeguard the source code for a program — or, really, anything written in plain text — in a "repository". It's then possible to keep track of which version of a program is the current one, to try experimental changes, to have other people contribute fixes or additions, and so on. Inform projects and extensions are, of course, programs too, and some Inform users have been placing them under source control for many years now. Fashion in source-control systems comes and goes — ```RCS```, ```mercurial```, ```perforce```, ```subversion```, and so on — but ```git``` is now fairly dominant. Though it is a notoriously difficult set of command-line tools to master, it is well served by more user-friendly front end apps for MacOS, Windows or Linux, and by the website: https://www.github.com In fact, the source code for the Inform compiler and surrounding tools is itself a ```git``` repository at GitHub: https://github.com/ganelson/inform There are many beginner's guides to ```git``` already, so this is not the place for that. But a brief note about ```.gitignore``` is in order. An Inform project, say "Agitation", is stored as two directories side by side: the so-called project folder, ```Agitation.inform```, and the materials folder, ```Agitation.materials```. (On MacOS, ```Agitation.inform``` looks and behaves like a single file in the Finder, but it is in fact a directory.) Some of the contents of these directories are things which must be kept permanently — the source text, pictures used, the IFID, and such — and some is ephemera which should be regenerated as needed — story files resulting from compilation, index HTML files, released websites, and such. It's clumsy to allow ```git``` repositories to contain these ephemeral, always-changing files, because then the repositories seem to be constantly churning with changes which aren't in fact meaningful. ```git``` therefore provides for a repository to contain an optional file called ```.gitignore``` which lists the _unimportant_ files, the ones which, in fact, ```git``` should ignore. Because ```.gitignore``` is a filename beginning with a full stop, it's a file which is invisible to casual users on some platforms (for example, by default the MacOS Finder does not display such files). This makes it a nuisance to change. Inform therefore automatically creates (or modifies) two ```.gitignore``` files whenever it compiles a project. One each is placed inside the project and materials folders, with sensible settings for each. These settings are placed in a so-called "stanza" between comment lines in the ```.gitignore``` files, like so: # This stanza written automatically by inform7 ... # End of stanza written automatically by inform7 This is usually exactly what is needed. If a ```.gitignore``` file is already present, Inform adds or updates this stanzas, leaving the rest of the file alone. But if even that is troublesome, adding this comment line: # No stanza written automatically by inform7 anywhere in the ```.gitignore``` file will tell Inform not to modify the file, and in particular not to add the usual stanza. It will be as if this feature of Inform did not exist for the project. # Releasing ## The finished product This chapter and the next are about what to do when we have a complete, finished work on our hands. For almost all of the time when a new work of IF is being written, it lives inside the familiar two-panel spread of the Inform user interface. But that isn't how eventual players will experience it. They will want to play a "story file" in a standard format, and they will do so with a wide range of different interpreters on many different computers or websites, including some – like mobile phones – on which Inform itself will not run. So how does a new work of IF reach players? The simple answer, covered in this chapter, is that clicking the Release button instead of Go causes Inform to output a stand-alone story file. But as we will see, Release can do much more than that: it can attach covers, include bibliographic data, make websites and much more. Releasing is the process of making all of the material we want to deliver to our eventual players. But that is only the first step. What do we do with the material when we have it? Printing out a manuscript of a novel is not the same as publishing it. So the next chapter, [Publishing], completes the story. ## Bibliographic data {PM_BadEpisode} ^^{bibliographic data <-- metadata <-- publication data} ^^{title+biblio+} ^^{author+biblio+} ^^{headline+biblio+} ^^{release number+biblio+} ^^{genre+biblio+} ^^{story description+biblio+ <-- blurb+biblio+} ^^{punctuation: apostrophe: meaning quotation mark} ^^{|': meaning (")+sourcepart+}^^^{+tosay+"[(unicode character)]" --> unicode character} Almost all printed books have a title page and a so-called "imprint" page, often its verso, which make up a description of the contents. The title page gives the name of the book and of the author, while an imprint page contains a variety of details about the edition, the printing, and so on. An ISBN number is allocated so that, from the number alone, any book seller or cataloguer can identify exactly this work. Sometimes other cataloguing information is added, such as the Library of Congress classification. This set of information is called "bibliographic data", and without it libraries and booksellers would be at a total loss. IF has bibliographic data, too. Inform has a number of special named values to hold this – who wrote the work being created, what it is called, what headline it has, what genre it has and what its release number is, and so on. These can be set as follows: The story title is "Mansfield Perk". The story author is "Janet Austen". The story headline is "An Interactive Romance". The story genre is "Romance". The release number is 7. The story description is "In Miss Austen's new interactive novella, Miss Henrietta Pollifax is adopted by the tempestuous landowner Sir Tankerley Mordant, and must make a new life for herself on the rugged moors." The story creation year is 2005. Most of these are self-explanatory. The `story creation year` is provided so that if we need to revise the work to fix some bugs a year later – by no means an uncommon occurrence – then we can make sure it is correctly identified as still being basically a 2005 work. (Just as a book which has had innumerable revised printings may say "First published 1988" on its imprint page.) The `story description` is a piece of text, analogous to the back cover blurb on a book: it might be two or three paragraphs long, so the example above is rather minimal, but it should not be epic in length. As we have already seen, a convenient abbreviation provides that if the first sentence of the source text consists solely of text in quotation marks, then that is considered the title. Thus if the source begins: "Mansfield Perk" then that will be the `story title`. Further, we can write "Mansfield Perk" by Janet Austen with the obvious effect: quotation marks around the author's name are optional here, for convenience, but note that we'd better have them in cases like: ^^{@Jerome K. Jerome} "Three Men in a Boat" by "Jerome K. Jerome" as otherwise the full stop after the K will end the sentence prematurely. The text of these bibliographic descriptions cannot normally include text substitutions, since they are written into external descriptions of the story file as part of its "binding". Two exceptions are allowed, though: `"[']"` makes a literal apostrophe, and can be used if we need to override Inform's normal conventions to do with converting apostrophes at the ends of words to double-quotes. For instance: "Summer of [']69" by Buzz Aldrin The other exception is that the `"[unicode ...]"` text substitution works, so for example: The story description is "This is a sentence[unicode 8212]with a parenthetical in dashes[unicode 8212]because 8212 is the Unicode number for an em-dash. But for example, 'pawn to [unicode black chess bishop]4' draws in a black chess bishop, so it works with names, too." If the bibliographic named values are not set by the source text, Inform will still need to say something. Unset text and number variables evaluate to `""` and `0` respectively, but this would make for a very unhelpful record. So Inform uses the following table instead of any value which is unset: Story title: Untitled Story author: Anonymous Story headline: An Interactive Fiction Story genre: Fiction Release number: 1 It is also possible to provide copyright and licencing details for a project. This follows the same syntax and conventions as for extensions, except that the word `story` is used instead of `extension`. See [Licence] for more. The licence for this story is "CC-BY-4.0". The copyright for this story is "Bartholomew Hendricks 2006-2024". The origin for this story is "https://www.loosecannonif.com/bh". The rights history for this story is "Adapted by permission from Jennifer Pond's novel 'The Transfinite Kitten' (2003)." Finally, the text variables `story serial code` and `project IFID` are automatically set by Inform to the IFID for a project, which is intended to be permanent, and to the serial code it's got today, which is more ephemeral since it is computed from the date (in the form `YYMMDD`). These variables cannot be changed at run-time, and cannot be set from assertion sentences, although there is a use option to set the IFID. ## Genres ^^{genre+biblio+} The `story genre` is not used in the banner at all, and exists purely to help librarians. If it is at all possible to do so, authors are asked to use one of the following standard categories: Comedy, Erotica, Fairy Tale, Fantasy, Fiction, Historical, Horror, Mystery, Non-Fiction, Other, Romance, Science Fiction, Surreal These categories are based on those currently used by bookshops, but a few notes may be helpful. "Fiction" is intended for works whose essential purpose is literary, in a way which trumps any subject they happen to have: if Julian Barnes writes a mystery, for instance, a bookshop will shelve it with modern novels rather than in the detective stories section, whereas P. D. James's Adam Dalgliesh mysteries will end up filed with detective fiction even though she has appreciable claims to be an important novelist. "Comedy" is used rather than "humour" to avoid the clash of spellings with "humor". This genre includes parodies. "Non-Fiction" would be used for a work of IF which is essentially a presentation, perhaps in a novel interactive format, of true information. A meticulous simulation of the Great Exhibition of 1851, for instance, might qualify. The distinction between "Surreal" and "Other" is that "Surreal" works contain at least some semblance of narrative, whereas "Other" is intended for works which "abuse" the format to present some entirely different sort of game – Tetris, say, or Minesweeper. ## The Library Card {LCARDS} ^^{bibliographic data} ^^{banner text} ^^{blorb file} Bibliographic data is useful for two reasons. Firstly, it enables the equivalent of a title page to be printed – traditionally called the "banner" – at the start of play; secondly, Inform uses it to generate the equivalent of a library card for the work, which can be used by other programs to help organise, sort and classify interactive fiction. If the card is given to any other program on any other machine (or an Internet-based archive) then, in principle, that system can know about our work of fiction without a human librarian having to get hold of a copy, play it and laboriously copy out the details. The "library card" is not of course a physical card, but a small "metadata" file which could potentially be transmitted quickly across the Internet. It contains no personal data other than what you choose to put on it, using the sentences documented in this chapter: it does not, for instance, identify your computer or IP address. In any case Inform does not send it anywhere, but merely keeps an up-to-date copy within the project, and includes it when making a release copy of the work. You can always see (a representation of) the current library card for a project in the Contents index. Authors are asked to play fair, in return, by writing sensible and useful bibliographic information for any work which is likely to circulate to other people; by being honest (writing under a pseudonym is fine, but not impersonating other people); and by conforming to standard practice. The Settings panel of each project contains a tick-box called "Bind up into a Blorb archive on release", and by default this is ticked. "Blorb" is a nonsense word from a popular early 1980s work of IF called _Enchanter_, where it was the name of a magic spell whose purpose was to "safely protect a small object as though in a strong box". In the late 1990s, the name was borrowed for a standard format for what might be called the wrapping and packaging of IF. A typical Blorb archive produced by Inform contains the "story file" – the actual program for the story – together with its library card and cover art. Modern IF interpreters such as Zoom for Mac OS X and Unix, and Windows Frotz, can play blorb archives directly, and the authors of Inform hope to make this the normal practice in future. Still, some interpreters cannot read blorbs directly and have to be given the actual story file: so by unchecking the above tick-box, we can insist that Inform creates only that. The disadvantage with this, of course, is that the library card (with all its bibliographic data) and any cover art is lost in the process. ## The Treaty of Babel and the IFID {IFIDS} ^^{IFID+biblio+} ^^{Treaty of Babel} ^^{Babel, Treaty of Babel} During March and April 2006, an agreement was reached between the IF archive and most of the different systems for creating IF – of which Inform is only one – called the Treaty of Babel. While these different systems create computer programs which are quite different internally, the Treaty provides for works of IF to come with bibliographic data which identifies them in a standard way. Inform is fully compliant with the Treaty. In particular, each new project created by Inform is allocated a unique identification number called its IFID. The IFID is the equivalent for IF of the ISBN of a printed book. Inform copies it onto the "library card" for the benefit of Internet-based libraries which may eventually accession the work. Of course many projects start but never see the light of day, so many possible IFIDs are "wasted": but that hardly matters, as there are plenty more numbers in the world. To see the IFID of your project, see the Library Card in the Index, or type the command ``VERSION``. > [!IMPORTANT] > The important thing is that **the IFID number must be unique to this one work out of all the IF ever created.** > > The Inform apps will try to make sure this is true, **unless** we do something to break this ourselves. For instance, if we take an existing project, copy it as a file, then work divergently on the original and on the copy so that they become two radically different works, they will still each have the same ID. This is a bad thing: if we want to duplicate a project but then turn it into something new, the best way to do that is to create a new project, and to copy and paste the source from the old to the new. > > In particular, be aware that using "Save as..." in the Inform apps generally saves a clone of the current project _but with a fresh IFID_. This is intended so that people who use "Save as..." on an old project to begin a new one do not accidentally reuse its IFID. -- -- -- Inform does provide a way to specify the IFID within the source text, but it should be used only with care. A special use option is needed: Use project IFID of "c20500c5-495d-47dd-8706-c1bb66d077ed". The IFID cannot be just any piece of text. To quote the Treaty of Babel, at §2.2: > The IFID shall be a sequence of between 8 and 63 characters, each of which shall be a digit, a capital letter or a hyphen. Inform enforces this by issuing problem messages for any attempt to use an illegal IFID, except that it silently converts lower-case `a` to `z` into capitals. The above example thus actually produces the IFID `C20500C5-495D-47DD-8706-C1BB66D077ED`. > [!WARNING] > So, then, there are two ways an IFID can be specified: in a special `uuid.txt` file tucked away inside the project, usually put there by the Inform apps; or in the source text, with `Use project IFID`. But since both are optional, and it's legal to give either, both, or neither, Inform sometimes needs to make a choice. This is how: > > - If neither is given, the IFID is `00000000-0000-0000-0000-000000000000`. > > - If both are given and they disagree, then the `Use project IFID` version as the answer. > Unless the version being overridden is `00000000-0000-0000-0000-000000000000`, a warning message is generated. > > As this suggests, the IFID `00000000-0000-0000-0000-000000000000` is special. Inform uses it only for throwaway test projects. A story should never actually be released with this IFID, and Inform will issue a warning if this is tried. ## The Release button and the Materials folder {PM_NoSuchPublicRelease} {release_files} ^^{user interface: Release button} ^^{Release button+ui+} ^^{release version (of the story)} ^^{materials folder: released story file} ^^{omitting code, for release version} ^^{|not for release} ^^{|for release only} ^^{headings} ^^{subheadings} ^^{source text: subdivisions} Inform's Release button does two things: it makes a stand-alone, public version of the current project – a "story file" – and it gathers up, or creates, whatever material we want to go with it. The release version of the project can be played by anyone with an "interpreter" – they do not need the Inform application installed on their computers, and they will not be able to see the source text. Released versions differ slightly from the versions playable in the Story panel of Inform, because debugging commands such as ``ACTIONS`` are not included with them. (As we've seen, also excluded is any material in the source text under a heading including the words `not for release`.) In some cases, if we release along with an interpreter, we can even make the project playable from a web browser, so that the player doesn't need to install any software at all, not even a browser plugin. The Release button also creates a `.materials` folder for the project, if one doesn't exist already. (On some platforms, the Inform user interface creates it automatically alongside the project.) Inform adopts the convention: the files associated with the project `Whatever.inform` should all be kept in a subfolder called `Whatever.materials` in the same folder that contains the project. For example, if we have a project filenamed Magician.inform which lives in a folder called "Works in Progress", then files might be arranged like so: ``` Works in Progress Magician.inform Magician.materials Collegio.pdf Mating Wyverns.mp3 ``` Of course "Magician" might not actually be the title of the project – it might be an abbreviation, or a working title. The name of the `.materials` folder has to match the name of the `.inform` file, not the title. Several advanced features of Inform make use of the `.materials` folder, and the "Release" button is one of them. It creates a further subfolder called "Release" within the materials folder. This is where it will always place the story file it creates, together with anything released "along with" the story – Inform will not need to put up a dialogue box asking us where to save the story file, because there is already a natural place. For instance, after a successful click on Release, we might then see: ``` Works in Progress Magician.inform Magician.materials Collegio.pdf Mating Wyverns.mp3 Release Collegio.pdf Magician.zblorb Mating Wyverns.mp3 ``` where `Magician.zblorb` is the actual story file produced by Inform. Note that Inform has made copies of the files to be released with it – the idea is that the Release subfolder contains only what Inform makes, and everything in the Release subfolder can be thrown away at any time. This is especially useful if we're releasing along with a website (see below), as then the Release subfolder will be exactly what needs to be uploaded to a server to be shown to the world. Equally, the Release subfolder is what can be zipped up and uploaded to archives or (if small enough) emailed out. ## The Joy of Feelies {PM_ReleaseAlong} ^^{feelies} ^^{materials folder: feelies} ^^{blorb file} ^^{release along with...+assert+: a file of (description) called (filename)+sourcearg+} "Feelie" is a slang word, again going back to the early days of IF, for something tactile included with commercially sold copies of IF games. For instance, ^{Infocom}'s _Wishbringer_ was not just a diskette in a pretty box: the box also contained a map, a letter, an envelope, a magic stone (well, a stone) and a booklet. Most of this was purely for fun, and to flesh out background to the story, but there would usually be clues sneaked into the text or artwork as well. Today's IF is usually not supplied in physical packaging, and not accompanied by physical objects. But authors do sometimes want to include extraneous matter, whether it's a simple read-me file of instructions or a multimedia extravaganza. Inform does not provide facilities to make artwork, movies, soundscapes, booklets, etc.: there are plenty of programs out there to do all of that already. But Inform does help with the collation and packaging-together. For instance, by placing the following sentence in the source text: Release along with a file of "Collegio magazine" called "Collegio.pdf" and a file of "The mating call of the green wyvern" called "Mating Wyverns.mp3". ...we tell Inform that we will also be providing two additional files. Note that in each case we supply a brief description and a filename. The filename should always have a standard file extension for a well-known and thoroughly standardised file format – `.pdf` and `.mp3` are pretty safe: so for instance are `.txt`, `.png`, `.jpg`, `.html`. The filename should not include punctuation marks other than the full stop dividing name from extension, and should not exceed 30 characters in length. It is also possible to supply a feelie which is not a single file, but is a mini-website: that is, a collection of interlinked HTML (and perhaps other) files. The convention here would be: Release along with a file of "Baltrazar's Guide to Magic" called "Guide". The absence of a file extension on the filename `Guide` tells Inform that the feelie in question is a mini-website: it is expected to sit inside a folder called `Guide`, with its home page being `Guide/index.html`. However, a mini-website like this must be created by hand: Inform does not copy it into place, it only creates links to the place where it ought to be put. We have seen that Inform takes the story file, which is analogous to the pages of a book, and places it into a Blorb archive, analogous to the binding. These new additional files are not placed in the Blorb, because that would make the Blorb archive rather large (and would hide them from the player, which defeats the purpose). But references to them do appear in the Blorb, so that any interpreter playing the Blorb would be able to tell that there are supposed to be additional files available. Similarly, references are entered onto the library card. ## Cover art {release_cover} ^^{materials folder: cover art} ^^{figures: cover art} ^^{cover art} ^^{release along with...+assert+: |cover art} ^^{IFDB+web+} Accompanying files are not the only things which can be included in a `release along with` sentence: for instance, we could Release along with cover art ("A stone gargoyle"), a file of "Collegio magazine" called "Collegio.pdf" and a file of "The mating call of the green wyvern" called "Mating Wyverns.mp3". Cover art can not only be used to advertise a work of IF, it is also displayed to players by certain interpreters, such as Zoom or Spatterlight for OS X, or Windows Frotz for Windows. It is also used on the IFDB ([ifdb.org](https://ifdb.org)), and by browsing applications. If Zoom is installed, then on Mac OS X Leopard, the Finder shows cover art directly: ![coverflow](doc_images/coverflow.png) Cover art for a work should be prepared in either JPEG (`.jpg`) or PNG (`.png`) format, and we recommend that it should be square, like a music album cover. Programs which notice the cover art for a work of IF are likely to scale this up or down as convenient for their own display purposes, but it would be helpful to provide the original art at 960 by 960 resolution. The cover art must not be smaller than 120 pixels in either dimension. To provide cover art, we should create an image file called Cover.jpg, or else Cover.png, and place it in the project's .materials folder. For instance, we might have: ``` Works in Progress Magician.inform Magician.materials Collegio.pdf Cover.jpg Mating Wyverns.mp3 ``` (supposing that, as in the previous examples, `Collegio.pdf` and `Mating Wyverns.mp3` are the filenames of two feelies that accompany the release). The text in brackets after the release instruction... Release along with cover art ("A cathedral at sunset."). ...is provided for the benefit of blind or partially sighted users, and should be brief. ## An introductory booklet and postcard {release_booklet} {release_postcard} ^^{introductory booklet and postcard} ^^{materials folder: introductory booklet / postcard} ^^{release along with...+assert+: |an introductory booklet} ^^{release along with...+assert+: |an introductory postcard} When IF is aimed particularly at people who have never played IF before, there are certain conventions which it's a good idea to explain, or players will simply not know what to do. It can become a chore writing a clear set of instructions, and then there is the further nuisance of explaining about the need for an interpreter program to play the IF story file. To alleviate this, Inform can `Release along with an introductory booklet`, as for instance in this example: Release along with cover art, the introductory booklet, a file of "Collegio magazine" called "Collegio.pdf" and a file of "The mating call of the green wyvern" called "Mating Wyverns.mp3". The introductory booklet is a standard 8-page PDF file, written and designed by ^{@Emily Short}, which contains all the basic information needed for a player to get started. It has been written to be as general-purpose as possible, in the hope of being useful for a range of widely different works of IF. There will certainly be works to which it would not be an appropriate supplement, and some authors will certainly prefer to write their own notes for players, but of course it is not compulsory. By making it available as a convenience, the authors of Inform do not intend to say that these are the "official" instructions or that others are not. It is simply intended as a time-saver. As an alternative, or a supplement, it's also possible to: Release along with an introductory postcard. which supplies a standard postcard about IF (everything new players need to know, at one glance) written and designed by ^{@Andrew Plotkin} and ^{@Lea Albaugh}. ## A website {release_website} ^^{materials folder: web pages for the story} ^^{release along with...+assert+: |a website} Much of the published IF of the last twenty years came with a brief text file describing what it was – a release note. Today it makes more sense to write this as a small web page, which can either be placed online, or simply distributed as part of the release. Inform is able to manufacture such a website automatically. We request this by writing, for instance, Release along with cover art, a website, a file of "Collegio magazine" called "Collegio.pdf" and a file of "The mating call of the green wyvern" called "Mating Wyverns.mp3". where the list of ingredients now includes `a website`. In fact, Inform makes only a single web page, called `index.html`, which it places in the materials folder (as set up in the previous section): this then contains suitable links to all the other material, such as the cover art images, if they are also provided. For instance: ![sampleweb](doc_images/sampleweb.jpg) After a successful release now, then, we should see: ``` Works in Progress Magician.inform Magician.materials Collegio.pdf Cover.jpg Mating Wyverns.mp3 Release Collegio.pdf Cover.jpg index.html Magician.zblorb Mating Wyverns.mp3 Small Cover.jpg ``` (`Release/Small Cover.jpg` is a form of the cover image intended for display at a smaller size. In earlier versions of Inform, the author had to provide this: there is now no need.) ## A playable web page {release_interpreter} ^^{materials folder: web-playable story} ^^{release along with...+assert+: |an interpreter} Modern web browsers are now so powerful as computing environments that they almost amount to general-purpose computers in their own right. The websites made in the previous section were passive, and simply displayed information about a story file. But it's also possible to make a more active page – one which can play the story file, right inside the browser, for anybody who visits. To make such a page, we must: Release along with an interpreter. This automatically releases along with a website as well, since we need the website in order to house the new page, which will be called `play.html`. This page will be bundled up with a customised copy of a story file interpreter coded in Javascript – in effect, a program for a web browser to follow – and a suitably encoded version of the story file. The practical effect should be that anyone visiting the page with any modern browser can just play. Inform ships with the "Parchment" and "Quixe" interpreters built in. By default Inform will use Parchment if the format (on the project's Settings panel) is set to Z-code, and Quixe if the format is Glulx. In fact, though, Parchment works with either format, and some users prefer using it. If we want to have Parchment even for a Glulx project, we can write: Release along with the "Parchment" interpreter. ...and that's just what will happen. In fact, Inform also supports the use of any other interpreter the author wants to try. If we have access to an exotic Javascript-based interpreter called, let's say, "Urbzig", then we can install it by putting it into the `Templates` subfolder of the `.materials` folder for the project: Release along with the "Urbzig" interpreter. ## Using Inform with Vorple ^^{Vorple system+ext+} ^^{extensions: specific extensions: Vorple system} ^^{release along with...+assert+: |an interpreter} "Vorple" is an innovative system by ^{@Juhana Leinonen} for allowing web-based Inform stories to make use of web controls and other gadgets. Using Vorple, a story can in principle have an entirely different user interface, and can make much better use of CSS styling, interface to Javascript libraries, and so on. Vorple has seen rapid development. In its early days it was included as part of the Inform app, but it has now evolved into a dynamic project which is better served by the [Vorple website](https://vorple-if.com/). ## Website templates ^^{materials folder: web pages for the story: templates} ^^{templates: for web pages for the story} Web pages are very idiosyncratic things and Inform will almost certainly not produce exactly what we want. What it actually does is to take an existing "template" web page, and paste in the relevant information to make the final product. So by starting with a different template, we can end up with an entirely different-looking web page: like this one, for instance – ![sampleweb2](doc_images/sampleweb2.jpg) The template ordinarily used by Inform is called `Standard` and comes built in. (A second built-in template, `Classic`, imitates the look used in 2005-08. The word "classic" here is to be understood in the sense of Classic Mac OS, the classic Doctor Who adventure _Time and the Rani_, classic Mayan civilisation, and so forth – really pretty awful.) Any other templates we must make ourselves, giving each one a different name, by convention a single word. In this section, we'll make a new one called `Platinum`. Suppose we write: Release along with cover art, a "Platinum" website, a file of "Collegio magazine" called "Collegio.pdf" and a file of "The mating call of the green wyvern" called "Mating Wyverns.mp3". This is identical to the previous version except for the `Platinum`: note the quotation marks. When it needs to find a template, Inform searches the following places in sequence: 1) the `Templates` subfolder of the project's own `.materials` folder, if this subfolder should exist; 2) the `Templates` folder in the user's own library: - on MacOS, this is `~/Library/Inform/Templates` - on Windows, `My Documents\Inform\Templates` - or on Linux, `/Inform/Templates` (c) the built-in stock of templates, currently only `Standard` and `Classic`. What Inform looks for is a folder name matching that of the template – so in our case we need to provide a folder called `Platinum`, and put it in either location (a) or (b). The template folder is expected to contain some combination of the following files: ``` Platinum index.html source.html style.css (extras).txt ``` There are two HTML pages here, one for the main front page, the other for pages of displayed source text (if we release along with the source text – see later in the chapter). The CSS file defines styles of text – sizes, fonts, colours, and so on – and positions material on the page. The `(extras).txt` – which is optional, of course – allows additional HTML pages, images, movies and so on to be added. If any of these is missing, Inform uses the one in `Standard` instead. In practice, this means the easiest way to create a new template is to supply just a new CSS file, which can change the colour, font, type size, and position of more or less everything in the site: ``` Platinum style.css ``` We probably want to start from the `Standard` version of `style.css` and edit in a few changes; the easiest way to get a clean copy of `Standard`'s CSS file to work on is to release the project with a `Standard` template, which causes this default `style.css` to appear in the `Release` subfolder of the project's .materials folder. (But it's wise to move the file out of `Release` before starting to edit it – files in `Release` are overwritten by Inform whenever a release is made.) This is not the place to describe how CSS works. CSS is a more or less universal format today for describing how web pages should look – their style rather than their content. A dazzling variety of possibilities can be seen at the excellent [CSS Zen Garden](http://csszengarden.com/), but of course there are many, many other textbooks and websites which describe CSS. ## Advanced website templates ^^{materials folder: web pages for the story: templates} ^^{templates: for web pages for the story} The following describes how Inform uses the extras file and the two HTML pages in a template, and will only be needed if a new template has to make changes so radical that altering the CSS alone won't be enough. The optional `(extras).txt` file – note brackets – is a text file which contains a list of named extras to throw in. For instance: ``` easter.html egg.png ``` These named files need to be present in the template folder. Files with the extension `.html` go through the placeholder expansion process just like the index and source pages; all other files are copied verbatim. HTML templates like `index.html` and `source.html` are fully valid HTML pages in their own right, though they have placeholder text where Inform will substitute the project's bibliographic data (see below). The `` element should include a reference to `style.css`, which of course will mean the CSS file given in the template (or the one from `Standard` if no CSS file is given) – for instance, ``` html ``` When it turns the template into the final web page, what Inform does is to replace certain capitalised words in square brackets with the appropriate text: Placeholder | Becomes -------------- | ------- `[TITLE]` | the story title `[AUTHOR]` | the author's name `[YEAR]` | the story creation year `[BLURB]` | the story description `[RELEASE]` | the release number `[COVER]` | an image of the cover art (the small 120x120 cover image) `[DOWNLOAD]` | the download link `[AUXILIARY]` | the list of feelie-like files, if any `[IFID]` | the IFID `[STORYFILE]` | the "leafname" of the story file, e.g., `Bronze.gblorb` `[TEMPLATE]` | the name of the template used to make the page `[SMALLCOVER]` | the filename of the cover when used at a smaller size `[BIGCOVER]` | the filename of the cover when used at full size `[TIMESTAMP]` | the time of releasing `[DATESTAMP]` | the date of releasing Everything else is left alone. In source pages, five further placeholders are available: Placeholder | Becomes --------------- | ------- `[SOURCE]` | the portion of the source text on this page `[SOURCELINKS]` | the navigational links `[SOURCENOTES]` | the footnote matter at the bottom of the source `[PAGENUMBER]` | the first number in "page 2 of 7"-like page counts `[PAGEEXTENT]` | the second number in "page 2 of 7"-like page counts Both [SOURCE] and [SOURCENOTES] must exist on the page, and [SOURCENOTES] must appear after [SOURCE] does in the file. (Of course the CSS in `style.css` might move the copy around on screen, but that's another matter.) ## Republishing existing works of IF {PM_RoomInIgnoredSource} ^^{materials folder: pre-existing story file} ^^{release along with...+assert+: |an existing story file} ^^{bibliographic data} Some long-time users of Inform will have projects which were originally made using the very different Inform 6 language. Story files produced with Inform 6 do not have any of the extra touches in this chapter: in particular, they have no cover art and no bibliographic data, which makes them rather plain and anonymous to newer Treaty of Babel-equipped programs like Zoom, Spatterlight or Windows Frotz. To help with this, today's Inform can republish an Inform 6 project by combining an Inform 7 source text which contains only release instructions and bibliographic data with an already-compiled Inform 6 story file. We do this by writing a short source text which contains: Release along with an existing story file. We then place the story file in the `.materials` folder. By default this will be called `Story.z8`, but we can alternatively name it: Release along with an existing story file called "Zork1_sg.z5". The Settings panel must be switched to the Z-machine for this to work, since only Z-machine story files are supported this way, not Glulx. And we can now use the Release button to obtain the goods. An existing story file can take advantage of all of the extra features – cover art, titling, website, feelies and so forth – earlier in this chapter, but not those – walkthrough, source text, map – which are still to come. The following is a typical example of a source text used solely to bind up an old Inform 6-compiled story file: "Curses" by Graham Nelson The story genre is "Fantasy". The story headline is "An Interactive Diversion". The story creation year is 1993. The release number is 16. The story description is "It's become a matter of pride now not to give up. That tourist map of Paris must be up here somewhere in all this clutter, even if it has been five years since your last trip. And it's your own fault. It looks as if your great-grandfather was the last person to tidy up these lofts..." Release along with cover art and an existing story file. ## Walkthrough solutions {release_solution} ^^{walkthrough, generated from Skein} ^^{materials folder: walkthrough} ^^{release along with...+assert+: |a solution} ^^{release along with...+assert+: (public / private) elements+sourcepart+} ^^{(public / private), in release elements+sourcepart+} ^^{(private / public), in release elements+sourcepart+} ^^{user interface: Skein panel} ^^{Skein panel+ui+} Since the earliest days of IF, players have distributed solutions to well-known stories, to help out other players at their wits' ends. The commonest format for these is a list of commands to type, sometimes with notes in the margin, and such a solution is called a "walkthrough", since it walks a player through the story. Few authors publish solutions of their own works, but many supply their testers with solutions, especially towards the end of testing, or submit a solution as part of a competition entry. To help with this, Inform can generate such a walkthrough solution automatically: Release along with a solution. Inform will then place a file called `solution.txt` inside the `Release` folder. The solution might look like so (although probably much longer): ``` Solution to "Memoirs of India" by Graham Nelson Choice: INVENTORY -> go to branch (1) EAST -> go to branch (2) Branch (1) DROP MANUSCRIPT SOUTH Branch (2) INVENTORY ... Always a good idea GIVE MANUSCRIPT TO THOMAS ``` Inform does not, of course, know how to solve IF all by itself, but derives the solution from the project's Skein. Since the Skein will have been used in testing the story, it will very likely contain a perfect solution – or several different ones, taking the story to a variety of possible endings. In the example above, there are two possible winning lines, which diverge right from the first move. (There can be further divergences: for instance, if branch (2) splits, it will split into branches called (2.1), (2.2), (2.3) and so on.) But the Skein will also contain plenty of unwanted diversions, so Inform does not rewrite the entire Skein as a solution. Instead, it looks for knots in the Skein which have been annotated. Any knot whose annotation begins "***" (three asterisks) is considered to be a final, winning move. (It is probably a good idea to lock such a knot once it has been annotated thus, too.) We can mark any number of knots "***" since, after all, we can declare any number of lines of play as possible solutions. Inform then constructs the solution out of all lines of play in the Skein which lead to "***" endings, and ignores other threads. ![annots](doc_images/annots.png) Annotations other than "***" in the Skein are turned automatically into comments in the solution text. For instance, the knot for the ``INVENTORY`` command in the second branch above was annotated "Always a good idea", and this was transcribed into the solution. (If an ending knot is annotated with, say, "*** Happy ending!" then the "***" marks it as an ending, and "Happy ending!" is added as an annotation to that ending.) By default, the solution text is not linked from our webpage, on the assumption that we may want to generate a walkthrough but not immediately advertise it to players. If we wish to change this, we may write instead Release along with a public solution. The terms public and private may also be applied to other elements we are having Inform generate to include on our webpage: see also the notes on private source text, below. ## Releasing the source text {release_source} {release_card} ^^{materials folder: source text} ^^{release along with...+assert+: |the source text} ^^{release along with...+assert+: |the library card} ^^{bibliographic data} ^^{source text: releasing with the story} ^^{release along with...+assert+: (public / private) elements+sourcepart+} ^^{(public / private), in release elements+sourcepart+} ^^{(private / public), in release elements+sourcepart+} Most authors will not want to publish the source text alongside the work itself, because this gives away all of its secrets. Inform provides the option mainly for the sake of the examples published on its own website, where making the source available is the whole point. But anyone is welcome to use the option, of course: Release along with the source text. If Inform is not also generating a website, this produces a plain text file called `source.txt` in the `Release` folder, and there is nothing more to be said. However, if a website is also being released, the source is also converted to a suite of web pages which are linked to and from the home page. (Each heading with substantive content is placed on its own web page, with the opening page containing a contents list.) Comments in the source are tinted to distinguish them. As a special feature, any comment which begins with an asterisk is considered a footnote and is printed below the source text, with a link. Thus comments thus: Hercules is a demigod.[* We're using Greek spellings so he ought to be Heracles, but players are so much more familiar with Hercules.] will be printed more like so: Hercules is a demigod.[1] ... Note [1]. We're using Greek spellings so he ought to be Heracles, but players are so much more familiar with Hercules. Footnotes are automatically numbered from 1 on each source page. By default, the source text is linked from our generated webpage, if we are releasing with a webpage. If we wish to change this, we may write instead Release along with the private source text. This will create a text file containing the source for our story, and place this file in our release folder, but not create a link so that the player can find it. Finally, we can: Release along with the library card. which releases a stand-alone XML file in 'iFiction' format for the bibliographic data on the story file; this is the same data embedded in the blorb file itself, but having an external copy makes it easier to see what Inform has done, and some external programs can read iFiction data like this. ## Improving the index map {MAPHINTS} {PM_MapFromNonRoom} {PM_MapToNonRoom} {PM_MapNonLateral} {PM_MapUnknownColour} {PM_MapUnknownOffset} {PM_MapUnknownOffsetBase} {PM_MapBadRubric} {PM_MapSettingOfUnknown} {PM_MapSettingUnknown} {PM_MapSettingTooLong} {PM_MapSettingTypeFailed} {PM_MapHintUnknown} {PM_MapDirectionClue} {PM_MapPlacement} {PM_MapPlacementDirection} ^^{materials folder: map} ^^{index map: customising for release <-- |EPS file} ^^{Map page of Index panel+ui+} ^^{user interface: Index panel: Map page} ^^{Index panel+ui+: Map page} As we have seen, `Release along with...` allows us to package up a work of IF with all manner of extra materials. But what are these to be? One popular option is to produce a map – sometimes partial, sometimes obfuscated – and supply that with the story: besides, there are some IF competitions where the rules require that the referee is supplied with a map even if the players are not, and failing that, it is sometimes nice to be able to print out a map of a work in progress. The World map in the Index tab is heavily stylised and cartoonish, intended to be clicked on or moused over, and viewed in a browser: although it is, in fact, possible to print it, the results are not very good. Fortunately, the same underlying map mechanism can be used to output something more useful and very much more customisable, as we shall see. The map-maker is one of the most complex parts of Inform, even though it actually contributes nothing to the final story file: the problem of how to draw up a "correct" map from the source text is by no means easy to solve. Inform tries, but it often gets things wrong. Its general practice is to place rooms on a square grid (actually a cubic lattice, as it works in three dimensions), but not all conceptual maps fit well onto this, and Inform often annoyingly puts a particular room in the "wrong" place. For instance, suppose Inform puts `Didcot` east of `Abingdon` and this makes the geometry look different to what we had in mind. We can correct with: Index map with Didcot mapped southeast of Abingdon. Note that this says nothing about exits from any room to any other room, and changes the final work of IF not at all: it simply helps Inform to draw the map index. (Instructions like this one are treated as being almost certainly true, but Inform does not quite always obey: it will never allow two rooms to be superimposed at the same grid position, no matter what we have asked in `Index map with...` instructions.) The same trick is useful if we have a situation like so: Inside of Sweeping Sands is Beach Hut Interior. `Beach Hut Interior` is a single room which does not connect to the rest of the map by any of the ten spatial directions, so Inform does not place it on the main map but instead moves it off out of the way in a map of its own. Given that it's just a single room, however, we might prefer to put into a convenient otherwise empty grid position like so: Index map with Beach Hut Interior mapped west of Sweeping Sands. Finally, note that this trick also ensures that the two locations are mapped on the same level vertically, and can be useful in cases where room A is both north of and above room B: Inform will want A to be higher up than B, but we can insist otherwise. ## Producing an EPS format map {EPSMAP} The `Index map with...` instruction is a much more varied thing than hinted at in the previous section, and its general form is Index map with [instruction] and [instruction] and ... and [instruction]. where the instructions can be of four different forms, as follows: [room A] mapped [direction] of [room B] EPS file rubric [text] ... and some optional details ... [setting] of [whatever] set to [value] We have already seen the first of these instructions. The second is short and has a fixed wording: EPS file so can be invoked by typing `Index map with EPS file.`, for instance. EPS stands for Encapsulated PostScript, which is a standard file format for line art. EPS files can be edited with sophisticated graphics programs such as Adobe Illustrator, and can be used as illustrations in many word-processors and page layout programs. They can also be converted to PDF by Mac OS X Preview, or used in Linux or Windows with the open-source Evince viewer. We need a line-art format because the map produced will never be exactly what we want: we are probably going to end up hacking it to change the fonts, add some drawings, tidy up the spacing and so on. A really large map will end up using quite a large "canvas", in EPS terms; it may be necessary to shrink it down in order to get it onto an A4 page, or to adjust whatever editing software is used to "custom paper size". When the map-maker has been given the `EPS file` instruction, it writes an attempt to draw the current project's map in EPS format as a file in the project's `.materials` folder, with the filename `Inform Map.eps`. Note that Inform will over-write any existing file of this name: but that is intentional, because one usually ends up tweaking and rebuilding the project over and over to get the map just so, and it would be tiresome for Inform to produce endless copies `Inform Map 19.eps`, etc. (The reason the EPS file is not placed in the Release subfolder is that it is not going to releasable to the public as it stands: for one thing it will be too raw, and for another, EPS is not a format everyone can read. It is provided as raw materials.) ## Settings in the map-maker The map-maker has altogether 35 named settings, and tweaking these can affect the result in ways which vary from the subtle to the grotesque. An important point is that the map-maker deals separately with the three levels in its working: the big picture of the whole map; each of the vertical slices which contain sub-maps; and finally all of the individual rooms. For instance, we might have 67 rooms, arranged on 3 vertical levels, all shown on one big map: Inform will try to show these stacked above each other, with the highest level at the top of the map, then the middle level, then the bottom level. Moreover, not only does the whole map have its 35 settings, but each level has its own independent collection of those 35 settings, and so does each individual room. So the actual number of variables in our example is 1+3+67 = 71 times 35, which is a lot. The convention is that setting the value of S (some setting, let's say) for something affects not only that thing, but also everything inside it, unless they have their own individual settings for S. For example: one of the settings is called `room-size`, and is the size of the little square boxes representing a room, measured in points. (One point is 1/72 of an inch, so 72 points equals 1 inch: it's a traditional printer's measure.) Suppose we write: Index map with room-size set to 36 and room-size of level 2 set to 28 and room-size of the Hall of Kings set to 52. The first instruction sets the value of `room-size` for the whole map (note the lack of an `of...`); the second for level 2 of the map, and the last for a single room only. The result is that the Hall of Kings is drawn as 52x52 point box, all rooms on level 2 are 28x28 (except the Hall of Kings, if it's on level 2), and all others are 36x36, half an inch square. The setting instruction also allows three other useful forms. A setting `of the first room` applies to the room in which the story begins: we might for instance write Index map with room-outline-thickness of the first room set to 2. which gives this special room a bolder edge to it, since the default value is 1. We can also apply settings not just to single rooms but to all rooms of a given kind: A rivery room is a kind of room. Index map with room-colour of rivery rooms set to "Navy" and room-name-colour of rivery rooms set to "White". Lastly, we can apply settings to all rooms in a given region: Northern Oxfordshire is a region. Hampton Poyle and Steeple Barton are in Northern Oxfordshire. Index map with room-name-font of Northern Oxfordshire set to "Helvetica-Oblique". (Note that rooms and regions don't have their own individual sets of the 35 settings: what happens is just that instructions like the last one change more than one room at once.) ## Table of map-maker settings Note that all map-maker settings have single word names, though many are hyphenated, and that `colour` is always given the English and Canadian spelling, not the American form `color`. |Setting|Specification| |---|---| | font | font (named in double-quotes) | | minimum-map-width | integer (measured in points: 72 = 1 inch) | | title | text (in double-quotes) | | title-size | integer (measured in points) | | title-font | font (named in double-quotes) | | title-colour | colour (named in double-quotes) | | map-outline | on/off | | border-size | integer (measured in points) | | vertical-spacing | integer (measured in points) | | monochrome | on/off | | annotation-size | integer (measured in points) | | annotation-length | integer (length to abbreviate down to) | | annotation-font | font (named in double-quotes) | | subtitle | text (in double-quotes) | | subtitle-size | integer (measured in points) | | subtitle-font | font (named in double-quotes) | | subtitle-colour | colour (named in double-quotes) | | grid-size | integer (measured in points) | | route-stiffness | integer (Bezier spline curve scale factor) | | route-thickness | integer (measured in points) | | route-colour | colour (named in double-quotes) | | room-offset | offset (in percentages of grid-size) | | room-size | integer (measured in points) | | room-colour | colour (named in double-quotes) | | room-name | text (in double-quotes) | | room-name-size | integer (measured in points) | | room-name-font | font (named in double-quotes) | | room-name-colour | colour (named in double-quotes) | | room-name-length | integer (length to abbreviate down to) | | room-name-offset | offset (in percentages of grid-size) | | room-outline | on/off | | room-outline-colour | colour (named in double-quotes) | | room-outline-thickness | integer (measured in points) | | room-shape | shape (named in double-quotes) | ## Kinds of value accepted by the map-maker **Integer** values are typed in the usual way: `3`, `-72`, etc. **Text** is in double-quotes: `"Map of Lower Delta"`, etc. **Font** names are in double-quotes: `"Helvetica"`, etc. Note that Inform makes no effort to look for such fonts: if we give the name of a font we haven't got, the result will probably be that the map's ``EPS`` file will be displayed in various applications with Courier (which looks like bad typewriting) substituted. All fonts are by default equal to the global `font` setting (by default equal to `"Helvetica"`), so changing `font` for the whole map affects everything not explicitly specified as having a different font. **Shape** names are in double-quotes with lower case. At present, the only legal shapes are `circle`, `square` and `rectangle`. **On/off** values are written just thus: on, off. No quotation marks. **Offset** values are actually pairs, and are written as two numbers (possibly negative numbers) joined by an ampersand, as in the example: `Index map with room-offset of Botley set to 10&-30.` Note lack of spaces around the ampersand. This means that Botley's room is displaced from its correct grid position on the ``EPS`` map by 10% of the grid size eastwards, and 30% southwards. (The grid size is the distance between one grid position and the next: displacing Botley by -200&0 would move it two whole grid positions westwards.) The **route-stiffness** setting is used when drawing routes between two rooms. These are drawn as Bezier curves, a standard way to make a smooth curve not only travel from A to B but also from pointing in a given direction at A to ending up pointing in a given direction at B. Thus a Bezier curve may turn a route round so that it leaves A pointing west, but curves around to enter B from the south. (Most routes involve leaving in one direction and arriving in the opposite direction, of course, and in those cases a Bezier curve is just a straight line.) The stiffness factor for a given room measures how much the curves are allowed to warp around in order to force them to arrive at that room from exactly the right compass bearing. The default is 100. Raising to, say, 250 can force curved paths into freakish zig-zags: whereas lowering to 1, the minimum, may make the route arrive at completely the wrong bearing. (Formally speaking: at each end of the route, a "control point" for the Bezier curve is made by taking the centre point of the room, then adding the relevant compass bearing's vector, scaled up by the route-stiffness as a percentage of the grid size.) **Colour** values are named and in double-quotes. These names are the same as those for the traditional set of web-page-safe colour chips, as follows: - `"Alice Blue"` - `"Antique White"` - `"Aqua"` - `"Aquamarine"` - `"Azure"` - `"Beige"` - `"Bisque"` - `"Black"` - `"Blanched Almond"` - `"Blue"` - `"Blue Violet"` - `"Brown"` - `"Burly Wood"` - `"Cadet Blue"` - `"Chartreuse"` - `"Chocolate"` - `"Coral"` - `"Cornflower Blue"` - `"Cornsilk"` - `"Crimson"` - `"Cyan"` - `"Dark Blue"` - `"Dark Cyan"` - `"Dark Golden Rod"` - `"Dark Gray"` - `"Dark Green"` - `"Dark Khaki"` - `"Dark Magenta"` - `"Dark Olive Green"` - `"Dark Orange"` - `"Dark Orchid"` - `"Dark Red"` - `"Dark Salmon"` - `"Dark Sea Green"` - `"Dark Slate Blue"` - `"Dark Slate Gray"` - `"Dark Turquoise"` - `"Dark Violet"` - `"Deep Pink"` - `"Deep Sky Blue"` - `"Dim Gray"` - `"Dodger Blue"` - `"Feldspar"` - `"Fire Brick"` - `"Floral White"` - `"Forest Green"` - `"Fuchsia"` - `"Gainsboro"` - `"Ghost White"` - `"Gold"` - `"Golden Rod"` - `"Gray"` - `"Green"` - `"Green Yellow"` - `"Honey Dew"` - `"Hot Pink"` - `"Indian Red"` - `"Indigo"` - `"Ivory"` - `"Khaki"` - `"Lavender"` - `"Lavender Blush"` - `"Lawn Green"` - `"Lemon Chiffon"` - `"Light Blue"` - `"Light Coral"` - `"Light Cyan"` - `"Light Golden Rod Yellow"` - `"Light Grey"` - `"Light Green"` - `"Light Pink"` - `"Light Salmon"` - `"Light Sea Green"` - `"Light Sky Blue"` - `"Light Slate Blue"` - `"Light Slate Gray"` - `"Light Steel Blue"` - `"Light Yellow"` - `"Lime"` - `"Lime Green"` - `"Linen"` - `"Magenta"` - `"Maroon"` - `"Medium Aquamarine"` - `"Medium Blue"` - `"Medium Orchid"` - `"Medium Purple"` - `"Medium Sea Green"` - `"Medium Slate Blue"` - `"Medium Spring Green"` - `"Medium Turquoise"` - `"Medium Violet Red"` - `"Midnight Blue"` - `"Mint Cream"` - `"Misty Rose"` - `"Moccasin"` - `"Navajo White"` - `"Navy"` - `"Old Lace"` - `"Olive"` - `"Olive Drab"` - `"Orange"` - `"Orange Red"` - `"Orchid"` - `"Pale Golden Rod"` - `"Pale Green"` - `"Pale Turquoise"` - `"Pale Violet Red"` - `"Papaya Whip"` - `"Peach Puff"` - `"Peru"` - `"Pink"` - `"Plum"` - `"Powder Blue"` - `"Purple"` - `"Red"` - `"Rosy Brown"` - `"Royal Blue"` - `"Saddle Brown"` - `"Salmon"` - `"Sandy Brown"` - `"Sea Green"` - `"Sea Shell"` - `"Sienna"` - `"Silver"` - `"Sky Blue"` - `"Slate Blue"` - `"Slate Gray"` - `"Snow"` - `"Spring Green"` - `"Steel Blue"` - `"Tan"` - `"Teal"` - `"Thistle"` - `"Tomato"` - `"Turquoise"` - `"Violet"` - `"Violet Red"` - `"Wheat"` - `"White"` - `"White Smoke"` - `"Yellow"` - `"Yellow Green"` ## Titling and abbreviation The main title of the map is the value of `title` for the whole map, so for instance we might write: Index map with title set to "Oxford and its Environs". The subtitle settings apply to the subtitles used for each of the levels, so for instance Index map with subtitle of level -1 set to "Tunnels and Sewers". Names of individual rooms can be controlled with: Index map with name of Radcliffe Camera set to "Library". (By default, the name of a room is its name in the main IF project, of course.) The smallest writing on the map is normally that used to label unorthodox or unclear exits (in particular, those going from one layer to another): this is what the `annotation` size, font and colour are used for. For most ways to set up the map, it's a practical necessity to abbreviate names of rooms, or they will spill out all over each other. Inform does this using the `room-name-length` setting. (The `annotation-name-length` is analogous.) For instance, if this setting is 5, then Inform will reduce the text of a name to at most 5 characters. It does this by successively throwing out spaces, lower case vowels, then other lower case letters, punctuation marks and finally upper case letters, always starting at the back of the name and working inwards: the process stops as soon as the name is short enough. For instance, "Reading" is abbreviated to "Redng", "Shangri-La" to "Shn-La" and "Cloud-Cuckoo-Land" to "C-C-L". The result can be a little comical, but is surprisingly unambiguous in practice. Abbreviation can effectively be abolished by raising the `room-name-length` to 128 (the highest permitted level), and note that the setting can be changed for individual rooms, so it is possible to have some room names abbreviated and others not, or in different degrees. ## Rubrics Lastly, we can add our own arbitrary text to the map: perhaps to annotate points, perhaps just to add more heading matter (such as the author's name, or the date). Each individual line added – and only single lines can be added, not typeset paragraphs – is called a "rubric". (There can be up to 100 of these.) We can create a rubric like so: Index map with rubric "Here Be Wyverns" size 16 font "Helvetica-Oblique" colour "Thistle" at 150&0 from Cloud-Cuckoo-Land. This gives rather more detailed information than is needed: `size 16` could have been omitted, giving us 12-point type by default, and similarly there is no need to specify a font unless it differs from the main `font` setting for the whole map; and the colour will be black if unspecified. The `at` position does need to be given, though. Note that it is relative to a given room on the map, and that the position specified is that of the centre-point of the text. (If we had written just `at 100&100`, say, that would specify a position relative to the bottom left hand corner of the map.) So, for instance: Index map with rubric "trapped door" size 8 at -60&-60 from Longwall. would add a little 8-point-type safety tip for naive map-followers. Inevitably, the settings in the map-maker will fail to get exactly the effect desired (though they will offer an excellent opportunity to waste entire days). But that is the whole point of producing output in ``EPS`` format: Inform aims not to produce final print-ready professional art, but to produce the raw material for making that final work of art. And if all that's required is a sketch-map, then Inform's output should be good enough quickly and without too much fuss. # Publishing ## Finding a readership So the new work of IF is written, and tested, and has all its bibliographic data and a fancy cover illustration lined up. What next? Releasing and gaining attention for independent games – commercial or otherwise – is a big, complex, and constantly changing field, and other online sources will be able to provide more up-to-date information than we can offer here. However, there are some resources, events, and community spaces specifically for authors of interactive fiction and text adventures in particular. First, though, a word about terminology. For many years, the phrase "interactive fiction" referred primarily to parser-based games like the ones Inform produces by default. For those games, there has always been an avid hobbyist community, but few sales, and most parser IF writers have not felt that it would be more trouble than it was worth to charge for their games, because the income would be slight relative to the effort of setting up a storefront. In recent years, other forms of interactive fiction – those that do not rely on typed input from the player – have experienced a commercial revival. There are a number of commercial game studios that write text-rich, choice-driven stories, especially for a mobile market. Simultaneously, the communities of interactive fiction readers and players have grown and diversified. Once "the IF community" referred to a specific group of people; now, there are many communities of people who play text-based games, in various formats, with various amounts of overlap. Although it is not a typical tool for choice-based mobile games, Inform has been used to produce commercial works, both parser-based and not. Users are very welcome to sell works created by Inform with no royalty or requirement for rights clearance. It's also widely used in education, and as a prototyping tool for other kinds of stories, such as interactive narratives that will ultimately take another (not text-based) form. ## Editing and Quality Assurance ^^{editing} ^^{playtesting} ^^{quality assurance} ^^{intfiction forum+web+} Authors coming from a literary background may think in terms of editing; people coming from software development and the game industry may think about playtesting and quality assurance. Whatever the background, it's good practice to have your work checked by other people before you release it. Other players can identify issues from typos to missing hints to thematic incongruities. Play-testers can often be recruited by placing an ad on [intfiction.org](https://intfiction.org/). ## A Page of Its Own ^^{materials folder: web pages for the story} ^^{release along with...+assert+: |a website} ^^{materials folder: web-playable story} ^^{release along with...+assert+: |an interpreter} ^^{itch.io+web+} One option for sharing your work with the world is to set up a web page and a copy of the story file on a private web host. That host should ideally be as stable as possible, so that the URL is likely to remain fixed for what might be a long period. Freeware stories have a long period of viability relative to commercial games, which means that players may still be hearing about and checking out a story years after its initial release. A stable address helps everyone with links, and makes it easier for search engines to direct people. Of course creating a web page involves a little design work, but tools are widely available which make this quite easy nowadays. And as we've seen, Inform can automatically generate web pages and whole small mini-sites to put all the information about a story file into a tidy format, even including the ability to play online. A second approach — instead of or alongside giving the game its own website — is to put it on a distribution platform designed for sharing games. One of the most accessible is [itch.io](https://itch.io). While it's a lot of work to put a game on a mobile app store or on Steam, setting up a storefront at the itch.io site takes only a few minutes. Doing so enables an author to list a game for download, set a price for their work or just to accept donations of the player's choosing. A game on itch.io will still need promotion and other attention if the author hopes to make any significant amount of money, but the barriers to listing something for sale are much lower than they once were. And itch.io can be a viable way to share a game that isn't intended to charge money at all. At the time of this writing, the itch.io platform lists 28,413 games tagged "interactive fiction." ## The IF Archive ^^{IF Archive+web+} ^^{IFDB+web+} Games and interactive works in general tend to become obsolete or unplayable fairly quickly. Many games written for iOS in the mid-2010s, for instance, are already impossible to access. Because of the portable underlying format, however, games written in Inform are unusually stable and maintainable. Inform projects written in the early 90s can still be played – indeed, can be played on platforms that did not exist when the games were written. If you're interested in the longevity of your project, you may want to submit the final version to the **IF Archive**. The Archive is a mirrored, stable collection of thousands of interactive fiction games and programming languages, manuals, fanzines, maps, walkthroughs, and other materials. As such, it's likely to stay around even if a personal website goes off-line; it's also the primary resource for people doing scholarship on interactive fiction (and there are a growing number of these). The Archive is very much a library, for long-term archiving, rather than a book-store. The catalogue is sober and textual, and there are no visual shop-windows, or posters advertising new titles hot off the press. Newcomers sometimes need practice finding their way around. And the Archive hosts story files (and associated manuals, as appropriate) but not advertising for them – it does not provide web-hosting for authors to set up mini-sites. Uploading a work to the IF Archive is not too difficult, and can be done in two ways. One way is the [IF Archive upload web form](https://upload.ifarchive.org/cgi-bin/upload.py). The other is to create a new page at the [Interactive Fiction Database](https://ifdb.org). It's then possible to upload the story file to the IF Archive from IFDB. This is easiest all round, since it allows both IFDB and IF Archive to be updated at once. In either approach, an author chooses and uploads a file, and accompanies it with a name and email address (so that the archive maintainers can verify the legitimacy of the work). The "About this file" field is for a line or two explaining what the story is – its full title and any critical information – and is used in generating the archive index. This is normally much shorter than the "blurb" described earlier. There's also a field to suggest where in the archive the story should be stored, but this is optional and intended chiefly for people expert in how the archive is filed. The archive maintainers will file a new story file in the obvious directory for its format. For Inform works, that means other Z-Machine – "z-code" – or Glulx story files. The maintainers sometimes place the same story file in multiple places in the Archive, using links. As with all large libraries, it takes the Archive a little while for new acquisitions to be processed. When this happens, one of the volunteer maintainers will email with the official URL from which anyone can now download the story file. Committing a story to the Archive is meant to be permanent. While the maintainers will happily replace older versions of stories with new improved releases, they are less eager to remove stories entirely. If that doesn't seem appealing, or if we do not want our story to be treated as freeware with essentially unlimited distribution, the Archive may not be a good choice. But it is deeply valued by the IF community, and has saved many works which could otherwise easily have been lost forever. Many contributions important in the history of IF were made by people who are now not easy to trace, and whose websites are long gone. But their work lives on. ## IFDB: The Interactive Fiction Database ^^{IFDB+web+} ^^{IFID+biblio+} ^^{IF Archive+web+} ^^{>VERSION} Once the story file has a home online, and a URL (that is, a web address) at which it can be found, it needs to be registered with the [Interactive Fiction Database](https://ifdb.org) (IFDB). Just as the IF Archive is a repository for stories themselves, IFDB is a database containing information about them – titles, authors, locations, solutions, reviews, recommendation lists and more. The name IFDB echoes the Internet Movie Database (IMDB), but in some ways it is also like the iTunes Music Store. For one thing, it's a shop-window for what's new, with cover art to catch the eye. For another, IFDB serves as a portal for players to try games directly in their browser. Promoting IF is all about pulling in impulse players – people who are passingly interested, but might not try the story if there is any significant work involved in setting it up. This is what IFDB is all about. IFDB is community-editable, like Wikipedia, though editors are required to create an account and log in first – this is free, of course. A standard form is provided for creating a new record (accessible by selecting the option to add a story listing). More or less the same information that appears on Inform's library card in the Contents index needs to be copied over: there's space for the author name, story title, genre, and so on. IFDB will also ask for an IFID, a code identifying the story uniquely. Inform generates one of these automatically for each project, and it, too, is on the Library Card. It can always be found by typing ``VERSION`` into the compiled story and looking at the line that says ``` transcript Identification number: //[some letters and numbers]// ``` The part between the // marks is the IFID. If there's cover art, that can also be uploaded, and good cover art makes a big difference to shop-window-appeal. The download link should give the most stable URL available. If you have not yet uploaded your story to the IF Archive, you may do so by selecting the "Upload it to the IF Archive" link instead of pressing the "Add a Link" button. The benefits of submitting your story to the IF Archive in this manner are two-fold. One, IFDB will fill in much of the information required by the IF Archive for you. Two, the link to your story will not appear until the IF Archive maintainers move it to its permanent home in the archive, at which point the download link will be automatically updated and presented on the story page. If you choose to upload your story file to the IF Archive independent of IFDB, then once the story file is safely up at its permanent home on the IF Archive, that is an ideal address to quote here. Otherwise, the URL of the work's own website is best. (Note that the IFDB entry can always be edited later, if the URL moves.) Commercial works which aren't available as free downloads can be registered on IFDB just the same, and this is almost certainly a good idea. Some awards for interactive fiction, such as the annual XYZZY Awards, require a game to have an IFDB entry as an eligibility requirement. ## Competitions, Exhibitions, and Jams ^^{ifwiki+web+} ^^{XYZZY} ^^{itch.io+web+} ^^{ProcJam} One very common way to get players for IF is to enter the story into an IF competition. The annual IF Competition, often just called IFComp, is the most prestigious and has the widest field, but the Spring Thing, ParserComp, EctoComp, and other events also catch people's attention. Entering a competition is a path of least effort for authors promoting their new work, because the competition organiser usually takes care of hosting and archiving submitted stories, promoting the competition as a whole, collecting votes, and encouraging players to post reviews. Different contests have different arrangements. The [IFWiki](https://ifwiki.org) usually posts a list of current and upcoming competitions, as well as lists of results for those recently past, on its front page. Some competitions also have their own websites, at least at the relevant times of year. All the same, there are many IF works that aren't cut out for competition release. Competitions tend to be best for short or medium-short works, because judges don't necessarily have time to play a lot of long stories at once, and sometimes this is a condition of entry. It's also good for publicity to win one of the annual [XYZZY Awards](https://xyzzyawards.org). All interactive fiction stories released in a given year are eligible, as long as they are listed on IFDB. Meanwhile, itch.io hosts many jams every year. A small handful of these are specifically intended for interactive fiction or parser-based adventures, but there are many other jams that allow entrants to put up any game with an appropriate theme, regardless of its format. The [itch.io Jams Calendar](https://itch.io/jams) lists the jams that are coming up. Finally, if your project is heavily focused on procedural generation – creating or remixing elements on each playthrough – then it may have a natural home at [Procjam](https://www.procjam.com/), a yearly event to "make something that makes something", and welcomes all kinds of generative projects, whether they are games or not. ## Meetups and Conferences There are a number of different local groups that get together to play or discuss interactive fiction, including a number that hold remote meetings. Announcements of some of these can be found at the [IntFiction events category](https://intfiction.org/c/general/events/47). Joining these groups may provide a context to discuss work in progress, and many are willing to do a group playthrough of games written by group members. There are also a range of conferences that accept talks or presentations about interactive fiction, both academic conferences and conferences adjacent to the game industry. While it is not a complete listing, [Emily Short's blog](https://emshort.blog/) attempts to link upcoming events. ## A short concluding homily It's natural to want to make a huge splash with a story, but in the IF community, instant widespread adulation for any work is pretty uncommon. For one thing, players tend to play when they get around to it... which may be weeks, months, or even years after the initial release. Reviews trickle rather than flooding in. Appreciation builds slowly. And sometimes works that placed unspectacularly in a competition, or seemed to be overlooked in the annual ^{XYZZY} Awards, gradually come to be regarded as classics because of some pioneering technique. So it's wise (if difficult) not to judge a story's success entirely by its immediate feedback. Even after its debut, a story can often use a little care and attention if it's to reach all its potential fans – whether that means building further releases, posting hint files or walkthroughs, developing new websites, or approaching outside reviewers. # Extensions ## Developing extensions The remaining chapters of this book are about building new extensions which can be shared with other story authors. The material in these final chapters will be steadily more technical as we engage with lower and lower-level parts of Inform. To develop a new kit, for example, calls for some traditional computer programming skills, and some experience of writing code in the Inform 6 language. But only very advanced extensions need to use a kit. Simple extensions are actually quite easy to make, and need no knowledge of Inform 6 at all. How to write that everyday sort of extension will be the subject of this first chapter. In this chapter, we'll take on the role of Peter Drake, an Inform author who wants to package up the following minimal piece of design as an extension: Ducking is an action applying to nothing. Understand "duck" as ducking. Report ducking: say "You duck!" Of course this is much too small to be worth making an extension of, but it will serve as an example. One way in which it _is_ typical of extensions, though, is that it adds something to the usual Inform stock of actions or phrases, but doesn't create any specific rooms or things. So it could in principle be included in all kinds of different stories, to give them a ducking action. As is typical of extension-writing, there are some definite rules about the title and author name, which Inform enforces, but there are also good-practice guidelines which are not enforced. In this chapter, we'll try to cover both. Extensions are designed to be shared, and community norms make that sharing more practical. ## Review of how extensions are used {EXTENSIONS} {SRULES} ^^{Standard Rules+ext+} ^^{extensions: specific extensions: Standard Rules} ^^{Basic Inform+ext+} ^^{extensions: specific extensions: Basic Inform} ^^{English Language+ext+} ^^{extensions: specific extensions: English Language} ^^{extensions: installing} ^^{files (compiling): extensions} ^^{extensions: built-in extensions} ^^{extensions: project-installed extensions} ^^{materials folder: project-installed extensions} ^^{inform7.com+web+} Extensions are identified by the combination of their title and author name, and sometimes by a version number as well. `Locksmith by Emily Short` is an extension; version 11 is one of the various versions it has had over the years. An extension becomes part of a story by being _included_. Three extensions are usually included by Inform, in a silent and automatic sort of way: - `Basic Inform by Graham Nelson`. This sets up the fundamentals of the Inform language, and defines phrases for dealing with data like text, lists and real numbers. - `English Language by Graham Nelson`. This is needed for the story to use English as its language of story-telling with the player. If the story were to be in some other language, a different extension would be substituted. - `Standard Rules by Graham Nelson`. This sets up the kinds and properties used in the world model for interactive fiction: rooms, doors, directions and so on. In so-called "basic projects", which do not have a command parser and are not games, the Standard Rules are not included. Other extensions are included only because the source text calls for them: Include Locksmith by Emily Short. Note, though, that extensions contain source text too, and can also have `Include` instructions like this: so one extension can call for another one to be included as well. It's not an error to make multiple requests for the same extension, but that extension is then included only once. This means it is quite safe for extension A to ask to include extension B, and for extension B to ask to include extension A. This will not cause infinite regress: it will simply mean that both are included. The one restriction here is that the same project cannot simultaneously include two different versions of the same extension. If Inform has both version 13 and version 15 of `Locksmith by Emily Short` available to it, it will make a choice of which to include, and will not include both. (Unless told otherwise, it will choose the one with the higher version number.) Where do these extensions live? Except for the three special cases above, Inform now always looks for them in the ```Extensions``` subdirectory of the project's "materials" folder. Extensions filed there are said to be _installed in the project_. Long-time Inform users might be expecting extensions to be installed in some cache stored elsewhere on the computer, but as of 2023 we no longer do that, and all extensions used by a story should be installed in the project. (A project can have extensions installed which it is not currently using, and can even have multiple versions of the same extension installed.) Experienced users might also be expecting to see the extension as a single file with a filename like ```Locksmith-v15.i7x```. That's still supported, but now deprecated. Modern extensions occupy directories — the ```d``` at the end of ```Locksmith-v15.i7xd``` stands for "directory". When distributed on the Internet, this may well be zipped up as `Locksmith.zip` or similar. The Inform app has the ability to download such a file, unzip it, identify its identity and version, and install it. But this can also be done by hand, of course. The Extensions tab in the Inform app displays details of all of the extensions installed in a project, and whether they are currently being used or not. It's accompanied by the Public Library tab, which allows other extensions to be downloaded directly from the Public Library into the project. ## Title and authorship ^^{extensions: writing: author+biblio+} ^^{author+biblio+: of an extension} ^^{extensions: writing: title+biblio+} ^^{title+biblio+: of an extension} ^^{bibliographic data: in extensions} In this chapter, we'll take on the role of Peter Drake, an Inform author who wants to package up the following minimal piece of design as an extension: Ducking is an action applying to nothing. Understand "duck" as ducking. Report ducking: say "You duck!" Of course this is far too small to be worth making an extension of, but it will serve as an example. It's typical of extensions in that it adds something to the usual Inform stock of actions or phrases, but doesn't create any rooms or things. It could in principle be included in all kinds of different stories, to give them a ducking action. The first task is to work out a name for the extension, which is a combination of title and author name. Here are some considerations: 1) The name of an extension, and of an author, should be written in using upper case on the first letter in each word. For example `Points Of View by Dino Di Maggio` is allowed, but note that it is `Of` not `of` and `Di` not `di`. (Having a definite rule about upper and lower case minimises problems on machines where filenames are read with case sensitivity.) 2) However, author names can include upper-case letters within words, so for example `Scrooge McDuck` is a valid author name. 3) Where possible, accented or unusual letters should be avoided in titles and author names, but they can in principle use any of the standard ISO Latin-1 characters. `Étude Pour La Fênetre by Françoise Gauß` is legal. 4) The title must not start with `The`, nor contain the words `by` or `version`, nor contain punctuation. Thus `The Stock Market` is illegal, but `Stocks And Shares` is fine. The title must not exceed 50 characters in length, including any spaces between words. 5) Titles should aim to give a straightforward description of the function of the extension, rather than cryptic allusions or puns. Because extensions are identified by title and author name in combination, there is no need to worry about making the title so distinctive that nobody else would ever use it. It causes no problems if John Smith and Mary Brown each write extensions called `Following People`, because one is `Following People by John Smith` and the other `Following People by Mary Brown`. 6) The author name must not start with `The`, nor contain the words `by`, `and` or `version`, nor contain punctuation, and must not be the word `Reserved`. Thus, `John X. Doe` is illegal, but `John X Doe` is fine; `The Edge` is illegal, but `Megan Thee Stallion` is fine. The author name must not exceed 50 characters in length, including any spaces between words. 7) Whenever possible, authors should use real names rather than cryptic handles like `Ifguy`, and to use genteel, plausible pseudonyms like `Emily Short` rather than, say, `Drooling Zombie`. 8) Authors should try to use the same author's name for all their own extensions, and (it should go without saying) should not masquerade as anybody else. For our example extension, rule (5) suggests we should call it just "ducking action", since that's what it provides. Rule (1) says we should capitalise to `Ducking Action`, and that's clearly okay under rule (4), since it's much shorter than 50 characters and contains none of the forbidden words. The author name is easy too: `Peter Drake`. So the example extension will be called `Ducking Action by Peter Drake`. ## Creating a new extension ^^{extensions: writing: example} To create a new extension, it's first sensible to create a host project which can try it out. The nascent extension then stays installed in that host project until it's ready to ship out to the world. So, let's begin with a project like so: "Ducking Test" [Include Ducking Action by Peter Drake.] The Village Pond is a room. Test me with "duck". Note that the inclusion is commented out by the `[` and `]`, since there's not yet an extension to include. We save this as, say, ```Ducking Test.inform```, then run it, which ensures that ```Ducking Test.materials``` is created too. In fact, it already has some contents: ``` code Ducking Test.inform Ducking Test.materials Extensions Reserved Release ``` We then need to create three further subfolders (also known as subdirectories), so as to get to this layout: ``` code Ducking Test.inform Ducking Test.materials Extensions Peter Drake Ducking Action-v1.i7xd Source Reserved Release ``` That is, we create an ```Extensions``` subfolder of the materials folder, then a ```Peter Drake``` subfolder of that, then a ```Ducking Action-v1.i7xd``` subfolder in turn, and finally, at the centre of these Russian dolls, a ```Source``` subfolder. So now we create a text file called ```Ducking Action.i7x```, which reads as follows: Version 1 of Ducking Action by Peter Drake begins here. Ducking is an action applying to nothing. Understand "duck" as ducking. Report ducking: say "You duck!" Ducking Action ends here. This should be a plain text file. It is sometimes said that "there is no such thing as plain text", there being so many ways to represent exotic characters: so to be precise, the source should be a text file with the Unicode UTF-8 encoding, either with or without a BOM marker, using any of the possible forms of line-ending (Unix, Windows, Macintosh, or Unicode line divider). But this is a detail which will only matter if the extension contains accented letters or other exotica. The default settings on any modern text editor will likely be fine. We save this file, and so now we have this setup: ``` code Ducking Test.inform Ducking Test.materials Extensions Peter Drake Ducking Action-v1.i7xd Source Ducking Action.i7x Reserved Release ``` We can now uncomment the `Include` line in the test project: "Ducking Test" Include Ducking Action by Peter Drake. The Village Pond is a room. Test me with "duck". When we run it again, the whole thing should now work: > TEST ME (Testing.) >[1] DUCK You duck! And that's it: a fully-functioning extension has been made. ## JSON metadata ^^{extensions: writing: metadata in JSON} ^^{bibliographic data: in extensions} Having got the `Ducking Action` extension working, in a minimal sort of way, we might now look again at the files being stored under the surface. ``` code Ducking Test.inform Ducking Test.materials Extensions Peter Drake Ducking Action-v1.i7xd extension_metadata.json Source Ducking Action.i7x Reserved Release ``` This is as before except that a new file, ```extension_metadata.json```, has appeared out of nowhere. JSON is an interchange format for computer programs to use when sending information to each other. If we look at this file, it reads: ``` code { "is": { "type": "extension", "title": "Ducking Action", "author": "Peter Drake", "version": "1" } } ``` In practice, extension authors can just forget that this file exists most of the time. Some low-level extensions will need to add various other pieces of information to it, but most extensions won't. If the extension title, author or version are changed, Inform will automatically correct ```extension_metadata.json``` to match the change. The commonest way that happens, in fact, is when the version number changes. Suppose we want to make an update to version 2. Suppose we correct the extension source so that it reads as follows: Version 2 of Ducking Action by Peter Drake begins here. Ducking is an action applying to nothing. Understand "duck" as ducking. Report ducking: say "You duck! Twice!" Ducking Action ends here. When we run the test project again, it once again works: > TEST ME (Testing.) >[1] DUCK You duck! Twice! But if we then look back at the files under the hood, we find that the folder previously called ```Ducking Action-v1.i7xd```, which held the extension, has now been renamed ```Ducking Action-v2.i7xd```, and also that the JSON metadata has become: ``` code { "is": { "type": "extension", "title": "Ducking Action", "author": "Peter Drake", "version": "2" } } ``` So the upshot of this technical little section is... that we can basically forget about the JSON metadata for the moment, and let it do its own thing. ## Begins here and ends here {PM_ExtMultipleBeginsHere} {PM_ExtBeginsAfterEndsHere} {PM_ExtMultipleEndsHere} {PM_ExtNoBeginsHere} {PM_ExtNoEndsHere} ^^{(extension) begins here+assert+ --> begins here} ^^{(extension) ends here+assert+ --> ends here} Here is where we've got to, then, with the extension source text: Version 1 of Ducking Action by Peter Drake begins here. Ducking is an action applying to nothing. Understand "duck" as ducking. Report ducking: say "You duck!" Ducking Action ends here. Note that the extension has to begin and end with special sentences. These act rather like headings (`Chapter 3`, say) in the main source text, but of course the `begins here` sentence contains important identifying information. Note that: 1) The `begins here` sentence must be placed as the only content of line 1 of the file. It must not contain comments in square brackets, and it must not break across multiple lines. If the extension began like this, Inform would refuse to include it: Version 1 of Ducking Action by Peter Drake begins here. 2) There must of course be exactly one `begins here` line, and exactly one `ends here` line. 3) Until 2023, it was common for extensions to place documentation underneath the `ends here` line, after a conspicuous tear-off marker line `---- DOCUMENTATION ----`. There is now a much better system for documentation: see [Extension documentation and testing]. 4) Other than this old style of documentation, which is now deprecated, no content is permitted below the `ends here` line. So it really should be at the end of the file. 5) In case the extension's title is a plural, we are allowed to write `begin` and `end` instead of `begins` and `ends`. For instance, this is fine: Version 2.34 of Projectile Rules by Jane Mallard begins here. Projectile Rules end here. We have already seen that there are rules about the title and the author name, and we turn next to the version number. ## Version numbering {PM_ExtVersionTooLow} ^^{version number (of extension)} ^^{extensions: writing: version number} ^^{extensions: using specific versions} ^^{extensions: listing credits for} ^^{>VERSION} ^^{use options: catalogue: |authorial modesty} ^^{authorial modesty+useopt+} At this point, let's take a closer look at the opening words of our extension. The first line reads: Version 1 of Ducking Action by Peter Drake begins here. Inform used to be very relaxed about version-numbering of extensions, but that turned out not to be good idea in the long run. In particular: 1) The version number is actually optional, so that it would be legal to just start with `Ducking Action by Peter Drake begins here.` This is now very much deprecated. Version numbers are our friends. Every extension on the Public Library is required to have a version number. 2) Before 2022, extensions were sometimes given version numbers in the form `N/YYMMDD`, as in this example: Version 6/040426 of Crossbow Bolts by Jane Mallard begins here. The material after the slash '/' was expected to be a date, so that `040426` would mean 26 April 2004. In order to preserve compatibility with old extensions like this one, Inform continues to allow this notation, but treats it as equivalent to writing `N.0.YYMMDD`, though with any leading 0s trimmed. So the above sentence is equivalent to writing: Version 6.0.40426 of Crossbow Bolts by Jane Mallard begins here. This `N/YYMMDD` is now deprecated, and no new extension should use it. The reason for the version number, of course, is that most extensions exist for some years, and are improved or maintained from time to time. This means that multiple different states of the extension will have been circulated on the Internet. If these different states have different version numbers, it will be possible for people to tell which one they have, and whether they need to update. So any authors sharing an extension with the public has an obligation to keep good version-numbering habits. Here are the considerations to follow: 1) Version numbers should consist of one to three whole numbers divided by dots, with no negative numbers allowed. Thus `5`, `3.3` and `2.1.71652` are all valid as version numbers, but `-4` and `3.1.2.5` are not. Any numbers not specified are taken to be 0: thus `3.3` means the same as `3.3.0`, and `5` means the same as `5.0.0`. 2) A shared community policy on version numbering is a huge help to extension users, so it's helpful for us all to agree on what good version-numbering is. Because of that, the Inform project follows a widely-recognised Internet standard called _semantic version numbering_, or _semver_ for short. For full details see [semver.org](https://semver.org), but the notes given here should be enough for our fairly simple needs. "Semantic" just means that version number changes should communicate something meaningful. So, whenever an extension author puts out a new version of an extension, the extension number should change in a way that signals how drastic the change will be. 3) In this system, the three possible numbers `X.Y.Z` are called the _major_, _minor_ and _patch_ numbers. Traditional semver rules say that all three should always be given, but as noted, Inform allows patch and minor numbers to be omitted for brevity. Our extension `Ducking Action by Peter Drake` had version number just given as `1`, but this was an abbreviation for `1.0.0`. 4) Every time an extension is changed and re-released, even just informally among friends but certainly if posted somewhere on the Internet, at least one of `X`, `Y` or `Z` should change — even if the amendment to the extension is something tiny and unimportant, like a typo fixed in its documentation. The rules are: - If the extension has changed so much that Inform projects using it will need to be changed in order to keep on working – for example, if a `To...` phrase has been taken out, or the name of a kind changed – then X should be increased. Y and Z then usually go back to 0. This is a _major version_. - If the extension provides new features but doesn't do anything to change the way its existing features are used, then X can stay the same but Y should increase, and Z then usually rolls around to 0. This is a _minor version_. - If the extension has changed only to fix bugs, or make its existing features work more efficiently, or provide better documentation or examples, then X and Y can stay the same but Z should increase. This is a _patch version_. 5) Because of the `(in place of ...)` feature covered later in [Extensions with different source text for different uses], any change of the names of the headings in the extension's source text — or movement of material between them — must be considered a major change. Creating new headings, however, is minor. 6) The full semver standard allows "annotations" to be added after the numbers, with a `+` or `-` character thrown in: thus, `10.2.0-beta+6X42` is a legal semver. Extensions should not do this. What do we gain from these rules? Firstly, if a user has two different copies of the same extension, they can at the very least tell which one is later. `3.2.7` is later than `3.1`, for example. Secondly, a user who currently has version 3.2.7 knows that an update to 3.2.8 can be made without really investigating. That same user can even update to 3.3, 3.4, ... without any trouble, choosing either to use or ignore whatever new features they are presenting. But the user knows that moving up to version 4 might well require some work – a project using version 3.5.1 will likely need writing to adopt version 4. Thirdly, a single project can have multiple versions of the same extension installed. On any given run, it can only use of them, but it can have several to choose from. As the author of `Ducking Action`, Peter Drake might want to keep back versions around in his test project ```Ducking Test.inform```, like so: ``` code Ducking Test.inform Ducking Test.materials Extensions Peter Drake Ducking Action-v1.i7xd Ducking Action-v1_1.i7xd Ducking Action-v1_2.i7xd Ducking Action-v2.i7xd Ducking Action-v3.i7xd ``` That might make it easier to test in which version a newly-discovered bug had appeared, for example. Note that when Inform reads this in the source text of the test project: Include Ducking Action by Peter Drake. ...it will then have to choose which of the versions installed it should use. By default, it will choose the one with the highest version number, so it will use ```Ducking Action-v3.i7xd```. But that can be overridden: Include version 1.1 of the Ducking Action by Peter Drake. This will only accept an extension if its version number is _compatible_ with 1.1, which means, if it is 1.1 _or later_, but still belongs to the same major version, 1. Perhaps surprisingly, then, this `Include` causes Inform to load ```Ducking Action-v1_2.i7xd```, because 1.2 is the highest version number available which is compatible with 1.1. ## Extensions including other extensions ^^{extensions: writing: including other extensions} Extensions can themselves contain `Include...` sentences asking for other extensions to be included. For example, suppose `Ducking Action` requires `Crossbow Bolts by Jane Mallard`. The obvious thing is to write: Version 1 of Ducking Action by Peter Drake begins here. Include Crossbow Bolts by Jane Mallard. ... And indeed if we are very confident that `Ducking Action` can work with any version of `Crossbow Bolts` which has ever existed, or is likely to exist, then that is fine. But suppose `Ducking Action` will only work with version 8. Then it can begin like so: Version 1 of Ducking Action by Peter Drake begins here. Include version 8 of Crossbow Bolts by Jane Mallard. ... If an extension does include other extensions, it is good style to place the `Include...` sentence(s) as early as possible after the introductory sentence. The build manager inside Inform, a component called ```inbuild```, can spot such a requirement wherever it occurs, but human readers often fail to notice them if they're not at the top of the file. An inclusion like this is sometimes called a _dependency_, because `Ducking Action` now depends on `Crossbow Bolts` in order to work. Following the semantic versioning standard, Inform will then try to include any version of `Crossbow Bolts` which is _compatible_ with version 8: so it will accept version 8, or 8.0.3, or 8.1, and so on, but not version 9 or above. That seems rather strict, but it's a consequence of the semver rules. If Jane Mallard has bumped her major version number to 9, that's a signal that her extension has broken its existing compatibility by changing how things behave in an important way. This underlines the moral that semver works best when everybody does it: if Jane has simply bumped 8 to 9 after a slight and unimportant change, she may be causing unnecessary work for other people. Peter Drake would have to change the above `Include` line, for example, in `Ducking Action`. It sometimes happens that the same project asks to `Include` the same extension multiple times. For example, if the project `Lily Pond` contains `Include` lines for both `Ducking Action` and `Crossbow Bolts`, and `Ducking Action` also requests `Crossbow Bolts`, that means it has been requested twice. This is fine if the version numbers in the requests can be reconciled, but sometimes they can't. For example, this pair is compatible: Include Crossbow Bolts by Jane Mallard. Include version 8 of Crossbow Bolts by Jane Mallard. And so is this: Include version 8.2.4 of Crossbow Bolts by Jane Mallard. Include version 8 of Crossbow Bolts by Jane Mallard. But this pair is not: Include version 9.5 of Crossbow Bolts by Jane Mallard. Include version 10.3 of Crossbow Bolts by Jane Mallard. because all versions compatible with 9.5 have major version number 9, and all versions compatible with 10.3 have major version number 10. So it is not possible to satisfy both, and Inform will produce a problem message. ## Extension rubrics ^^{extensions: writing: rubric+biblio+} ^^{rubric, of an extension+biblio+} ^^{>VERSION} It's very helpful for an extension to be accompanied by a brief description of what it does, so that a user browsing through lists of extensions can see more than just the title. This is called a _rubric_. Every extension should give a rubric. It's written as a double-quoted text placed immediately after the beginning sentence, and with no intervening comments. For example: Version 1 of Ducking Action by Peter Drake begins here. "An action for ducking one's head, to avoid a projectile or pass under a low doorframe." Ducking is an action applying to nothing. Understand "duck" as ducking. Report ducking: say "You duck!" Ducking Action ends here. A few considerations about rubrics: 1) Rubrics are never printed in play, and they cannot make use of text substitutions in square brackets. 2) A rubric should not exceed 500 characters at the outside, and should if possible be shorter than that. Most extensions can be summed up fairly in a sentence or two. 3) The rubric is a good place to explain the title, if there's any ambiguity. For example, "ducking" might suggest skipping a class, or a meeting, or avoiding some task. The text "to avoid a projectile or pass under a low doorframe" above makes clear that we mean something more physical and in-the-moment. A second double-quoted text can also, optionally, be added in yet a third special starting paragraph. This is to provide additional credits to people who have contributed to this or earlier versions. For instance: "based on original Inform 6 code by Marc Canard" Note the typical style here: it's a phrase rather than a sentence, and neither starts with an upper-case letter nor ends with a full stop. (The additional credit is then used in documentation and also in the ``VERSION`` text of any Inform story file using the extension.) ## Licence ^^{extensions: licencing of use} ^^{>VERSION} First, though, a word about sharing. Anyone is free to write an extension on any terms or for any reason, of course, and some writers develop private extensions of their own, to be used only in their own stories, or to be used by collaborators whom they know well. But most extensions are written to be shared with strangers — that is, they are made available to anybody who wants to download and use them. There are several online repositories of extensions written in this way, of which one is the Inform Public Library, accessed from the Inform app. ### Credits for extensions During play of any story compiled by Inform 7, typing ``VERSION`` (or ``COPYRIGHT``) lists various serial numbers of the pieces of software used to make it. The list concludes with names, authors and version numbers of any extensions used. So every author whose work contributes to a story automatically gets a modest credit within it. The licencing terms for those extensions are also given. The same list can be printed, at the discretion of the designer, using the textual substitution: > phrase: {phs_extcredits} say "[the/-- list of extension credits]" > > This text substitution expands to one or more lines of text crediting each of the extensions used by the current source text, along with their version numbers and authors. Extensions whose authors have chosen the `use authorial modesty` option are missed out (unless they declare a licence, in which case that licence is still mentioned, since it may be a legal necessity). If we want our extension to go uncredited – perhaps if it is a low-level enabling sort of thing, for instance – we can place the following sentence inside the definition of the extension: Use authorial modesty. The same sentence placed in the body of a source text causes all extensions by the same author as the main source text to go uncredited. In other words, if Isaac Miggins writes a source text and includes, say, Unlikely Events by Isaac Miggins, then this extension will go uncredited in the ``VERSION`` command. A complete list, undiluted by modesty, can always be obtained using: > phrase: {phs_compextcredits} say "[the/-- complete list of extension credits]" > > This text substitution expands to one or more lines of text crediting each of the extensions used by the current source text, along with their version numbers and authors. Every extension is included, even those whose authors have opted for `use authorial modesty`. Whenever one author copies or adapts programs or text by another author, copyright law comes into play. If we want to publish or sell a story which uses an extension by somebody else, we need their permission. The form that permission usually takes is a general _licence_ (or "license", in US English) where the extension author says, in effect: Anybody can use this provided ... and then gives some conditions. ### Open-source licences for extensions The source text for an extension can contain special sentences which specify its licence, that is, the terms on which other Inform authors can use it. For example: The licence for this extension is "CC-BY-4.0". The copyright for this extension is "Emily Short 2006-2024". The origin for this extension is "https://www.emshort.com/inform". The rights history for this extension is "Adapted by permission from sample code by Adam Cadre in 2006." Those are the only four things which can be set — `licence` (or the spelling `license` is also allowed), `copyright`, `origin` and `rights history`. All four are optional. - The `licence` must be _either_ `"Unspecified"` _or_ one of the standard SPDX machine-readable licence codes listed at: [https://spdx.org/licenses/](https://spdx.org/licenses/) — see below for notes on what to choose. Inform will throw a problem message if the licence is now deprecated by SPDX, usually because it has been found to be legally problematic in practice, and better versions are now available. Note that the SPDX list contains only open-source licences: if we don't want to open the source of an extension we should leave the `licence` at the default setting `"Unspecified"`. - The `copyright` declaration must take the form `"Owner's Name YYYY"`, where `YYYY` is a year after 1970, or else `"Owner's Name YYYY-ZZZZ"`, to indicate that it was created in year `YYYY` and most recently refreshed or rewritten in year `ZZZZ`. Note that it must not contain a `©` symbol, or text like `(c)` or `(C)` or `Copyright`: that's added later automatically. It should just give the owner's name and a date. Both a name and a year are required: Inform rejects `"2020"` or `"Emily Short"` with problem messages because of this. - The `origin` is the URL for the home web page of the extension, if there is one. Note that some popular licences, such as `CC-BY-4.0`, require users of the software under licence to reproduce the URL of its home page. If this URL is given, then Inform takes care of that requirement automatically. - The `rights history` should be one or more complete sentences explaining any other _legal_ notes necessary. Less is more here, but if, for example, we are making a new version of some old code by somebody else (and if their licence allows that, of course), then we should credit that. The `rights history` should not be used for miscellaneous acknowledgements, just for what's legally required. If one of the other four settings is made, but no `licence`, it defaults to `"Unspecified"`. If one of the other four settings is made, but no `copyright`, it defaults to the name of the author (given in the extension title, or the title sentence for a story) and the current year of compilation. `origin` and `rights history` are both blank by default. ### Licences accepted by the Inform Public Library The best way to share an Inform extension with the world may be to submit it to the Inform Public Library. This is a curated collection, rather than being a service anyone can publish on, and the curators are looking for generally useful extensions whose subject matter will be suitable for users of all ages, and will not run into legal difficulties. Inform is widely used in education, so the Public Library may be being browsed in classrooms by young children. The Public Library also aims to host extensions which users can grab and make use of without legal worries, so it can only accept licenced extensions, and for policy reasons it will only accept a short list of simple, easily understood, popular and highly permissive licences — currently, six are allowed. This is many fewer than the full SPDX list, which currently includes some 617 non-deprecated open-source licences. But many of those are obscure enough that there's no case law on them, or else they are trying to achieve particular policy goals: the `BSD-3-Clause-No-Nuclear-Warranty`, for example. Not all are certified as "free" or "open" by the two bodies usually considered authoritative, the Free Software Foundation and the Open Source Initiative. And even those which are rated both "free" and "open", which are reasonably popular, and which have no obvious axe to grind, may not be sufficiently free for all of our users' needs. If we want to open-source an extension, leave users almost completely free to use it, but still keep the copyright and require users to acknowledge that, then the following can be used: Licence code | Full name ---------------- | --------- `"MIT"` | MIT License `"CC-BY-4.0"` | Creative Commons Attribution 4.0 International `"Artistic-2.0"` | Artistic License 2.0 Extensions licenced on these terms can safely be used since Inform automatically complies with the need to acknowledge in its handling of the ``COPYRIGHT`` and ``LICENCE`` commands, and also when releasing a project. For example, if it releases a story to a website, that website will include a page of copyright acknowledgements. If the `MIT` licence is used, the text of that licence is included on this website page, which satisfies its only other requirement. `Artistic-2.0` only makes this list because it is the licence used for the source code to Inform itself, and so the built-in Inform extensions — the Standard Rules, Basic Inform and English Language — are covered by that automatically. It was designed for large pieces of software with a range of uses (it began as the licence for the Perl programming language), and is not a good fit for stand-alone extensions, since it has a relatively long and convoluted legal text. `CC-BY-4.0` is better known and more widely used, but some people feel it's better suited to pictures and text than to software, where `MIT` is much more widely used. The above all require attribution, and retain copyright. If we want to go further, the following are also available: Licence code | Full name ------------- | --------- `"MIT-0"` | MIT No Attribution `"CC0-1.0"` | Creative Commons Zero v1.0 Universal `"Unlicense"` | The Unlicense Here `MIT-0` is a halfway-house: the author does still retain copyright, but the user doesn't have to acknowledge that. This would be a good fit for a `Use authorial modesty.` sort of extension. (As with `MIT`, Inform auto-includes a copy of this licence as part of any website release, since that is still required.) Under `CC0-1.0` and `Unlicense`, even copyright is donated to the public domain: this will affect how Inform prints the rights details — Inform will say ``Placed in the public domain by ...`` rather than ``(c) ...`` — but won't very much affect the freedom of users, which is almost complete for any of these licences. For real zealots, `CC0-1.0` is thought to relinquish all conceivable patent claims too, and has had more legal attention than the `Unlicense`, but both have their adherents. Some no-attribution licences are so free that users can even remove our names, fraudlently claim to be the author themselves, and so on. They certainly don't need to give us any credit. But just because this is legally allowed does not mean it's ethical, and Inform automatically acknowledges all extension contributors, even if the licence does not require it. The Public Library will not host an extension if the curators think the author has been dishonest. So this concern is not much of a concern. A more likely scenario to think about is: what if it's twenty years from now, and somebody wants to take over this extension as the new maintainer, but we're not around to be asked? The more free the licence, the more clear the position will be for that new maintainer. Note that the Public Library will _not_ accept `CC-BY-NC-4.0`, `CC-BY-NC-ND-4.0` and so on, and will not accept `GPL-2.0`, `GPL-3.0` or similar. We have made this policy choice because: - We want Public Library users to feel completely free to publish commercial games. This is why we do not allow `-NC`, "no commercial use", licences. - Similarly, clauses intended to force users of an extension to share the results impose a restriction on the author of a story which we want to avoid. Authors should be free to publish stories without having to publish the source text if they want to. So, no `-SA`, "share-alike", restrictions, and no form of the GPL. - Any story using an extension could, at a stretch, be considered a derivative work, and we don't want the legal safety of an extension to come down to delicate questions of law. So, no `-ND`, "no derivative works", clauses. Extension authors are completely free to licence their extensions however they would like to, of course. Our shortlist of six licences is simply a hosting-policy choice made by the Inform Public Library. Users are free to choose other licences and circulate extensions elsewhere. ## Compatibility with story file formats ^^{extensions: writing: for a specific virtual machine} ^^{Glulx: extensions for Glulx only} ^^{Z-machine: extensions for Z-machine only} ^^{virtual machine: extensions for Z-machine / Glulx only} ^^{Basic Screen Effects+ext+} ^^{extensions: specific extensions: Basic Screen Effects} The Inform app gives each project a Settings panel, and the most consequential setting by far looks like this: > __Story File Format__ > > Inform translates the source text into a story file which can have either of two standard formats. You can change your mind about the format at any time, but some language features require Glulx to be used. > > - Z-Code version 8 (medium-sized textual projects: most portable) > > - Glulx (large and multimedia projects: most capable) The default is Glulx, and that is what almost all users accept, but there are certainly still users creating small Z-machine story files. The setting matters a great deal because Z-code story files are not only small, they handle data in smaller chunks: it's a 16-bit virtual computer, not a 32-bit one like Glulx. This is why `number` values can be so much larger in Glulx. Glulx also offers the `real number` kind, which is not available with the Z-code setting, and so on. There are further differences to do with visual effects. Though it is not offered as a setting in the Inform apps, there's a third platform too: command-line Inform tools can compile to a C program which can then be compiled as a binary program on almost any computer. C behaves very like Glulx as a platform for Inform, but there are a handful of differences. So although an extension should ideally work fine on all platforms, some inevitably can't, and they need to signal that to Inform. So let's suppose that `Ducking Action` needs to compute the precise head velocity of the player in meters per second, and needs real arithmetic to do that. If so, it cannot run on the Z-machine, and the extension header ought to say so. To do that, it can optionally contain a _compatibility note_, like the one here: Version 1 of Ducking Action (not for Z-machine) by Peter Drake begins here. Historically, Inform only supported four compatibility notes: (not for Z-machine) (not for Glulx) (for Z-machine only) (for Glulx only) But it now supports quite a variety of compatibility notes. As noted above, there's now a third platform, `C`, so these are possible too: (not for C) (for C only) Inform also accepts `16-bit` and `32-bit` to mean any platform where values occupy that many bits: the Z-machine is 16-bit and C and Glulx are 32-bit. Moreover, for backwards compatibility reasons, Inform in fact interprets the terms `Z-machine` and `Glulx` as synonyms for `16-bit` and `32-bit`, rather than as requiring these specific platforms. So these all have the same practical effect: Version 1 of Ducking Action (not for Z-machine) by Peter Drake begins here. Version 1 of Ducking Action (not for 16-bit) by Peter Drake begins here. Version 1 of Ducking Action (for Glulx only) by Peter Drake begins here. Version 1 of Ducking Action (for 32-bit only) by Peter Drake begins here. If more platforms are added in future, it seems likely that this system will be made more flexible still. In general, good advice is to choose the simplest compatibility note possible. Here this seems clearest: Version 1 of Ducking Action (not for 16-bit) by Peter Drake begins here. An alternative to restricting `Ducking Action` like this is for it to provide two different versions of its functionality, one which works on each platform — then anybody can use it. This is the feature we will explore next. ## Extensions which vary with use {PM_HeadingInPlaceOfUnincluded} {PM_HeadingInPlaceOfUnknown} {PM_UnequalHeadingInPlaceOf} ^^{extensions: writing: including other extensions} ^^{extensions: writing: modifying other extensions} ^^{headings: in extensions} We have already seen that it is possible for headings in the source text to be marked `(for release only)` or `(not for release)`. This provides what, in other programming languages, is sometimes called "conditional compilation". The program can come out in two different ways, depending on whether the user is making a regular compilation, or a final release one. And the difference is whether the material under these headings is included in the program or not. `(for release only)` and `(not for release)` are not the only markers like this which can be placed on a heading. Suppose we write out our example extension like so: Version 1 of Ducking Action by Peter Drake begins here. Ducking is an action applying to nothing. Understand "duck" as ducking. Section on reporting (for 32-bit only) Velocity is a kind of value. 1.0 m/s specifies a velocity. Report ducking: let V be 0.04 m/s; let R be a random number from 5 to 15; say "You duck! Your head moves at [V times R]!" Section on reporting (for 16-bit only) Report ducking: say "You duck!" Ducking Action ends here. The practical effect is that on a 16-bit platform we get this content: Ducking is an action applying to nothing. Understand "duck" as ducking. Report ducking: say "You duck!" Whereas on a 32-bit platform we get this: Ducking is an action applying to nothing. Understand "duck" as ducking. Velocity is a kind of value. 1.0 m/s specifies a velocity. Report ducking: let V be 0.04 m/s; let R be a random number from 5 to 15; say "You duck! Your head moves at [V times R]!" And therefore if we duck on Glulx, we see something like ``You duck! Your head moves at 0.32 m/s!``, whereas on Z, we just get ``You duck!``. Two further features like this are provided to recognise that extensions might need to interact with each other. When `Ducking Action` is included in a project, quite likely other extensions are included in it, too. We can't know in advance what all of those will be. But let's suppose that `Ducking Action` can't work in the same story as an extension that we know is popular. We could then make part of `Ducking Action` read differently in that situation. For instance: Chapter 2a (for use with Locksmith by Emily Short) specifies that everything under this heading (and its subheadings, if any) will be ignored unless the extension `Locksmith by Emily Short` is included as well. Conversely, Chapter 2b (for use without Locksmith by Emily Short) will be ignored unless `Locksmith` _isn't_ included. This allows an extension to give two variations on the same material – one if `Locksmith` is present, the other if not. This feature is probably best used in a positive way. For example, maybe `Ducking Action` can make ducking through doorways even more cool in projects which have `Locksmith` included too. The final way to use "conditional compilation" on headings is best avoided unless absolutely necessary. It's best explained by example: Section 6 - Hacked locking (in place of Section 1 - Regular locking in Locksmith by Emily Short) If `Ducking Action` contains this section heading, then the material underneath it is spliced in to `Locksmith` in place of whatever `Locksmith` had put under the heading `Section 1 - Regular locking`. Here are some disclaimers: 1) Above all, this is a potentially treacherous feature. Authors need to be vigilant to each other's changes if this is used. (What if Emily Short renames her sections, or moves material around between sections?) 2) If there should be two or more headings of the same name in the given extension, the first is the one replaced. 3) If two or more headings attempt to replace the same heading in the given extension, the final attempt in source text order is the one which succeeds. 4) Heading dependencies like the above are scanned in a top-down way. Thus, if we have: Chapter 2a (for use with Locksmith by Emily Short) [...] Section 1 - Hacked marbles (in place of Section 4 in Marbles by Peter Wong) [...] and we don't include `Locksmith`, then the replacement of `Section 4` of `Marbles` is not made, because `Section 1 – Hacked marbles` is subordinate to the `Chapter 2a` heading which we've told Inform to ignore. 5) If the name of the heading to replace contains the word `in`, it's a good idea to use quotation marks for clarity: Section - Hacked questions (in place of "Section 4 - Phrase used to ask questions in closed mode" in Questions by Michael Callaghan) 6) It bears saying again: use this feature only when really necessary. ## Extensions in the Index ^^{Contents page of Index panel+ui+} ^^{user interface: Index panel: Contents page} ^^{Index panel+ui+: Contents page} ^^{kinds: documenting in extensions} ^^{specification of (thing)+prop+} ^^{specification of (thing)+propcat+} ^^{Kinds page of Index panel+ui+} ^^{user interface: Index panel: Kinds page} ^^{Index panel+ui+: Kinds page} ^^{headings: in extensions} ^^{(unindexed), headings in extensions+sourcepart+} As soon as a project has successfully been translated, its Index is brought up to date: pages of the index record all the kinds and what they are for, all the phrases which can be used, and so on. Any kind or phrase created in an extension is automatically included. The extension's presence in the project is itself recorded – the Contents index for any project contains a brief list of all extensions used in that project, along with their authors and version numbers. All of that is automatic, but there are two ways in which an extension can help matters by improving the way its contents are indexed. ### Providing a specification for each kind The Kinds index aims to give the reader a brief note of what each kind is intended for. For example, `text` is briefly explained as: > Some text in double quotation marks, perhaps with substitutions written in square brackets. This is called the _specification_ of the kind. Inform allows any kind defined in the source text to be given a specification like this. For example: A low door is a kind of door. The specification of low door is "Represents a door which a person can normally only walk through while ducking." `Specification` is a sort of pseudo-property, which does not really exist. Like the rubric to an extension (see [Extension rubrics]), this text never appears in the story as played, and is not in fact compiled. It is used only in the Index. ### Grouping phrases together under sensible heading names Some extensions provide hardly any phrases, or none at all, but others provide many. (`Basic Inform` defines hundreds.) The Phrasebook in the Index will, by default, simply lump these all together, which isn't easy for users to browse. However, if the phrases are defined under different headings, then those headings will be used in the index, too. Section - Head motion [Some "To ..." phrases here] Section with some more phrases - Door clearance [Some more "To ..." phrases here] These batches of phrases would then be listed in the index under ``Head motion`` and ``Door clearance`` respectively. 1) Inform looks for a hyphen in the heading and then uses any text which follows the hyphen. 2) If there is no hyphen, the entire heading text is used. 3) If an extension contains no headings, all its phrases are indexed simply as "Miscellaneous". If there are, say, only five or fewer phrases, then this is not worth the trouble, but otherwise it probably is. And the same is true for action definitions, and how they are listed in the Actions index; but once again, this is probably not worth the trouble if the extension contains only five actions or fewer. ### Hiding material from the index Finally, any phrase or variable defined immediately under a heading whose name ends in the word `unindexed` will be omitted from the Phrasebook or Contents index respectively. (That _won't_ apply to definitions under subheadings of the heading.) For example: Chapter 2 - Implementation - Unindexed To secretly adjust all the door heights: ... This is intended so that technical apparatus used only inside the extensions can be concealed from the outside user's immediate view. Inform as it is presently constituted does not allow extensions to make fully private definitions, but this feature at least allows them to make unadvertised ones. ## Images and other resources ^^{extensions: writing: figures} ^^{extensions: writing: sounds} ^^{extensions: writing: files (data files)} ^^{figures: in extensions} ^^{sounds: in extensions} ^^{files (data files): in extensions} ^^{materials folder: for an extension} An extension directory can, optionally, contain a subdirectory called ```Materials```. If it does, this can then contain a wide variety of useful things, laid out almost exactly like the materials folder for a project. Because it's included in the extension, anybody downloading the extension gets all of these extras along with it. So, then: * Figures can be provided in ```Materials/Figures```. * Sound effects can be provided in ```Materials/Sounds```. * Data files can be provided in ```Materials/Data```. * Templates for websites or interpreters can be provided in ```Materials/Templates```. This means extensions can be wrappers for these, so that users of such templates do not even need to write their own release instructions - because those can be put in the extension's source text. * Kits can be provided in ```Materials/Inter```. They are private to this extension, and are linked into a project including the extension _if the extension metadata says so_. See [Kits]. * Language bundles can be provided in ```Materials/Languages```. That goes beyond the scope of this manual, but language bundles enable stories to use natural languages other than English. But an important exception is that extensions may _not_ be provided in ```Materials/Extensions```. Extensions containing other extensions... is a regress too far. As an example, Inform supports figure and sound effect declarations like so: Figure of dalmatian mascot is the file "dalmatian.jpg". Sound of gushing water is the file "gushing.ogg". If such sentences are found in the main source text, nothing changes about their meaning: the files, ```dalmatian.jpg``` and ```gushing.ogg```, are looked for in the project's materials folder, as before. But if such sentences are found in the source text for an extension directory, then Inform looks for the files first in the materials for the extension. If it doesn't find them there, it then turns to the project's materials folder. If Inform does find that the extension directory has provided the resource, it then just checks to see if the author has _overridden_ this. For example, suppose the author using `Red Fire Hydrants by Emily Short` doesn't like the dog picture, and wants to substitute a better one. That author can then supply this: ``` code Hypothetical Project.materials/Figures/Red Fire Hydrants/dalmatian.jpg ``` Note that this is in a subdirectory of ```Figures```, with the same name as that of the extension. This means the author could replace ```dalmatian.jpg``` from multiple different extensions, while still having a quite unrelated ```dalmatian.jpg``` used by the project's main source text. ## Use options for extensions ^^{use options: defining in extensions} ^^{use options: active / inactive+adj+} ^^{active / inactive (use option)+adj+} ^^{inactive / active (use option)+adj+} ^^{numerical value of (U - use option) ... number+phr+} Extensions should ideally cater for a range of possible uses, and one way to do that is to provide use options. We have seen many of these already, such as: Use American dialect. Use the serial comma. Extensions can also create use options. There are two sorts: "configuration flags", which are either set or not set; and "configuration values", which are numbers. The following creates one of each: Use automatic low lintel ducking translates as a configuration flag. Use duck depth translates as a configuration value. The user's story could then begin: Include Ducking by Peter Drake. Use automatic low lintel ducking. Use duck depth of 10. The distinction between these: Use duck depth translates as a configuration value. Use duck sway of 6 translates as a configuration value. is that `duck sway` has a default value of 6 (i.e., will be that if the source text never specifies anything), whereas `duck depth` has a default value of 0. If the user gives two use instructions which clearly can't both be satisfied, a problem message will reject this as a contradiction. For example: Use duck depth of 17. Use duck depth of 22. If the idea is that a configuration value is some sort of maximum, which is often useful, then it can be defined as `at least` a value (which must be non-negative): Use maximum actor height of at least 60 translates as a configuration value. Should the user then say both of these: Use maximum actor height of at least 175. Use maximum actor height of 200. there is then no contradiction, and the value comes out as 200, which satisfies both requirements. (Of course, it's unlikely that any user will type both sentences. But that user might type one sentence into the source text, and also include an extension which, perhaps without the user even knowing, is also trying to configure `Philately`.) This would still produce a Problem: Use maximum actor height of at least 175. Use maximum actor height of 160. Sneakily, we can also make what look to the user like several flags, but are actually mutually exclusive. For example, suppose we want the user to be able to select either of these, but not both: Use bobbing ducks. Use swivelling ducks. That can be done like so: Use bobbing ducks translates as the configuration value DUCK_MOTION_TYPE = 1. Use swivelling ducks translates as the configuration value DUCK_MOTION_TYPE = 2. As this suggests, under the hood a value called ```DUCK_MOTION_TYPE``` is being set. Attempting to set both options will now cause Inform to throw a problem message for a contradiction, as will a sentence like `Use bobbing ducks of 3`. (We know that these settings are numerical; the user does not.) The so-called "identifier" for the configuration value, in this case ```DUCK_MOTION_TYPE```, isn't a typical Inform name written out in words: it has to be a single word made up of capital letters, digits and underscores. See [Use options from I6] for why this is. So much for how we define these configuration flags or values, and how the user sets them: now for how to read back the settings which the user has made. 1) The adjectives `active` and `inactive` apply to use options. A configuration flag is `active` if it has been used; a configuration value if it has been set to a non-zero value. 2) The phrase `numerical value of U`, for any use option `U`, produces its current value. (For a flag, that will be 1 if it is active, 0 if it is inactive.) Note that `active` and `numerical value` are _not_ properties: they are set forever by the user, and cannot change at run-time. So `now U is active` and `now the numerical value of U is 10` do _not_ work. For example: Before going through a low door when the automatic low lintel ducking option is active: say "(first ducking your head)[line break]"; silently try ducking. To return to our two mutually exclusive options: Use bobbing ducks translates as the configuration value DUCK_MOTION_TYPE = 1. Use swivelling ducks translates as the configuration value DUCK_MOTION_TYPE = 2. ...suppose the user has chosen neither. Then both are inactive, and both have a numerical value of 0. If the user has chosen to `Use swivelling ducks` then `swivelling ducks option` is `active` and has a numerical value of 2. In case helpful, here's a little diagnostic command called ``OPTIONS``: {*}Showing use options is an action out of world, applying to nothing. Understand "OPTIONS" as showing use options. Carry out showing use options: repeat with U running through active use options: if the numerical value of U > 1: say "[U] has been set to [numerical value of U]."; otherwise: say "[U] is on."; say "Inactive: [list of inactive use options]."; ## Run-time problems ^^{error messages: defined in extensions} ^^{problem messages: defined in extensions} Run-time problems are the ones thrown by stories which hit some impossible demand while playing: perhaps they find that they need to divide a number by zero, or they try to make a physical person wear a concept, or put a room on top of a shelf, or something else which simply can't be done. All experienced Inform authors will have seen RTPs before, but in case not, running this will certainly do it: The Cellar is a room. The wine crate is here. When play begins: now the wine crate is in the wine crate. Extensions can trigger RTPs of their own, too. For example, suppose `Ducking` detects a bad situation which it can't do anything about. It can then do something like this: issue the run-time problem "OverDucked"; say "*** ", (the) ducker, " seems to be putting their head below their feet."; The RTP name, here `OverDucked`, must correspond exactly to the name of a Markdown file stored in an ```RTPs``` subdirectory of the extension: ``` code Philately-v1.i7xd extension_metadata.json Source Philately.i7x RTPs OverDucked.md ``` The file ```OverDucked.md``` should then give an explanation: ``` code # A head can't be ducked below a person's feet It's a physical impossibility to duck your head through the ground. We're not allowing acrobatics or highly unlikely situations, such as standing just on the edge of a deep hole. ``` > phrase: {ph_issuertp} issue the run-time problem (text) > > Produces a run-time problem message with the given code-name. For example: > > issue the run-time problem "CantDivideByZero"; > > This phrase should be used only in extensions. The file ```CantDivideByZero.md``` must then exist in the extension's ```RTPs``` subdirectory, and must give an explanation. ## Style and best practice guide _The following is not a comprehensive style guide, and these are very much guidelines, not rules. But they may be helpful when writing an extension which is to be shared with the world._ ### Use directory format for extensions, not single file format. The older single-file extension format is not described in this chapter, because it's much less capable and will eventually be deprecated. The Public Library will henceforth only accept directory-format extensions. Conversion is easy: in the Extensions panel for a project, a single-file extension will have a ```MODERNISE``` button next to it. Click this, and confirm. ### Include enough material to make the extension worthwhile. If your feature is implemented in just one or two rules, which do not do anything very surprising, it's probably not substantial enough for an extension. ### Avoid a miscellany of features. This doesn't mean "do only one thing". Many extensions usefully contain a bundle of related features. But they are best if those features naturally go together. It's better to build an extension around one sort of functionality than to build it around one sort of scenario or story. An extension for "everything you need to implement a shop" might be better broken down into two different extensions, one which implements money, change, and so on, and one which deals with managing the goods on sale. ### Give your extension a descriptive name, avoiding comparatives. For example, `Rideable Vehicles` is preferable to `Better Vehicles`, because it says what it provides. Avoid stylish titles like `Locksmith`. For more on good titling practice, see [Title and authorship]. ### Give your extension a version number. While it is still legal Inform to write an extension with no declared version number, this is very unwise for anything which might be used by anyone other than the author. A good extension should always begin by giving its current version number in the opening words, like so: Version 9 of Locksmith by Emily Short begins here. See [Version numbering] for more. ### Follow the semantic versioning convention. Under the hood, Inform tracks version numbers which follow the `MAJOR.MINOR.PATCH` semantic convention. If only one or two numbers are given, the others are implicitly 0: thus `9` means `9.0.0`, and `9.3` means `9.3.0`. If you release _any_ update of your extension, however minor the change, increase its version number. Semantic version numbers are a promise which you are making, so: - The `MAJOR` number must increase if there is any significant change to how the extension carries out its existing job. - Otherwise, increase just `MINOR` if you are adding new features, but not changing anything about existing ones. - Otherwise, increase just `PATCH` if you are fixing bugs, but making no change to the feature set. ### Write a brief rubric text, describing what it does more fully. This is the short quoted text appearing just under the title in an extension's source text. Aim to write 30-50 words giving a fuller idea of what the extension does. For example: ``` code "Provides more sophisticated listing options: the ability to impose special ordering instructions on a list, and also the ability to change the delimiters of the list to produce different styles and effects." ``` Do not include your name or the extension's title: they are described immediately above in any case. If the extension has been withdrawn, or is now deprecated, say so in the rubric. ### Write documentation. An extension is really only useful if it comes with documentation, and there's a whole chapter of this book about how to write it: see [Extension Documentation and Testing]. - Unless the extension works equally with both major compilation settings (Glulx or Z-machine), make a prominent compatibility note at the top of the documentation. - Similarly if the extension requires other extensions in order to work, or is incompatible with other popular extensions, or with modern versions of Inform. - If the extension _does_ work with Basic Inform alone, explicitly say so, because extensions usually don't. - Aim to be concise, but give as many examples as possible. - Every phrase which you document should be given a "box" giving its own specification, in the same style as the main Inform manual. - Documentation should include the names of any rules, rulebooks or activities which the user might want to customise or modify. ### Provide examples. Examples are short Inform source texts, with a little commentary, demonstrating features of your extension. Try to write at least one for every non-obvious thing your extension can do, or every interesting use-case you've thought of which might not occur to other people. Imitate the style of the main Inform documentation examples. For each example, include within it a short test script which plays it out: Test me with "get all / w / drop all / look / get all / w / drop all / look". ### Provide test cases. For every example, include also the ideal textual output which it produces, so that your extension can be automatically tested. (Inform provides controls for the users to run these tests on an installed extension.) You can also provide test cases which are not part of the documentation, but verify the correct running of some part of your extension. For example, if you define an action, you can provide a test case which tries out every way a player, or a third party, might attempt the action, correctly or not. The better your test case coverage, the easier it is to keep the extension up to date when Inform changes, and the more confidence users will have with it. ### Use rules, rulebooks, actions, and activities. Wherever possible, implement your features using rules: either as part of the Standard Rules rulebooks and activities, or as part of your own. Rules are good because they give the user great ability to customise how your extension operates, and also to understand what it's doing, since the `RULES` debugging command allows users to track this behaviour. There is no significant overhead to having multiple rules rather than just one, and wherever possible each rule should contribute one idea. For example, the Standard Rules implements the wearing action by first making three checks to see if it's sensibly possible for an actor to put on an article of clothing. But it breaks these out into three different rules, so that users can override just one and keep the other two, for example. ### Name rules consistently. Every rule which affects an action, or does something which changes how the usual rulebooks or activities behave, or does something significant to provide your own functionality, should have a name. For action rules, follow the naming style used in the Standard Rules. For example, the wearing action is implemented with the following rules: can't wear what's not clothing rule can't wear what's not held rule can't wear what's already worn rule standard wearing rule standard report wearing rule Here, the `check` rules have names beginning with "can't", because they each provide a single potential reason why an action cannot take place. Note that the names do not contain "you", i.e., these are _not_ named in the style: you can't wear what's already worn rule The `standard wearing rule` is a carry out rule, and performs the actual action. What the word "standard" means here is that this is a single rule performing the change of world state which the action calls for, in what we consider the normal way. (Here, say, a hat object would become worn by the actor.) In general, actions are "atomic", in that you wouldn't want them to be only partly carried through. So a single carry out rule like this is appropriate even if the action does something complicated. But if it's very complicated, and you could imagine users wanting to tweak it, consider handling the actual change of game state with an activity. Similarly, the `standard report wearing rule` is a single rule providing a routine description of what happens. ### Use adaptive text. Adaptive text is the Inform feature which allows it to present the same basic sentences in different tenses, or agreeing with different nouns. A typical non-adaptive message would be: "You're not holding that!" But this assumes the story is told with a second-person protagonist (called "you"), and that "that" is singular. The adaptive version would be: "[We] [aren't] holding [regarding the noun][those]!" Verbs adapt, too, and if you need an unusual verb to do so, then go ahead and declare it: you won't tread on any other extensions by doing that. For example, once this declaration is made: To hornswoggle is a verb. then you could write adaptive text like: "[The actor] [hornswoggle] [the noun]." For many, many examples of adaptive text, see the action rules in the Standard Rules. ### Use lettered responses. Rules for actions (and also for some activities) often print standard responses, and Inform provides features for users to modify or replace these. Your own rules can make that possible, too, by using response letters. For example: Report an actor eating (this is the standard report eating rule): if the action is not silent: if the actor is the player: say "[We] [eat] [the noun]. Not bad." (A); otherwise: say "[The actor] [eat] [the noun]." (B). This rule provides two responses, `A` and `B`. When you first define a rule, letter the different possible replies from `A` upwards. (If there are more than 26, you have too much going on for one rule: break it up.) When updating an extension to make a new release, _do not reletter these responses_: your users now expect `B` to be the one printing something like "The doctor eats the apple." So if you add a new response, make it `C`, even if it's higher up in the rule than `A`: that doesn't matter. ### Naming of actions and activities Activities should be named in a way which concisely describes what they do: issuing the response text activity printing the locale description activity Note the participles `issuing` and `printing`: do _not_ call these issue the response text activity print the locale description activity And similarly for actions: climbing tying it to ### Make actions work for all actors. When Inform users are writing a story, it's quite common to write an action on the assumption that only the player will ever be the actor. If you're the author of the story, you can be sure that that will be true. But if you create an action in an extension, you don't know how it will be used, so don't make assumptions. In practice, this means writing the rules for the action to talk about `the actor`, not `the player`, and remembering that they may not be the same. For example, this is _not_ a good rule: Check pushing something to (this is the can't push vertically rule): if the second noun is up or the second noun is down: say "[The noun] [cannot] be pushed up or down." (A); stop the action. Firstly, it fires only if the actor is the player. Fix that like so: Check an actor pushing something to (this is the can't push vertically rule): if the second noun is up or the second noun is down: say "[The noun] [cannot] be pushed up or down." (A); stop the action. But even this version implicitly assumes the actor is the player, because it prints a complaint to the player if the action is impossible. The right way to do this is: Check pushing something to (this is the can't push vertically rule): if the second noun is up or the second noun is down: if the actor is the player: say "[The noun] [cannot] be pushed up or down." (A); stop the action. This rule fires for any actor, and if the actor is trying to push an object upstairs or downstairs, the action will stop: but the complaint will be printed only if the player is the guilty party. ### Make actions physically reasonable. Play nicely with the world-modelling conventions of the Standard Rules. Define your action in a way which limits its applicability to what is physically possible. For example: Throwing it at is an action applying to one carried thing and one visible thing. ### Write a specification for your action. Help users by providing some index documentation on your action. This doesn't need to be large or elaborate: The specification of the inserting it into action is "By this action, an actor puts something he is holding into a container: for instance, putting a coin into a collection box." ### Avoid global variables where possible. Try to avoid "global state" where possible, and minimise the use of sentences like: The controller is a person that varies. For one thing, `controller` is a word which could easily cause clashes with nouns in your users' stories, but for another, do we need to store this at all? For example, an extension which automatically moves certain people around every turn, to simulate crowd behaviour, could be implemented using: The wanderer list is a list of people that varies. And that might be the most efficient way to do it. But there are alternatives: for example, declaring an either/or property for whether a person is actively wandering or not. Similarly, if a variable is only needed to preserve state across multiple rules in the same action, rulebook or activity, make it a variable private to that action, rulebook or activity. ### Either-or properties. If defining an either-or property, always give a name for its opposite too, and explicitly say what the usual state is. For example, instead of this: A device can be switched on. Write this: A device can be switched on or switched off. A device is usually switched off. ### Move any substantial Inform 6 code into a kit. This will be the subject of the final chapter in this book, [Kits]. "Substantial" here means that you need to define one or more Inform 6 functions or global variables. Old-fashioned extensions would generally do this with a so-called "inclusion", like so: Include (- [ FunctionName par1 par2; ... ]; -). While there is no plan to withdraw `Include ...` from the language, its use is now deprecated. Small kits are quite easy to construct, and can be included in an extension's directory so that the user never needs to know how all this is done. Give such a kit a name based on the extension's name: e.g. `Graphics Windows` might have a kit `GraphicsWindowsKit`. # Extension Documentation and Testing ## Making a documentation set for an extension ^^{extensions: writing: documenting} Every extension intended to be used by anybody other than its author needs _documentation_. This is a brief manual explaining what it does, and how to use it. Some extensions are simple enough that a single page of notes is enough, but others benefit from examples. In the previous chapter we followed the story of an extension called `Ducking Action by Peter Drake`, which was held in a directory called ```Ducking Action-v1.i7xd```. (That in turn sat installed into the ```.materials``` folder of a test project called ```Ducking Test.inform```.) Since there is only so much one can write about the act of ducking, this chapter will suppose that we are now documenting a larger and more capable extension for stamp collectors, called `Philately`. So we start with the extension looking like so: ``` code Philately-v1.i7xd extension_metadata.json Source Philately.i7x ``` We now add a new subdirectory alongside ```Source```: ```Documentation```. ``` code Philately-v1.i7xd extension_metadata.json Documentation Documentation.md Source Philately.i7x ``` So in other words, we need to create a new subdirectory called ```Documentation``` and create a new text file inside it called ```Documentation.md```. That new directory is called a _documentation set_, and although it will start in a minimal way, with a single file and hardly any text, it can scale up considerably. The entire in-app documentation for Inform, with the two books _Writing with Inform_ and _The Recipe Book_, and all their examples and indexes, are constructed as a single documentation set. It's very unlikely that an extension will ever need so huge a manual, but it could if we wanted it to. Once again, ```Documentation.md``` is a plain text file encoded as UTF-8, just like ```Philately.i7x```: a text editor which can edit one can also edit the other. It can start like this: ``` code ## Introduction The "Philately" extension provides ways to manage stamp collections. Contact stampbuff1837@gmail.com with any bug reports. Individual stamps can be declared, and given prices: The Harding Memorial 1923 Issue is a stamp. "Note the black border of this US 2 cents issue." The price of the Harding Memorial is $25.50. ``` As the filename ending ```.md``` will already have signalled to some readers, ```Documentation.md``` is written in a notation called _Markdown_. It is in fact a way to mark text _up_, but an easy, low-fuss one, at least compared to many other syntaxes which have been tried. The little file above contains two markings-up: the ```##``` marks the word ```Introduction``` as a section heading, and the fact that the ```The Harding Memorial ...``` line is indented by one tab step means that it is presented as a source text extract, syntax-coloured as Inform 7 source. Extension documentation is presented exactly like this manual: so, for example, > ### Introduction > > The "Philately" extension provides ways to manage stamp collections. > Contact stampbuff1837@gmail.com with any bug reports. > > Individual stamps can be declared, and given prices: > > The Harding Memorial 1923 Issue is a stamp. > "Note the black border of this US 2 cents issue." > > The price of the Harding Memorial is $25.50. Markdown is a widely-used Internet standard, so modern text editors often offer special facilities for editing Markdown content, and will for example syntax-colour it nicely. ### Technical footnote There are many dialects of Markdown. The one Inform uses is called _Inform-flavored Markdown_, as follows: * All CommonMark features are supported, i.e.: emphasis, strong emphasis, backticked code snippets, links, images, web autolinks, email autolinks, block quotes, ordered lists, unordered lists, thematic breaks, indented code samples, fenced code samples with optional info strings, ATX headings (i.e. using ```#``` characters), setext underlined headings (i.e. using a second line of ```----``` characters), backslashed escapes, and HTML entities; *except that* * For security reasons, raw HTML blocks are not passed through as HTML, and similarly raw HTML tags are not allowed. So ```this is bold``` does not place the word "bold" in boldface, and instead passes the angle-bracket notations through into the resulting text. * All GitHub-flavored Markdown's extensions to CommonMark are supported: strikethrough, tables, task list items and extended autolinks. * An extension syntax allows marking-up documentation for indexing: see [Indexing documentation]. * And one further extension is made for compatibility with old-style headings: see [Headings and organisation]. Inform's documentation engine passes the entire suite of validation tests for both CommonMark and Github-flavored Markdown, so it is fair to call this an extended but highly standard Markdown. ### Historical footnote In releases of Inform before 2024, extension documentation was tacked on to the end of the extension source after a tear-off-slip like line reading `---- DOCUMENTATION ----`; and it was then written in its own non-standard markup notation, although this was very minimal. The results were not very appealing, and there was no proper syntax colouring. ## Headings and organisation ^^{headings: in extension documentation} ^^{extensions: documenting: headings} The Markdown notation for headings looks like so: ``` code # Chapter Heading ## Section heading ### Subheading within a section ``` Technically there can be up to six ```#``` characters, for progressively less important headings, but for Inform documentation we stop at three. By default, Inform places each chapter on its own web page. Small extensions with little to document therefore often use only section headings, and then all of the documentation fits on a single page. By convention, the first section heading is an introduction, like so: ``` code ### Introduction The "Philately" extension provides ways to manage stamp collections. Contact stampbuff1837@gmail.com with any bug reports. _Compatibility_. Although "Philately" is compatible with either the Z-machine or Glulx settings, it can only display stamp images under Glulx. ``` Customarily, the introduction ends with a note on compatibility if there's anything like that which the user should know. Chapter and Section headings can also be written with "setext underlining", or in the traditional Inform extension notation. So the following are all equivalent: ``` code # Perforations Perforations ============ Chapter: Perforations ``` And similarly: ``` code ## Embossing Embossing --------- Section: Embossing ``` But as style guidance, we now prefer ```#``` and ```##```. A small technical caveat: Inform-flavoured Markdown does not allow level 1 (Chapter) or level 2 (Section) headings to be used inside block quotes or list items. This is because it seems madness to break the page at those positions; CommonMark does allow this, but it's hard to imagine why. ## Textual effects and short code samples ^^{extensions: documenting: formatting} ^^{italics: in extension documentation} ^^{bold: in extension documentation} ^^{strikethrough: in extension documentation} ^^{backticks: in extension documentation} ^^{fonts: in extension documentation} Three textual effects are available: Effect | Example Markdown | Result --------------- | ------------------------------------- | ------ Strong emphasis | ```This stamp is **unperforated**.``` | This stamp is **unperforated**. Weak emphasis | ```All sales _subject to authentication_.``` | All sales _subject to authentication_. Strikethrough | ```recently ~~went on sale~~ was sold for $712.30``` | recently ~~went on sale~~ was sold for $712.30 People often think strong emphasis and weak emphasis means bold and italic respectively, and it usually does in practice, but there are many forms of display in the world. Something which often trips people up is that the strength comes from the doubling of the markers, not from the choice of marker. ```*This*``` produces *This*, whereas ```__This__``` produces __This__. Small samples of source text can be given by "backticking" them, like so: ``` code The `real number` kind can hold a wide range of values. We want to recognise the command ``MOVE ROOK``. The reply is just ``You can't see any such thing.`` In Markdown syntax, ```**this**``` produces strong emphasis. ``` The effect of which is like this: > The `real number` kind can hold a wide range of values. > > We want to recognise the command ``MOVE ROOK``. > > The reply is just ``You can't see any such thing.`` > > In Markdown syntax, ```**this**``` produces strong emphasis. Note that there are three notations here — one, two, or three backticks on each side of the material being quoted — which, under normal Markdown rules, are completely synonymous. So most Markdown viewers would display all these program-like fragments of text indistinguishably. But Inform displays them differently, and somehow there are _four_ different looks. What is happening here is that all four are code samples, just as the Markdown rules say they should be, but Inform is using different colouring rules to paint them on screen. The convention we follow is this: - Single backtick means Inform 7 source text. - Double backtick placed around upper case letters and/or spaces means a command a player might type into the Inform command parser. - Double backtick around anything else means "transcript text", that is, text printed by an Inform story during play. - Triple backtick is for generic code samples which aren't Inform 7 source text. This may all seem pedantic, but it does make documentation clearer. For example, this: ``` code `"He [bracket]Lord Astor[close bracket] would, wouldn't he?"` prints as ``He [Lord Astor] would, wouldn't he?``. ``` comes out as: > `"He [bracket]Lord Astor[close bracket] would, wouldn't he?"` prints as ``He [Lord Astor] would, wouldn't he?``. Which is easier to fathom than: > "He [bracket]Lord Astor[close bracket] would, wouldn't he?" prints as "He [Lord Astor] would, wouldn't he?". As a general piece of guidance, then, pieces of source text should be never be quoted in ordinary double-quotation marks. Those should be reserved for more human quotations. Markdown, like politics, is "the art of the possible". ### Backslash escapes ^^{backslash escapes: in extension documentation} ^^{extensions: documenting: formatting} Markdown also supports so-called HTML entities, which provide a way to type certain unusual characters by name rather than literally. For example, ```ℋ``` produces ℋ, a mathematical symbol. Nowadays it's usually better just to type the character directly: ```ℋ``` also produces ℋ. But it does raise the question: how do we write \ℋ without it coming out as ℋ? The answer is that the backslash character ```\``` can be used to "escape" certain characters which would otherwise cause Markdown to apply formatting, or some layout effect. So for example ```\_underlining_``` produces \_underlining_, and ```\ℋ``` produces \ℋ. A literal backslash can always be obtained as ```\\```, like so: \\. Note that none of this applies inside code examples, where a backslash is just a backslash and has no special powers. Similarly, it's not possible to apply emphasis inside a code sample, because the underscore and asterisk characters do nothing active there either. ## Longer code samples ^^{code examples: in extension documentation} ^^{extensions: documenting: code examples} ^^{syntax colouring: in extension documentation} ^^{extensions: documenting: syntax colouring} Inform documentation tends to be broken up with examples of source text, and this can be done very simply, by indenting the material one tab stop from the margin. (Or, equivalently, by four spaces.) ``` code Individual stamps can be declared, and given prices: The Harding Memorial 1923 Issue is a stamp. "Issued less than a month after President Warren H. Harding died in office on 2 August 1923, this US 2 cents issue featured an unusual black border." The price of the Harding Memorial is $25.50. Note that the `monetary value` kind can hold prices of only up to around 23 million dollars, but as of 2023 that should be enough. The highest sale price in history for a single stamp is $9480000, paid in 2014 for the only existing British Guiana 1c magenta, and it then depreciated to $8307000 when sold again in 2021. ``` This produces: > Individual stamps can be declared, and given prices: > > The Harding Memorial 1923 Issue is a stamp. "Issued less than a month after President Warren H. Harding died in office on 2 August 1923, this US 2 cents issue featured an unusual black border." > > The price of the Harding Memorial is $25.50. > > Note that the `monetary value` kind can hold prices of only up to around 23 million dollars, but as of 2023 that should be enough. The highest sale price in history for a single stamp is $9480000, paid in 2014 for the only existing British Guiana 1c magenta, and it then depreciated to $8307000 when sold again in 2021. If the opening line of the quoted passage begins with a ```>``` character and then what looks like a command, Inform will guess that it's a transcript instead. And therefore this: ``` code We want to penalise players not taking this seriously, so: > LICK STAMP You seriously degrade the value of this $174.90 Weimar republic issue. ``` comes out as: > We want to penalise players not taking this seriously, so: > > > LICK STAMP > You seriously degrade the value of this $174.90 Weimar republic issue. An alternative Markdown syntax makes it possible to specify exactly what sort of syntax-colouring should be used, like so: `````` code This is some JSON: ``` code { "is": { "type": "extension", "title": "Philately", "author": "Peter Drake", "version": "1" } } ``` `````` Note the use of three backticks before and after the block of whatever the sample is, and the presence of the word ```code```. Inform also supports ```inform``` (meaning the same thing as ```inform7```), ```inform6```, ```transcript``` and ```plain``` (no colouring at all). For example, this is syntax-coloured as Inform 6 code: ``` inform6 [ DisplayStamp st perf_flag; ... ]; ``` When an Inform source text code sample is marked with the special notation ```{*}```, this is displayed with a "paste me into the app" button attached in place of these symbols. For example: ``` code To set the scene: {*} "Definitely Unhinged" Include Philately by Stanley Gibbons. The British Museum Stamps Room is a room. The cabinet is a closed openable container in the Stamps Room. And so on: {**}The Saxony 1856 is a stamp in the cabinet. "A forgery by Jean de Spirati! Priceless." ``` Here the ```{**}``` notation means that the sample continues the previous one, and that a single paste button in the ```{*}``` position collects all of this text together into a single run. So for example: > To set the scene: > > {*} "Definitely Unhinged" > > Include Philately by Stanley Gibbons. > > The British Museum Stamps Room is a room. The cabinet is a closed openable > container in the Stamps Room. > > And so on: > > {**}The Saxony 1856 is a stamp in the cabinet. "A forgery by Jean de Spirati! Priceless." ## Block quotations and phrase boxes ^^{quotations: in extension documentation} ^^{extensions: documenting: formatting} "Block quotations" are suitable for quoting a piece of human writing, rather than code, and are introduced by ```>``` characters on the left margin: ``` code Roger S. Brody notes: > Some Harding rotary press-printed stamps were perforated gauge 11 x 11 > on the flat-plate equipment instead of the normal 10 x 10 rotary > perforating machine, producing an important twentieth century rarity. ``` The block continues for as long as the run of lines prefaced by ```>``` continues. Block quotations can themselves contain lists and other block quotations, and even code examples, though we need to type the number of spaces very carefully to ensure that those examples are exactly four spaces in from the point where ordinary text in the quotation would be: ``` code This does seem rather an extreme position: > We want to penalise players not taking this seriously, so: > > > LICK STAMP > You seriously degrade the value of this $174.90 Weimar republic issue. ``` Note that there are _five_ spaces between the ```>``` signs in the line with the ``LICK STAMP`` command. This is because the block material begins after ``> `` (one space) and then indents to reach the transcript text (four spaces). So the result is: > This does seem rather an extreme position: > > > We want to penalise players not taking this seriously, so: > > > > > LICK STAMP > > You seriously degrade the value of this $174.90 Weimar republic issue. Note that block quotes can contain multiple paragraphs, code samples (as in this example), and even lists and tables. One of the main uses of block quotations in Inform documentation is to provide the displayed boxes which give the specification of a "To..." phrase. For example, this: ``` code > phrase: set pronouns from (object) > > This phrase adjusts the meaning of pronouns like IT, HIM, HER and THEM in > the command parser as if the object mentioned has become the subject of > conversation. Example: `set pronouns from` here - > > set pronouns from the key; > set pronouns from Bunny; > > might change IT to mean the silver key and HIM to mean Harry "Bunny" Manders, > while leaving HER and THEM unaltered. ``` ...is a completely normal block quotation from a Markdown point of view, but the Inform documentation engine displays it in a special way: > phrase: set pronouns from (object) > > This phrase adjusts the meaning of pronouns like IT, HIM, HER and THEM in > the command parser as if the object mentioned has become the subject of > conversation. Example: `set pronouns from` here - > > set pronouns from the key; > set pronouns from Bunny; > > might change IT to mean the silver key and HIM to mean Harry "Bunny" Manders, > while leaving HER and THEM unaltered. ## Notes, tips, and cautions Inform supports a modest extension to Markdown format made by GitHub which allows block quotations to become informational or warning notices. Thus: ``` code > [!NOTE] > Useful information that users should know, even when skimming content. > [!TIP] > Helpful advice for doing things better or more easily. > [!IMPORTANT] > Key information users need to know to achieve their goal. > [!WARNING] > Urgent info that needs immediate user attention to avoid problems. > [!CAUTION] > Advises about risks or negative outcomes of certain actions. ``` (This is GitHub's own description of what these tags are for.) The result is: > [!NOTE] > Useful information that users should know, even when skimming content. > [!TIP] > Helpful advice for doing things better or more easily. > [!IMPORTANT] > Key information users need to know to achieve their goal. > [!WARNING] > Urgent info that needs immediate user attention to avoid problems. > [!CAUTION] > Advises about risks or negative outcomes of certain actions. Thus: > [!TIP] > A stamp sold as mint condition should have undisturbed gum for anything > issued after about 1930. Look for very fine (VF) centering, intact > perforations, postmarks (on used examples) that don't obscure the design, > ideally with clear date and city details. Like all other block quotations, these can contain all manner of other material inside, and not only text. ## Tables ^^{tables: in extension documentation} ^^{extensions: documenting: tables} A simple table looks like so, with pipe characters ```|``` dividing the columns; it will only become a table if there is a ruler line under the column headings. ``` code Column 1 | Column 2 | Column 3 -------- | -------- | -------- A | B | C D | E | F G | H | I ``` which produces > Column 1 | Column 2 | Column 3 > -------- | -------- | -------- > A | B | C > D | E | F > G | H | I There's no actual need to be tidy about lining up the pipes. ``` code Column 1 | Column 2 | Column 3 -------- | -------- | -------- A | B | C D | E | F G | H | I ``` produces exactly the same result. Table entries cannot contain other tables, or block code samples, or lists, or anything like that: but they can happily contain the simpler markup: `````` code Column 1 | Column 2 | Column 3 --------- | ----------- | --------- **Alpha** | _Beta_ | ~~Gamma~~ `Delta` | ``EPSILON`` | ``Zeta`` ```Eta``` | Theta | ι `````` producing: > Column 1 | Column 2 | Column 3 > --------- | ----------- | --------- > **Alpha** | _Beta_ | ~~Gamma~~ > `Delta` | ``EPSILON`` | ``Zeta`` > ```Eta``` | Theta | ι Table columns can be aligned leftwards or rightwards by adding colons ```:``` to the ruler line, as in this example: ``` code | Stamp | Price | | :---------------------------------------------------- | ------: | | GB 1883 SG183 10s Ultramarine | €614.72 | | GB 1862 SG77 3d Pale carmine-rose (Wmk. Emblems) Pl.2 | €234.18 | ``` producing: > | Stamp | Price | > | :---------------------------------------------------- | ------: | > | GB 1883 SG183 10s Ultramarine | €614.72 | > | GB 1862 SG77 3d Pale carmine-rose (Wmk. Emblems) Pl.2 | €234.18 | ## Lists and to-do items ^^{lists: in extension documentation} ^^{extensions: documenting: lists} ^^{to-do items: in extension documentation} ^^{extensions: documenting: to-do items} We have three sorts of list. Bulleted lists: ``` code Notable German stamps include: - Baden 9 Kreuzer error: stamp printed on blue-green instead of pink paper - One kreuzer black: issued 1849 in Bavaria, first German postage stamp - Sachsen 3 Pfennige red: Saxony was the second German state to issue postage stamps - Vineta provisional: an unauthorized issue - Yacht issue: a common design of postage stamps for the German colonies ``` resulting in: > Notable German stamps include: > > - Baden 9 Kreuzer error: stamp printed on blue-green instead of pink paper > > - One kreuzer black: issued 1849 in Bavaria, first German postage stamp > > - Sachsen 3 Pfennige red: Saxony was the second German state to issue postage stamps > > - Vineta provisional: an unauthorized issue > > - Yacht issue: a common design of postage stamps for the German colonies A list can alternatively be numbered, with this syntax: ``` code Notable Jamaican stamps include: 1) Jamaica 1 shilling inverted-frame stamp error 2) Jamaica 6d abolition of slavery postage stamp 3) Jamaica 1956-58 £1 chocolate and violet 4) Jamaica 1968 human rights stamps ``` resulting in: > Notable Jamaican stamps include: > > 1) Jamaica 1 shilling inverted-frame stamp error > > 2) Jamaica 6d abolition of slavery postage stamp > > 3) Jamaica 1956-58 £1 chocolate and violet > > 4) Jamaica 1968 human rights stamps List entries can in fact be much longer, and can contain all manner of layout elements: ``` code 1) Here's a two-paragraph list entry. With this being the second paragraph. 2) And a list within a list. How about China this time? - Red Revenues – 1897 provisionals, issued by the Qing dynasty - The Whole Country is Red – 1968 design error stamp - Golden Monkey stamp – 1980 Chinese zodiac stamp 3) Indian stamp | Notable for -------------------------------------------- | ----------- Scinde Dawk | First stamps in Asia Inverted Head Four Annas | — Indian 10 Rupee Mahatma Gandhi postage stamp | Overprinted "SERVICE" ``` producing: > 1) Here's a two-paragraph list entry. > > With this being the second paragraph. > > 2) And a list within a list. How about China this time? > > - Red Revenues – 1897 provisionals, issued by the Qing dynasty > > - The Whole Country is Red – 1968 design error stamp > > - Golden Monkey stamp – 1980 Chinese zodiac stamp > > 3) Indian stamp | Notable for > -------------------------------------------- | ----------- > Scinde Dawk | First stamps in Asia > Inverted Head Four Annas | — > Indian 10 Rupee Mahatma Gandhi postage stamp | Overprinted "SERVICE" And to-do lists are list entries with a sort of tickbox notation: ```[ ]``` or ```[x]```: see the example at the start of this section. Finally, note that if the items in a list are not divided by skipped lines, then the list is called "tight" (as opposed to "loose") and presented slightly differently: ``` code 1) Prices depend on condition and circumstances. 2) Victorian issues vary widely in circulation. My collection includes: - [ ] none of the 500 orange-red 1d Mauritius Post Office stamps (1847) - [x] one of the roughly 21 billion Penny Red stamps (1841-79) ``` produces: > 1) Prices depend on condition and circumstances. > 2) Victorian issues vary widely in circulation. My collection includes: > - [ ] none of the 500 orange-red 1d Mauritius Post Office stamps (1847) > - [x] one of the roughly 21 billion Penny Red stamps (1841-79) For Inform documentation, we prefer loose lists, which are easier to read on screen. ## Links and cross-references ^^{links: in extension documentation} ^^{extensions: documenting: links} The standard Markdown syntax ```[Label]``` or ```[this is a link][Label]``` makes a link where the destination is referred to by a label, rather than given explicitly. In traditional Markdown, that label can then be _defined_ like so: ``` code See [CommonMark] for more on this. [CommonMark]: https://commonmark.org "The CommonMark specification" ``` And this would work fine in Inform's Markdown too, but it's not very helpful when what we want is to make an internal cross-reference. Suppose we want a link to Chapter 2 of the current document: we can't say what the URL for that is because we don't know exactly how Inform will choose to store the HTML. Because of that, the dictionary of labels for links is pre-populated by Inform so that it automatically contains the names of all Chapters and Sections in the current document, and also all Examples. So for example: ``` code See [Perforations] and also [Embossing]. The example [The Red Mercury] shows how to implement Austrian rarities. ``` ...would all work automatically provided that the extension documentation contains a chapter called "Perforations", a section called "Embossing" and an example "The Red Mercury". For accessibility reasons, we recommend that all links be written directly, that is, where the link text is the same as the destination label, like this: ``` code See the example [The Red Mercury] for how to implement Austrian rarities. ``` rather than: ``` code See the example [of rarities](The Red Mercury) for more on Austria. ``` because although this would work fine for sighted users, displaying "See the example of rarities for more on Austria" but with the words "of rarities" linked, screen-readers display such links in a confusing way. ## Images in documentation ^^{figures: in extension documentation} ^^{extensions: documenting: figures} Extension documentation should not use externally hosted images, i.e., images on some server which requires an Internet access to fetch. Instead, they should use only their own private images. Those images should be stored in an ```Images``` subdirectory of the ```Documentation``` directory. For example, suppose we have this setup: ``` code Philately-v1.i7xd extension_metadata.json Documentation Documentation.md Images InvertedJenny.jpg Source Philately.i7x ``` We can then display this picture using the standard Markdown notation for such things, the ```![...](...)``` notation, but using the _leafname alone_ as the image label. For example: ``` code Only 100 of the following have ever existed: ![1918 24c US stamp of a Curtiss JN-4 plane but printed upside-down](InvertedJenny.jpg) ``` producing: > Only 100 of the following have ever existed: > > ![1918 24c US stamp of a Curtiss JN-4 plane but printed upside-down](doc_images/InvertedJenny.jpg) In fact, to display just the image, it would be enough to write: ``` code Only 100 of the following have ever existed: ![InvertedJenny.jpg] ``` but the full form is highly recommended since it provides alt-text for display by screen-readers for partially sighted users. ## Examples for extensions ^^{extensions: writing: giving examples} ^^{examples: in extensions} All extension authors are strongly encouraged to provide examples. These are exactly like the ones in _Writing with Inform_, so hundreds of example examples can be found among the source code for Inform. Each example should have its own file, and those files are placed in the ```Examples``` subdirectory of the documentation set. For example, suppose we are going to provide two examples, called "Unhinged" and "Please Do Not Perforate". Then the files would look like so: ``` code Philately-v1.i7xd ... Documentation Documentation.md Examples Unhinged.txt PleaseDoNotPerforate.txt Images InvertedJenny.jpg ``` Note that: 1) Example files like ```Unhinged.txt``` have filenames ending ```.txt```, not ```.md```. As we shall see, they are _almost_ Markdown files, but not quite. 2) The filename should be the name of the example with spaces and any other non-alphanumeric characters removed, and with camel-casing. So "What's Up, Jenny?" would be ```WhatsUpJenny.txt```. An example file consists of a _head_, and then a skipped line, and then the _body_. The body is just Markdown documentation exactly like that described in the chapter so far, except that it mustn't use ```#``` or ```##``` headings. It doesn't need any title at the top, because Inform generates that automatically from the head. So, then, the head. This might look like so: ``` code Example: *** Please Do Not Perforate Location: Actions for handling stamps Description: How to handle sheets of stamps being broken up along perforation lines. ``` Each line is of the form ```Key: Value```, that is, each line says what it specifies and then specifies it. The first line must begin ```Example:```, and then give 1 to 4 asterisks ```*```, ```**```, ```***``` or ```****```. These mean the same thing as they do in the main Inform documentation: they rate the example for simplicity, with fewer asterisks being simpler. A subsequent line must also give the `Description:`, though it doesn't actually have to be next. All other potential keys are optional, but the use of `Location` is strongly recommended. This should be the title of one of the sections of documentation. For example, if the extension's main documentation includes this: ``` code ## Actions for handling stamps Two actions are provided for... ``` ...then an example marked ```Location: Actions for handling stamps``` is placed at the foot of the section. As a genuine example of an example, then, the following is a complete one taken directly from `Locksmith by Emily Short`. It's typical of small examples which don't need very much explanation, so the source text is not broken up with explanations: that's why there's a single paste marker ```{*}``` and no resume-paste markers ```{**}```. ``` code Example: ** Rekeying Location: The passkey and keychain kinds Description: Modifying the way passkey descriptions work. As a default, Locksmith describes what passkeys unlock only after printing their default description. Under some circumstances, however, we might want to override that behavior, like this: {*}"Rekeying" Include Locksmith by Emily Short. The player carries a passkey called the tin key. The tin key unlocks the tin box. The tin box is closed, openable, lockable, and locked. In the box is a single Cheerio. Cereality is a room. "The newly-opened 'cereal bar' allows you to mix and match cereal types at will." The box is in Cereality. The passkey description rule is not listed in any rulebook. The description of a passkey is usually "[if the item described unbolts something][The item described] unlocks [the list of things unbolted by the item described][otherwise]You have yet to discover what [the item described] unlocks[end if]." Test me with "i / x key / unlock box / i / x key". ``` ## Testing ^^{extensions: writing: testing} ^^{testing commands: >TEST: testing extensions} Like any software, extensions need to be tested. They should ideally be exercised on a variety of plausible use-cases, with each feature being tried out. The examples are often ideal for doing that. So, for example, any bug fix made in `Philately by Peter Drake` can be checked out for safety by making sure that its four existing examples run as they should. Of course, this can be done by hand: by pasting in the example sources, running them in the Inform app, typing ``TEST ME``, and then looking over the resulting transcript of play to make sure it's all as it should be. But automated testing makes this much easier. From the documentation page on an extension, as displayed in the app, there is a link to a sub-page called ```run its 2 test case(s)``` (or whatever number there are, of course). That page provides a menu of testing options: it's possible to test an individual example, or all of them at once. On each test, four options are provided: _Test_. Compile the paste-me-in source text, play its ``TEST ME`` script of commands, and check the transcript of the story which results against the correct or _blessed_ transcript. This test can fail either if the story won't compile because of Problem messages, or if the story then plays incorrectly, or if no blessed transcript is available to check against. _Bless_. Compile the paste-me-in source text, play its ``TEST ME`` script of commands, and "bless" the transcript of the story which results as being the correct outcome. _Curse_. Remove the blessed transcript; there is then no officially correct version. _Rebless_. Equivalent to _curse_ then _bless_. Effectively says that the new behaviour may be different to the old, but that that's intentional, and that the new way is good. If we do bless the transcript of play from the two examples from `Philately`, and look inside the extension again, we see this: ``` code Philately-v1.i7xd ... Documentation Documentation.md Examples Unhinged.txt Unhinged--I.txt PleaseDoNotPerforate.txt PleaseDoNotPerforate--I.txt Images InvertedJenny.jpg ``` Two new files have appeared: ```Unhinged--I.txt``` and ```PleaseDoNotPerforate--I.txt```. These are the ideal transcripts of play from those examples. ## Test cases which are not examples ^^{extensions: writing: testing} ^^{testing commands: >TEST: testing extensions} Inform also allows test cases which are not examples from the documentation. Authors who are very much into "unit testing" will probably want to take advantage. For example, if `Philately` provides a high complicated phrase: To dismantle (album - a stamp album): ... then this may need testing with many different possible albums, to make sure everything works even in peculiar cases. (What if the album is empty? Or only contains many copies of the same stamp?) These oddball uses wouldn't make a good example. So an extension can also contain one or more "test cases". These exist only for testing and never appear in the documentation, so although they are similar to examples, they are much simpler in structure. They occupy a ```Tests``` subdirectory rather than living in ```Examples```: ``` code Philately-v1.i7xd ... Documentation Documentation.md Examples Unhinged.txt Unhinged--I.txt PleaseDoNotPerforate.txt PleaseDoNotPerforate--I.txt Images InvertedJenny.jpg Tests DismantleEmpty.txt DismantleEmpty--I.txt DismantleLarge-Z.txt DismantleLarge-Z--I.txt DismantleLarge-G.txt DismantleLarge-G--I.txt ``` There are three test cases here. Note that Peter Drake is prudently trying out one of them on both the Z-machine and Glulx settings, to make sure it works for both sorts of story. The convention (and it's only a convention) is to use the suffixes ```-Z``` and ```-G``` to distinguish these. The opening line of a test case takes the form ```Test: Title``` rather than ```Example: *** Title```. There's no row of asterisks. There's no meaningful ```Location:``` to give, nor ```Description:```, since those both relate to documentation. So the header for a test case is often just that one titling line. Also, once the header is finished, there is a skipped line and then an Inform source text - this is not indented and not surrounded by documentation. Here is a sample test case: ``` code Test: DismantleEmpty Include Philately by Peter Drake. ... Test me with "get album / dismantle album". ``` For a few tests, notably those which involve restarting the story file or performing ``UNDO`` commands, the "script" of commands needs to be stored in another sidekick file to the test case, rather than in a `Test me with ...` line in the source text. That can be done by creating a file like this: ``` code GET ALBUM DISMANTLE ALBUM UNDO PULL OUT PAGE 2 DISMANTLE ALBUM ``` Such a file should then be filenamed with an ```-S``` (for "script") suffix: for example, ```DismantleTorn--S.txt```. ## Full list of testing options As was mentioned earlier, the header for an example normally specifies ```Example:```, ```Location:``` and ```Description:```, while the header for a test case specifies ```Test:```. But further options are available. For example, the previous section suggested having two variants of the same test, one using the Z-machine and one Glulx. How is this to be done? The answer is that they are the same, but with different header options: ``` code Test: DismantleLarge-Z For: Z-machine ``` versus ``` code Test: DismantleLarge-G For: Glulx ``` The full list of legal options is given below, though users will rarely if ever need most of them. 1) ```RecipeLocation: Heading```. This is ignored for examples in extensions, but is used by examples in the main Inform documentation, and indicate which section of _The Recipe Book_ they should be filed in. (Inform examples use an identical file format to extension examples, but are present in two books at once, so they need two different location indicators.) 2) ```Index: Text```. Again, this is used for Inform documentation examples but ignored for extension examples. It gives a brief descriptive text to appear in the A-Z index of documentation examples. 3) ```Description: Text```. This is the strap-line underneath an example title, usually giving a brief explanation of what is being demonstrated. While it is not strictly compulsory, an example should really provide this. It's ignored for test cases. 4) ```Language: Basic` or `Language: Inform```. The default here is ```Language: Inform```, which means the example/test should be run using the normal Inform programming language. ```Language: Basic``` says that it is a Basic Inform example, that is, uses the pared-down version of the language with all interactive fiction features removed. 5) ```CompatibleWith: Description```. This can be used to mark an example as being compatible only with certain platforms. Most examples work on any platform, so the default ```CompatibleWith: all``` is fine. 6) ```For: Z-Machine``` or ```For: Glulx``` or ```For: C``` or ```For: Untestable```. Which platform the code should be compiled to when this example/test is tested. The default is ```For: Glulx``` provided that Glulx is compatible with the ```CompatibleWith``` description, and ```For: Z-Machine``` if it is not. If an even finer distinction is needed, ```For:``` can be set equal to any format text which Inform recognises: in fact, ```For: Glulx``` is a synonym for ```For: inform6/32```. ```For: Untestable``` says that an example doesn't really contain code which can usefully be tested, and that Intest can therefore ignore this example; test cases are not allowed to say this, since a test case which cannot be tested is a contradiction in terms. 7) ```CompileOnly: Yes``` or ```CompileOnly: No``` (the default is ```No```). This can specify that a test should be compiled but not played. The test is considered a success if no Problem messages are issued. Extension tests just might need to set this if an example is too complex to test fully, for example if it involves complicated screen effects. 8) ```TestCompilerInternals: Yes``` or ```TestCompilerInternals: No``` (the default is ```No```). This is only used for unit tests internal to the ```inform7``` compiler. Switching this on makes it possible to use the otherwise forbidden ``Test ... (internal) with ...`` in source text, which makes the compiler reveal its innermost thoughts. Extension tests will not need this. 9) ```TestReleaseMetadata: Yes``` or ```TestReleaseMetadata: No``` (the default is ```No```). This is only used for testing the Inform compiler, and specifically verifying the blurb and iFiction files it outputs on a release run. Extension tests will not need this. 10) ```GenerateIndex: Yes``` or ```GenerateIndex: No``` (the default is ```No```). Tests of an example or a test case are carried out in a throwaway Inform project, so that there is usually no point rebuilding the Index at the end of compilation — nobody will ever see it. But if the point of the test is exactly to check that the Index has been written correctly, then of course we do need to generate it, and it's for those test cases that this option exists. Extension tests will not need this. 11) ```GenerateDiagnostics: Yes``` or ```GenerateDiagnostics: No``` (the default is ```No```). Used only by one Inform compiler test case, and only to output certain files which show diagrams of internal data structures for use in the technical documentation on the website. Extension tests will not need this. ## Providing an index ^^{extensions: documenting: index for documentation} ### Basics of indexing The documentation for an extension can have an index much like the alphabetical index to _Writing with Inform_. This will really only be needed if the extension is a large one with a great deal of documentation to cover, of course. But by using the special marking-up features below, an extension's author can make Inform automatically generate an index page as part of its documentation set. Standard Markdown notation does not provide indexing features, so the conventions below are an extension to regular Markdown. (They are actually borrowed from notations originally devised by ^{@Donald Knuth} for indexing TeX's manual, _The TeXBook_.) For example: ``` code The ^{catalogue} of ^{@Roger S. Brody} lists three variants.^^{misprints} ``` The outward appearance of this line is exactly as if it had read: ``` code The catalogue of Roger S. Brody lists three variants. ``` but it accumulates three entries in the alphabetical index for the documentation: - Brody, Roger S. - catalogue - misprints Material in braces normally comes through into the visible documentation, but if the caret ```^``` is doubled then it does not. The ```@``` marker is for names, and inverts them when indexing, so that ```^{@Alice Zephyr}``` reads as "Alice Zephyr" but indexes as "Zephyr, Alice". Note that indexing marks are not read in backticked code or code examples. So: ``` code The `^{indexing}` notation is... ``` would not index anything, because the index markers occur inside a backticked piece of code. (This is a point of difference with the old ```indoc``` tool, which _did_ read index markers in example Inform source text.) ### Subentries If an entry's text contains a colon (with substantive material either side), that's taken as a marker that something is a subentry. Thus: ``` code ^{reptiles: snakes} ``` indexes under the "snakes" subentry of the entry "reptiles", while coming through into the visible documentation only as "snakes". Thus: ``` code "Why did it have to be ^{reptiles: snakes}?" mused Indy. ``` comes out as: ``` code "Why did it have to be snakes?" mused Indy. ``` Sub-entries can be arbitrarily deep. There can be, but need not be, index entries for the super-entry (in this case "reptiles") elsewhere. ### See... Indexes often provide multiple ways to look up the same thing: for example, they might contain an index entry reading "Superman, see Kent, Clark". ``` code ^^{Kent, Clark <-- Superman} ^^{reptiles <-- crocodiles <-- alligators} ``` The second example here creates two such crossreferences: "crocodiles, see reptiles" and "alligators, see reptiles". ### Alphabetization The index consists of "headwords", the terms being indexed (which may or may not be just one word), which are presented in alphabetical order in the index. These are alphabetized in a way which excludes initial "a", "an" or "the"; if the first word is a number from 1 to 12, it's replaced by the spelled version (thus "3 A.M." appears as if "three A.M."); other numbers are sorted numerically - thus "Zone 10" appears after "Zone 9", not after "Zone 1"; and any bracketed text is ignored for alphabetisation purposes - so "(leaf) tea" is alphabetised as if it were "tea". Alphabetization can be altered using the ```-->``` notation. For example: ``` code The Anglo-Saxon measure of land was the ^{hundred --> 100}. ``` This creates the index entry "hundred", but also tells Inform that it should be alphabetised as if it were the number 100: it thus appears in a different place in the index, but still as the text "hundred". This only needs to be done once. Subsequent indexing markers ```^{hundred}``` will go into the same place. Note that writing either ```^{hundred --> 100}``` or ```^^{hundred --> 100}``` will create an index reference to "hundred", as well as changing where this headword appears in the A-Z. If you want to set the alphabetization without creating an index reference at all, you can use three carets: ``` code ^^^{hundred --> 100} ``` ## Multiple-volume documentation and site maps An extension will hardly ever need this feature, but any documentation set can include two files of options: - ```contents.txt``` specifies the Markdown source files which make up one or more "volumes", and defines the notations used to index them. - ```sitemap.txt``` specifies the URLs for the HTML pages of the miniature website which the volumes are turned into. One file defines the _content_, while the other controls the _output_: thus the same content could generate different output for different purposes just by swapping out ```sitemap.txt```. ### The contents file A documentation set can in principle contain multiple volumes; the main in-app documentation for Inform contains two, _Writing with Inform_ and _The Recipe Book_. If no ```contents.txt``` file is provided then there is a single volume only, whose source must be entirely contained in the file ```Documentation.md```, and whose only indexing notations used are the basic ones described in [Providing an index]. For almost all extensions, that will be completely fine, of course. If given, ```contents.txt``` is a list of commands, each on its own line. Blank lines are ignored, as are lines beginning with the comment character ```#```. Three commands are legal: (1) ```volume: "Full Title of Volume" or "LABEL"``` creates a volume, giving both a full title for it and also a convenient abbreviation, which should not contain white space and should be different from the label of any other volume in the same set. For example: ``` code volume: "Writing with Inform" or "WWI" ``` (2) ```text: "Leafname.md"``` specifies that the current volume, that is, the one most recently declared, has this file as its next piece of content. A volume can have any number of content files; for example: ``` code volume: "The Lord of the Rings" or "LOTR" text: "Fellowship.md" text: "Towers.md" text: "Return.md" ``` would establish that the Markdown source for the LOTR volume would consist of these three files concatenated in the order given. The wildcard character ```*``` may be used up to once in each text name. So: ``` code text: "chapter*.md" ``` may match multiple files, and if so, will concatenate them in alphabetical order. Note that each ```text: ...``` command is required to match at least one file, and also that the ```contents.txt``` file as a whole is required to exactly account for all of the files in the documentation folder whose names end in ```.md```. It is thus impossible for loose Markdown files in this folder not to appear in at least one volume of the documentation. (3) ```index notation: NOTATION = MEANING``` allows the author to extend the set of indexing notations used in the volumes of this documentation set. Indexing notations are used to show what "category" a headword belongs in. By default, there are just two categories: ```standard``` and ```name```. It's as if the following commands are assumed: ``` code index notation: ^{headword} = standard index notation: ^{@headword} = name (invert) ``` To reiterate, these commands need not be given, since they are in effect already, but they make simple examples of the syntax. The notation part on the left shows how to mark up the ```headword```, using special characters either to the left or the right or both, to indicate the category. In the case of ```standard```, nothing special appears on either side; in the case of ```name```, an ```@``` character has to appear on the left. More elaborately: ``` code index notation: ^{XYZZY-headword-PLUGH} = magic ``` would set things up so that: ``` code The ^{XYZZY-magic word-PLUGH} cannot always be used. ``` would be printed as: ``` code The magic word cannot always be used. ``` but would make an index reference to the headword "magic word", of category ```magic```. Of course, that's not a very good notation, but _chacun à son goût_. Multiple notations for the same category are perfectly legal. So: ``` code index notation: ^{name... headword} = name (invert) ``` would make typing ```^{name... Emily Short}``` equivalent to typing ```^{@Emily Short}```. Categories are shown in the index, and they can also affect the HTML styling, as defined by some CSS, of the headword in question. Note the option ```(invert)``` placed after the category name. Several options are available: * ```(invert)``` means "invert forenames and surname" and is what turns ```Emily Short``` into the headword "Short, Emily". * ```(bracketed)``` means "use different CSS styling on any pieces of the headword which are in round brackets", the CSS style in question being ```indexCATEGORYbracketed```, where ```CATEGORY``` is the category name. * ```(unbracketed)``` means the same, except that any such round brackets are also removed from the headword. * ```(under X)``` means: make every headword in this category a subentry of the headword ```X```. * ```(also under X)``` means the same, except that headwords in this category are in the index twice, once in their own right and once as a subentry of ```X```. * ```(prefix "TEXT")``` means to add the text ```TEXT``` in front of all headwords of this category. * ```(suffix "TEXT")``` means to add the text ```TEXT``` after all headwords of this category. * ```("TEXT")``` adds the gloss text ```TEXT``` to all headwords of this category. So for example: ``` code index notation: ^{!headword} = monarch (suffix " (of Scotland)") (under monarchs) ``` would mean that ```^{!James VI}``` would lead the headword "James VI (of Scotland)" being filed as a subentry of the headword "monarchs". ### ```sitemap.txt``` If given, ```sitemap.txt``` is a list of commands, each on its own line. Blank lines are ignored, as are lines beginning with the comment character ```#```. The following commands are legal: ```contents: STYLE to "PATH"```. This refers to the contents page for a set of documentation. The default is ```contents: standard to "index.html"```, that is, making an ordinary-looking contents page and storing as ```index.html```. The alternative style is ```duplex```, which makes sense only when there are two volumes of documentation, and then presents their contents pages side by side. (This is how the contents page for the main Inform app documentation is made, but no extension is ever likely to need it.) ```volume contents: VOLUME to "PATH"```. This is only needed to give individual volumes their own contents pages. ```VOLUME``` should be the quoted title or label of the volume in question, which must be one of those created by the ```contents.txt``` file. For example: ``` code volume contents: "Writing with Inform" to "WI_index.html" ``` ```pages: VOLUME to "PATH"``` or ```pages: VOLUME by BREAKING to "PATH"```. Specifies how the content in the named volume is to be turned into individual HTML files. Giving ```all``` in place of a volume name applies the command to everything in every volume, and in particular is sensible if there's only one volume because no ```contents.txt``` file was given. Optionally, material can be split up ```by sections``` or ```by chapters```, in which case the content will be divided up following the level 1 and 2 headings in the Markdown documentation. If it is not split up in this way, then there will be one HTML file output for each Markdown file of source material in the volume. Clearly this can all result in multiple HTML files being created, so the ```PATH``` needs some flexibility in expressing names for those files. It supports two special characters: ```#``` expands to the section and chapter number for split files, so for example ```5_16``` for section 16 of chapter 5; and ```*``` expands to the unexpanded leafname of the Markdown source file from which material was drawn. For example: ``` code pages: "Writing with Inform" by sections to "WI_#.html" ``` The default, if no ```sitemap.txt``` file is supplied, is: ``` code pages: all by chapters to "chapter#.html" ``` ```example: LABELLING to "PATH"``` specifies how any examples in the documentation should be labelled — they can be ```numbered```, i.e., labelled 1, 2, 3, ..., or ```lettered```, labelled A, B, C, ... — and what files they should be written to. Again ```#``` is a special character meaning the label for the example. The default setting here is: ``` code examples: lettered to "eg_#.html" ``` which produces the files ```eg_A.html```, ```eg_B.html``` and so on. (If there are more than 26 examples, it's clearly better to use numbers, but the lettering runs ```A```, ..., ```Z```, ```2A```, ```2B```, ..., ```2Z```, ```3A```, ... and so on, so letters do not actually run out.) ```FORM index: "TITLE" to "PATH"``` specifies that a given index page should be generated, what title to give it, and where to put it. (These are indexes in the sense of book indexing, and not to do with the HTML sense of ```index.html``` pages.) For example, the built-in Inform documentation uses all four possible index pages: ``` code alphabetical index: "Alphabetical Index of Examples" to "alphabetical_index.html" numerical index: "Examples in Numerical Order" to "numerical_index.html" thematic index: "Examples in Thematic Order" to "thematic_index.html" general index: "General Index" to "general_index.html" ``` The general index is the A-Z listing of index entries produced by the ```^{...}``` notations used throughout the volumes; the other three indexes are ways to catalogue the examples in the volumes. "Thematic" order in this sense means the order in which examples occur in the second rather than the first volume; it's not likely to be useful for any other documentation set. ```cross-references: to "PATH"``` writes a set of cross-references generated from phrase descriptions and heading markers in the volumes into the named file, which is plain text rather than HTML. For example: ``` code cross-references: to "xrefs.txt" ``` This is only likely to be helpful for the main Inform documentation, not for extension documentation. # Low-Level Programming ## The architecture of Inform ^^{architecture of Inform} ^^{Inter code} ^^{I6: syntax} ^^{I6: not quite the same as Inform 6} ^^{Inform 6: not quite the same as I6} ^^{inform-fiction.org+web+} ^^{extensions: Inform 6 code in extensions} ^^{I6 <-- Inform 6} ^^^{Inform 6 <-- I6} Inside the Inform applications is a _compiler_, which turns source text which describes a story into a computer program which runs that story — or else, of course, refuses and issues Problem messages. Many programming languages are compiled. Inform is typical in that it does not perform the process in a single step. In fact it works in three main stages: 1) Source text is compiled down to a so-called _intermediate language_, called Inter. 2) Inter code is then _code-generated_ down to a low-level computer program written in some suitable _target language_. - In the Inform app, this other language will be Inform 6, created in the 1990s for generating interactive fiction _story files_. - For command-line users, it can instead be C, which can make an executable program for almost any computer old or new. 3) The relevant _back-end_ compiler, such as ```inform6``` or ```clang```, then turns that target program into the final product. Inform, however, is unusual in allowing programmers quite a lot of access to what goes on at stage (2). In particular it's possible to - change details of how Inform generates Inter from source text at stage (1), - teach Inform new ways to do this as part of phrase definitions, and - merge in Inter code which isn't generated from source text at all. Although Inter code does have a textual form of a sort, it isn't the sort of thing any human would want to write directly. This is fairly typical: ``` code typename K_number = int32 typename K_func = function /main/K_number -> /main/K_number package (K_func) R_101 _code local (/main/K_number) x code .begin inv !if inv !eq val x val 6 code inv !return val (/main/K_truth_state) 1 inv !return val (/main/K_truth_state) 0 ``` Inform therefore allows Inter to be produced not only from source text, but also from a second and much lower-level language. We will call this language "I6". We'll call it that because it looks very like Inform 6, though there are a handful of differences. These two chapters will assume a rough familiarity with I6 syntax. Readers who have ever used a language like ```C``` will probably be able to pick this up as they go along. For example, the Inter code above corresponds roughly to a function of ```x``` written like so in I6: ``` code [ R_101 x; if (x == 6) return true; return false; ]; ``` Failing guesswork, the documentation for the Inform 6 programming language is probably best: the _Inform Designer's Manual_, fourth edition (2001), the so-called "DM4", is the definitive book on that. This is open-access online: [Inform 6 Designer's Manual](https://inform-fiction.org/manual/html/). In 2001, Inform 7 did not exist, so "Inform" then meant "Inform 6". To reiterate, though, I6 material in an Inform source text is not fed in any direct way into the ```inform6``` compiler. It is translated into Inter code, which might or might not be code-generated to an Inform 6 program. Even if it is, the fragment which came from the I6 original will not look precisely the same. This is the first of two chapters about how to use I6 within Inform. In this chapter, we'll see how that can define powerful new phrases, among other things. These features will mostly benefit extension authors, but they can also be used directly in the source text for stories. In the next chapter, on [Kits], we'll go on to see how to create very much larger blocks of Inter which can provide the underpinning for powerful new features. Those can only usefully be created as parts of extensions. ## Defining To phrases with I6 {PM_UnendingI6} {PM_InlineTooLong} {PM_InlineRule} {PM_BadInlineExpansion} {PM_BadInlineTag} ^^{I6: syntax: phrases} ^^{phrases: defining in I6} ^^{((- -)), for writing I6 in source text+sourcepart+ --> (} ^^{punctuation: curly braces: used in I6 definitions of phrases+sourcepart+} ^^{|{ \}: used in I6 definitions of phrases} The phrases described in this book all have definitions given in the extensions automatically included with all projects — `Basic Inform`, the `Standard Rules` or, in a few cases, `English Language`. Those phrases are mostly, though not universally, defined using I6 notation, using the feature described below. For example, `Basic Inform` makes this definition: To say (something - number) in words: (- print (number) say__n=({something}); -). The minus sign in `(-` and `-)` is supposed to be a mnemonic for the decrease from 7 to 6: later we shall use `(+` and `+)` to go back up the other way, from 6 to 7. The use of the `(-` and `-)` notation, in place of an ordinary phrase body, tells Inform how to convert an _invocation_ of the phrase into Inter code. For example, `say 125;` would then be converted to the Inter resulting from this: ``` code print (number) say__n=(125); ``` whereas `say the capacity of the basket` might become: ``` code print (number) say__n=(I_basket_U1.A_capacity); ``` What has happened here, then, is that the _token_ `{something}` in the definition has been replaced by the value supplied to the `say` phrase. A few notes: 1) The I6 code given can contain multiple statements, not just one, and can include loops, function calls and so on. In practice they seldom run to more than a line or two, but they absolutely can. 2) These fragments of I6 will, once they become Inter code, eventually be translated to a target program. Even if that program is written in Inform 6, the original `say 125` and `say the capacity of the basket` would now come out differently again: ``` inform6 LanguageNumber((say__n = 125)); @push self; LanguageNumber((say__n = GProperty(OBJECT_TY, (self = I_basket_U1), A_capacity))); @pull self; ``` The details are unimportant. But it illustrates the point that writing I6 guides the compiler to create Inter: it doesn't compose literal Inform 6 material. 3) Programmers may want to note the difference between this and a more regular definition: To say (something - number) in words: say "I don't know how to say [something] in words." This second definition would create a _function_, and would call that function with the argument `125` or `I_basket_U1.A_capacity`. Phrases defined by `(-` and `-)` are more like what are called _macros_, though since they are type-checked they are more like the modern-day macros of languages like Swift or Rust than like the old-school macros of C. There can of course be more than one token in a phrase: To sort (T - table name) in (TC - table column) order: (- TableSort({T}, {TC}, 1); -). When the braced name of a token appears in the I6 — for example, ```{TC}``` — this is compiled to the I6 expression for whatever was supplied in that token. Braces `{` are significant in I6, so this syntax rule might cause ambiguity. To obtain a real brace, it's enough to ensure that the character following it is a space. It's also possible for the pair of characters `-)` to occur in I6 code, particularly with ```for``` loops like this one: ``` inform6 for (i=3 : i>0 : i--) ``` We can prevent Inform from reading the `-)` as terminating the I6 by again adding an extra space: ``` inform6 for (i=3 : i>0 : i-- ) ``` ## Defining To decide phrases with I6 ^^{I6: syntax: phrases to decide whether/if} ^^{I6: syntax: phrases to decide a value} ^^{phrases: defining in I6} The previous section showed how to define so-called _void phrases_ with I6: that is, those which do something, but produce no value or opinion as a result. We can also define _to decide phrases_ with I6. There are two sorts of these: first, those which decide whether or not something is true. An example of a phrase to decide whether something is true would be: To decide whether (N - a number) scares people: (- ({N} % 10 == 4) -). This in fact tests whether the number ends in a "4", which is considered bad luck in some Pacific Rim countries. (We'll ignore negative numbers.) A key difference between this definition and the ones in [Defining To phrases with I6] is that the content between `(-` and `-)` is not a series of statements ending in semicolons: it's an _expression_, which evaluates to a number. If that number is non-zero, the decision is yes; otherwise, the decision is no. In I6, there's no real difference between a condition and an expression, so a phrase to decide on a value is basically the same: To decide which number is the hours part of (t - time): (- ({t}/60) -). Again, this must be an I6 expression. It's conventional to write the value in round brackets, to emphasise that it is a value, and not a piece of imperative code. This is all very well when the kind of value needed can easily be expressed in I6. That's true enough for `number`, `real number`, `truth state`, and `time`. But values which need more elaborate storage, like `text` or `list of real numbers`, are not so simple. Beware that the I6 expression ```"rabbit"``` certainly looks like text, but it is _not_ a valid Inform `text` value. However, just as braces can be used to represent "tokens" (like `{t}` or `{N}` in the examples above), they can also do certain other things. A particularly useful one is `{-new:KIND}`, which produces a valid default value for the kind named. For example, `{-new:text}` makes a valid (albeit empty) text. The following decides on the list `{54, -18}`: To decide which list of numbers is the magic list: (- (LIST_OF_TY_InsertItem(LIST_OF_TY_InsertItem({-new:list of numbers}, 54), -18)) -). As examples like this suggest, it's not really possible to work with tricky kinds of value such as text, stored actions or lists without some knowledge of how they are implemented by ```BasicInformKit```, which provides Inter-level support for them. That's where the `LIST_OF_TY_InsertItem` function can be found, for example. ## By value and by reference Consider the following phrase definition, which reverses a list, so that `{1, 4, 9}` becomes `{9, 4, 1}`: To reverse (L - a list of numbers): (- LIST_OF_TY_Reverse({-lvalue-by-reference:L}); -). Clearly the actual work is done by the `LIST_OF_TY_Reverse` function from ```BasicInformKit```: how it does that work needn't concern us. But why isn't the definition this instead? To badly reverse (L - a list of numbers): (- LIST_OF_TY_Reverse({L}); -). The answer is that one translates `L` _by reference_, and the other _by value_. * `{L}` makes a _copy_ of the list passed to it, but * `{-lvalue-by-reference:L}` makes a direct reference to the original. So for example: When play begins: let L be {1, 4, 9}; showme L; reverse L; showme L; badly reverse L; showme L; produces first `{9, 4, 1}` — as expected, the effect of `reverse L` — but then `{9, 4, 1}` again. That's because `badly reverse L` made a copy of `L`, as a result of which it had its own independent list, which happened also to contain the numbers 9, 4, and 1; it reversed that copy; and then, since the copy was no longer needed for anything, threw it away. The original `L` was untouched. In general, then, if a phrase wants to mutate a piece of existing data in some way, it should be defined using a reference like this. ## Defining generic phrases in I6 ^^{generic phrases} ^^{kinds: kind variables} ^^{variables: kind variables} ^^{characters (letters): capital letters as kind variables} We have already seen so-called _generics_: see [Generic phrases] and [Kind variables] for details. But for example, To decide what list of Ks is tripled-up (V - value of kind K): let L be a list of Ks; add V to L; add V to L; add V to L; decide on L. When play begins: showme tripled-up 23; showme tripled-up "fish"; showme tripled-up {3, 7, 9}; This shows the lists: ``` transcript "tripled-up 23" = list of numbers: {23, 23, 23} "tripled-up "fish"" = list of texts: {"fish", "fish", "fish"} "tripled-up { 3, 7, 9 }" = list of lists of numbers: {{3, 7, 9}, {3, 7, 9}, {3, 7, 9}} ``` How might we replicate this if we were defining the same phrase using I6? Like so: To decide what list of Ks is tripled-up (V - value of kind K): (- (LIST_OF_TY_InsertItem( LIST_OF_TY_InsertItem( LIST_OF_TY_InsertItem( {-new:list of K}, {V}), {V}), {V})) -). And note that the kind variable `K` is available inside the I6 definition, where it is used in `{-new:list of K}`. ## Repeat loops and their variables A special syntax is available for defining new forms of `repeat` loop. For example: To repeat fivefold begin -- end loop: (- for ({-my:1} = 1: {-my:1} <= 5: {-my:1}++) {-block} -). Note the `begin -- end loop` suffix, which tells Inform that a "block" of further phrases hangs off of the loop. It is available _only_ for phrases which begin `repeat` or `while`, and since it's hard to imagine non-standard forms of `while`, it exists really to allow a range of interesting `repeat` loops to be created. The body of the loop expands into the token `{-block}` in its definition. For example, in the following: repeat fivefold: say "Bang!" `say "Bang!"` is the material which `{-block}` expands to. The other noteworthy thing in this definition is the repeated mention of `{-my:1}`. What this does is to allocate a temporary local variable, which in this case will be used as a loop counter. It can be used exclusively by the phrase for as long as the phrase is executing: we will never know its name. (It may already have been used by some other phrase before us, and may go on to further adventures afterwards.) Note that this: repeat fivefold: repeat fivefold: say "Bang!" works as expected, saying ``Bang!`` twenty-five times. Two different local variables are active here: `{-my:1}` for the outer loop will be a different variable from `{-my:1}` for the inner loop. I6 phrase definitions can allocate up to nine locals, `{-my:1}` to `{-my:9}`. While they are mostly useful for `repeat` loops, they're not restricted to them and do have other applications. The slightly foolish example above conceals its "loop variable". It's more usual to have a loop variable with a name. For example, `Basic Inform` contains a definition like so: To repeat with (loopvar - nonexisting K variable) running from (v - arithmetic value of kind K) to (w - K) begin -- end loop: (- for ({loopvar}={v}: {loopvar}<={w}: {loopvar}++) {block} -). ...to tell Inform how to compile something like: repeat with ticker running from 9:10 am to 10:51 am: say "The ticker reads [ticker]."; Here `9:10 am` is a `time` value, and that is indeed an `arithmetic value`, so `v` is set to `9:10 am` and `K` is set to `time`; and that fits with `w`, because `10:51 am` is also a `time`. So far, so good. But note the first token, which has a rather unusual wording. `nonexisting K variable` matches any name which is not already taken, and creates a local variable with that name, giving it the kind `K`. So in this case, it creates `ticker`, and gives it the kind `time`. The loop header is then expanded. In `for ({loopvar}={v}: {loopvar}<={w}: {loopvar}++)`, the token `{loopvar}` expands to whatever local `ticker` has been assigned to. In the body of the loop, meanwhile, `ticker` compiles to this same local. And when the loop completes, the variable will be given up again. Besides `nonexisting K variable`, Inform also supports `existing K variable`, which differs from it in the obvious way. Both can only refer to local variables, which are basically `let` values and `repeat` loop counters. But these are in fact special cases of a more general concept, _storage_: somewhere a value can be stored. For example, if we write: A door has a number called street number. The red door is a door in the Old Street. The postal delivery time is a time that varies. ...then `postal delivery time` and `street number of the red door` are both examples of storage which would not match either `existing K variable` or `nonexisting K variable`. The phrase token `storage` matches any storage location; `storage of KIND` matches storage holding a given kind. For example: To clear the (name of kind of value K) in (S - storage of K): (- {-my:1} = {-new:K}; {-copy:S:1} -). Note another tricksy bracing there: `{-copy:S:1}` makes a copy of the data in `{-my:1}` and puts it in the storage item `S`. This is needed because it really isn't as simple as `{S} = {-my:1}`: it can expand to rather more code than that, depending on what the nature of the storage is. ## Invocation counters {PM_LabelNamespaceTooLong} As we have seen, I6 phrase definitions are able to create temporary values, sometimes with natural-language names, sometimes anonymously, which last for the duration of the phrase's execution but no longer. But they can also be given some persistent state: that is, some sort of value which is retained between one invocation and the next. This is managed using _invocation counters_. Here is a simple example: To moan: (- print "That's ", {-counter:MOANCOUNT}, ".^"; {-counter-up:MOANCOUNT}; -). If we then run `moan; moan; moan`, we get: ``` transcript That's 0. That's 1. That's 2. ``` There is no variable called `MOANCOUNT`. This is only a label we're using so that we can have multiple different counters and still distinguish them from each other. The first time Inform invokes `moan;`, it expands the bracing `{-counter:MOANCOUNT}` to 0. It also expands `{-counter-up:MOANCOUNT}`, which produces no code in the final program, but internally adds 1 to the `MOANCOUNT` held in the compiler. And so on. `moan; moan; moan` therefore compiles to the equivalent of: print "That's ", 0, ".^"; print "That's ", 1, ".^"; print "That's ", 2, ".^"; Note that this is contrast with: repeat with X running from 1 to 3: moan; This would print: ``` transcript That's 0. That's 0. That's 0. ``` The counter does not count the number of times the phrase is _executed_: it counts the number of times it is _invoked_, that is, compiled. The `repeat` loop above does something three times, but what it does uses the same invocation each time. That really only seems mildly useful, though. Where invocation counters come into their own is in managing storage. Here is another toy example: To remember (N - number): (- {-counter-makes-array:MEMCOUNT} {-counter-storage:MEMCOUNT}-->{-counter:MEMCOUNT} = {N}; -). To decide which number is the remembered number: (- ({-counter-makes-array:MEMCOUNT} {-counter-storage:MEMCOUNT}-->{-counter:MEMCOUNT}) -). What happens here is that `{-counter-makes-array:MEMCOUNT}` says that Inform should reserve run-time storage in an array which has one entry for each possible value of the counter (in this case, `MEMCOUNT`). In this toy example, the counter is never actually incremented — there's no `{-counter-up}` — so in fact the array will contain only a single entry. Still, that's memory. The effect is that: remember 267; say "Oh yes, I was going to use [the remembered number] for something."; will output ``Oh yes, I was going to use 267 for something.`` Between the execution of the two phrases, the value 267 was stashed in the array entry `{-counter-storage:MEMCOUNT}-->0` (because `{-counter:MEMCOUNT}` was 0). It is also possible to move counters downwards, using `{-counter-down:MEMCOUNT}`. This must be done with great care, because they cannot be allowed to go below zero. Still: To remember (N - number): (- {-counter-makes-array:MEMCOUNT} {-counter-up:MEMCOUNT} {-counter-storage:MEMCOUNT}-->{-counter:MEMCOUNT} = {N}; -). To decide which number is the remembered number: (- ({-counter-makes-array:MEMCOUNT} {-counter-storage:MEMCOUNT}-->{-counter:MEMCOUNT} {-counter-down:MEMCOUNT}) -). Provided the user is very careful, this allows the following to work: remember 5; remember 11; showme the remembered number; showme the remembered number; producing ``` transcript "remembered number" = number: 11 "remembered number" = number: 5 ``` So here we've made a little stack. The outer invocations of `remember` and `remembered number` are using the entry `{-counter-storage:MEMCOUNT}-->0`, which holds 5, and the inner pair are using the entry `{-counter-storage:MEMCOUNT}-->1`, which holds 11. As a final spin on all of this, `{-counter-makes-array:MEMCOUNT:3}` would have told Inform to allocate three consecutive array entries per counter value of `MEMCOUNT`, rather than just one. So we can have more storage then just one value, if we need it. This is all a little fragile and contrived-looking, but it will come into its own when we make segmented say phrases, in the next section. Counters can also be used to make jump labels. For example, To start screening (N - number): (- {-counter-up:SCREENCOUNT} {-counter-makes-array:SCREENCOUNT} {-counter-storage:SCREENCOUNT}-->{-counter:SCREENCOUNT} = {N}; -); To screen out (M - number): (- if ({-counter-storage:SCREENCOUNT}-->{-counter:SCREENCOUNT} == {M}) jump {-label:SCREENCOUNT}; -); To finish screening: (- .{-label:SCREENCOUNT}; -). And then, for example: start screening 20; screen out 5; say "Well, it wasn't 5."; screen out 10; say "Or 10."; screen out 20; say "Or 20."; finish screening; say "Done."; produces: ``` transcript Well, it wasn't 5. Or 10. Done. ``` because `screen out 20` jumped to the `finish screening` point, but `screen out 5` and `screen out 10` did not. In practice, this is a very rickety way to define bizarre control structures, but if used with care then some surprising effects are possible. ## Defining segmented text substitutions with I6 ^^{I6: inclusions: phrase elements} ^^{text substitutions: defining: segmented} ^^{defining: text substitutions: segmented} A "segmented" text substitution is a syntax where text is placed between two or more different text substitutions. For example: "Annie [one of]dances[or]sulks[or]hangs out at Remo's[at random]." Here there are four segments: `one of`, `or`, `or`, and `at random`. Implementing segmented substitutions will make great use of the invocation counters and storage feature already described (see [Invocation counters]), but it needs something else, too. We have to guard against the user accidentally writing this: "The hotel [at random] is on fire." We want `at random` to be legal only when closing a `one of` construction. But if `at random` had been defined as just another text substitution, Inform would not have been able to detect that. Inform therefore allows us to mark text substitutions as being any of three special kinds: beginning, in the middle of, or ending a segmented substitution. - If the phrase prototype ends `-- beginning CONSTRUCT`, then this is a substitution beginning the segmented substitution code-named `CONSTRUCT`. - If it ends `-- continuing CONSTRUCT`, then it can appear only between a beginning phrase and an ending phrase for the same `CONSTRUCT`. Any number of continuing segments can appear, including none. - If it ends `-- ending CONSTRUCT`, then it brings this use to an end. This phrase has to follow a beginning phrase for the same `CONSTRUCT`. These code-names are just labels to tell the compiler to tie the phrase definitions together: they have no other significance. As a simple example, in this construct we have a beginning and an ending segment but no continuing ones in between: To say emphasis on -- beginning say_emphasis_on: (- style underline; -). To say emphasis off -- ending say_emphasis_on: (- style roman; -). This creates `"[emphasis on]"` and `"[emphasis off]"` such that they can only be used as a pair, like so: "This is [emphasis on]quite sophisticated[emphasis off]." Here we used the code-name `say_emphasis_on` to tell Inform to relate these two definitions together. It seems a good idea to choose code-names which, like this one, consist of the construction's name but with underscores in place of spaces: that way, no unexpected name clashes between code-names are likely to occur. Note that Inform does _not_ allow the same segmented say construction to be nested in the same text, and this greatly simplifies things when defining them. ### Worked example: say one of The `say one of` construction is immensely useful, and also extensible. It can't be implemented fully in stand-alone phrase definitions, because it needs some supporting I6 functions, perhaps stored in some kit. Even so, it requires no special compiler support. In particular, let's see how `"[one of]Alice[or]Bettina[or]Carol[cycling]"` works. This is supposed to print ``Alice`` the first time, then ``Bettina`` the second, then ``Carol``, then back to ``Alice`` and so on. Unsurprisingly the beginning segment does almost all of the work, because that's the part which chooses what to print. Here goes, in slightly simplified form: To say one of -- beginning say_one_of: (- {-counter-makes-array:say_one_of} {-counter-storage:say_one_of}-->{-counter:say_one_of} = {-final-segment-marker}({-counter-storage:say_one_of}-->{-counter:say_one_of}, {-segment-count}); switch (({-counter-storage:say_one_of}-->{-counter:say_one_of}{-counter-up:say_one_of})%({-segment-count}+1)-1) {-open-brace} 0: -). To say or -- continuing say_one_of: (- {-segment-count}: -). To say cycling -- ending say_one_of with marker I7_SOO_CYC: (- {-close-brace} -). What does this produce? Suppose this is the 7th invocation of the phrase in the story, and suppose Inform has chosen to put the storage into `some_array`. Then we get code like this: some_array-->6 = I7_SOO_CYC(some_array-->6, 3); switch ((some_array-->6) % 4 - 1) { 0: print "Alice"; 1: print "Bettina"; 2: print "Carol"; } Note that when expanding a beginning phrase, `{-segment-count}` expands to the number of segments used (not counting the ending) — here, that's 3. But when expanding a continuing phrase, it expands to a count of the segments so far. So in the first use of `"[or]"` it becomes 1, and in the second 2. The `4` in the line `switch ((some_array-->6) % 4 - 1` is initially a little mysterious. What are there four of? The answer is that we are allowing for a fourth possibility, which is to print nothing at all. In the `one of ... cycling` construction, that never happens. But in `one of ... stopping`, for example, it does. The idea, then, is that if `some_array-->6` contains 1, we print ``Alice``; for 2, we print ``Bettina``; for 3, ``Carol``; but for 0, we would print nothing. The other enigmatic thing here is the "marker", which seems to be the strange-looking `I7_SOO_CYC`. This is a way to allow the same construction to have multiple possible endings. For example: To say stopping -- ending say_one_of with marker I7_SOO_STOP: (- {-close-brace} -). The only difference between `"[stopping]"` and `"[cycling]"` is that they have different markers: `I7_SOO_STOP` and `I7_SOO_CYC`. These are in fact the names of functions which can be found in ```BasicInformKit```. They look like so: [ I7_SOO_CYC oldval count; oldval++; if (oldval > count) oldval = 1; return oldval; ]; [ I7_SOO_STOP oldval count; oldval++; if (oldval > count) oldval = count; return oldval; ]; Each of these functions takes the original state of the counter, which will be `some_array-->6`, and the total number of segments, and returns a new state. Note that the initial state is always 0. `I7_SOO_CYC` takes this to 1, then 2, then 3, then 1, then 2, ...; whereas `I7_SOO_STOP` takes this to 1, then 2, then 3, then 4, then 4, then 4, ...: and this value causes printing not to occur. So that is how we get the cycling versus stopping behaviour. `Basic Inform` defines a number of other possible endings, each with its own marker function to perform the state change. Because `"[one of] ... [or] ..."` is such a useful construction – switching between alternative forms of text, which writers of IF very often do – the above implementation is intentionally left open for new endings to be added, and the examples below show how easily this can be done. Lastly: the weasel words about "slightly simplified form" above are because the description above leaves out some highly technical business to do with making sure that comparisons between two texts do not behave unexpectedly because one has been iterated during the comparison process. Essentially, we turn off the state changing during the time when a text comparison is being made. But this detail does not change the big picture. ## Defining adjectives with I6 ^^{I6: inclusions: adjectives} ^^{adjectives: defining: with I6} There are three ways to specify that an adjective is defined at the I6 level. For example: Definition: a number is prime rather than composite if Inter routine "PRIMALITY_TEST" says so (it is greater than 1 and is divisible only by itself and 1). Inform now actually tests if a number N is prime by calling ```primality_test(N)```, and it assumes that we have also included such a routine in the output. The routine is expected to return true or false accordingly. The text in brackets does nothing functional, but is the text used in the Lexicon dictionary part of the Phrasebook index for the user's benefit; it should be a brief definition. Extension authors are asked to provide these little definitions, so that their users won't be confused by blank lexicon entries. The second way makes a more capable adjective, since it can not only be tested, but also made true or false using `now`. For example: Definition: a scene is crucial if Inter routine "SceneCrucial" makes it so (it is essential to winning). The difference here is `makes it so`, not `says so`, and as this implies, the routine has more power. `SceneCrucial` is called with two arguments: z `SceneCrucial(S, -1)` tests whether the scene is crucial or not and returns true or false; `SceneCrucial(S, true)` must make it true; and `SceneCrucial(S, false)` must make it false. Another useful difference is that if the kind of value is one which is stored in block form (e.g. for an adjective applying to text), the routine is given a pointer to the block, not a fresh copy. A third way to define an adjective, which should be used only if speed is exceptionally important, is to provide a "schema" – a sort of I6 macro, like those provided by the C preprocessor. For example: Definition: a rulebook is exciting if I6 condition "excitement_array-->(*1)==1" says so (it is really wild). The escape `*1` is expanded to the value on which the adjective is being tested. (This is usually faster than calling a routine, but in case of side-effects, the `*1` should occur only once in the condition, just as with a C macro.) To repeat: if in doubt, use the Inter routine method above. ## Inform values from I6 {PM_TranslatesNonAction} {PM_TranslatesActionAlready} {PM_TranslatedTwice} {PM_TranslatedUnknownCategory} {PM_TranslatedToNonIdentifier} {PM_NonPropertyTranslated} {PM_NonQuantityTranslated} {PM_QuantityTranslatedAlready} {WM_BracketPlus} ^^{accessible to Inter as...+assert+} ^^{Inter code: accessible to Inter as...+assert+} ^^{properties: making accessible to I6} ^^{actions: making accessible to I6} ^^{objects: making accessible to I6} ^^{kinds: making accessible to I6} ^^{activities: making accessible to I6} ^^{((+ +)), for including Inform 7 code in I6+sourcepart+ --> (} What if an I6-written definition needs to access something defined in the source text? For suppose, if the source text says: The Maltese Falcon is on the mantelpiece. How can I6 code refer to the Falcon? Clearly, inside the Inter code for the story, there will be some constant whose value is the object number for the Falcon. But what is it? Probably something like `I_maltese_falcon_U1`, but only probably. The Inform compiler could have chosen anything it wanted. How can we find out? Here are three answers, with the best first. ### By not finding out The flip answer is that there's almost certainly a better way to achieve whatever is needed by writing Inform source text in the ordinary way. For example, there's no need to write: To decide whether clues are here: (- (TestVisibility(player, I_maltese_falcon_U1)) -). since this works fine: To decide whether clues are here: decide whether or not the player can see the Maltese Falcon. ### By making it accessible to Inter The next best option is to tell the Inform compiler to make the I6 value for the Falcon available by defining a constant which will refer to it. For example: The Maltese Falcon object is accessible to Inter as "MALTESE_FALCON". To decide whether clues are here: (- (TestVisibility(player, MALTESE_FALCON)) -). Other constructs can also be made accessible in this way. Here is a rulebook: The banana rules is a rulebook. The banana rules is accessible to Inter as "BANANA_RULES". A banana rule: say "I am yellow!" To exhibit the behaviour: (- FollowRulebook(BANANA_RULES); -). And here is an activity: Grimly testing something is an activity. The grimly testing activity is accessible to Inter as "GRIM_ACT". For grimly testing: say "I am grimly testing." To exhibit the behaviour: (- CarryOutActivity(GRIM_ACT); -). An action: Smashing is an action applying to one thing. The smashing action is accessible to Inter as "Smash". To go smash (target - a thing): (- TryAction(false, player, ##Smash, {target}, nothing); -). A kind: A fruit is a kind of thing. The fruit kind is accessible to Inter as "K_fruit". A property: A thing can be coveted or neglected. The coveted property is accessible to Inter as "coveted". A table and column: Table of Fizzy Drinks name niceness "coke zero" 1 "sprite" 0 The Table of Fizzy Drinks is accessible to Inter as "TABLE_FIZZ". The niceness column table column is accessible to Inter as "NICENESS_COLUMN". A phrase: The doubling phrase is accessible to Inter as "DOUBLING_FN". To double up (N - a number): (- print "Twice ", {N}, " is ", DOUBLING_FN({N}), "^"; -). A kind: A dragster is a kind of vehicle. The dragster kind is accessible to inter as "K_dragster". To decide if (V - vehicle) drags: (- ({V} ofclass K_dragster) -). And an enumerated value: A colour is a kind of value. The colours are cerise, cerulean and chartreuse. The cerulean value is accessible to inter as "CERULEAN_COLOUR". Variables, however, cannot at present be made `accessible to Inter`. Note that none of these constructions — the `banana rules`, the `grimly testing something activity`, the `smashing action` and so on — are being created from raw Inter material. The Inform compiler is creating them, just as normal. All that is happening is that _names_ for them are being made available at the I6 level. ### A now-deprecated trick: using `(+` and `+)` This is very much a last resort. But for _some_ simple Inform values, it's possible to mix source text with I6 code like so: To decide whether clues are here: (- (TestVisibility(player, (+ Maltese Falcon +) )) -). Just as `(-` and `-)` is supposed to suggest stepping down from Inform 7 to I6, so `(+` and `+)` is supposed to suggest stepping up again. Two cautionary notes: 1) This feature is being removed from Inform. Any use of it generates warning messages, and in the next major release, the feature will be gone. 2) On rare occasions, this notation can be triggered by accident. For example, this admittedly very strange definition looks as if it should work: To count: (- for (++{-my:1}; {-my:1}<10; {-my:1}++) print i, " "; -). But in fact it doesn't, because it contains what Inform thinks is a matched pair of `(+` and `+)` either side of `+{-my:1}; {-my:1}<10; {-my:1}+`. That excerpt is obvious nonsense, of course, and it will throw a problem message. This could be fixed by inserting a space: To count: (- for ( ++{-my:1}; {-my:1}<10; {-my:1}++) print i, " "; -). Note that `+)` is only significant where it follows a `(+`, and in this revised version it doesn't. ## Use options from I6 ^^{use options: accessing from I6} A phrase with an I6 definition can access the settings of use options directly provided that they have been declared with a view to that. For example: Use drifting lilypads translates as the configuration flag DRIFTING_LILYPADS. Use horny skin translates as the configuration value SKIN_TYPE = 1. Use scaly skin translates as the configuration value SKIN_TYPE = 2. Use frog count of at least 10 translates as the configuration value FROG_COUNT. Use maximum jump height of 6 translates as the configuration value JUMP_HEIGHT. See [Use options for extensions] for more on how to define these: the important point here is that, because the declarations supplied identifier names for the values, those values are now accessible from I6. For example: To jump (H - height): (- if ({H} > JUMP_HEIGHT) print "Jumping ", JUMP_HEIGHT, " feet.^"; else print "Jumping ", {H}, " feet.^"; -). Note that `DRIFTING_LILYPADS`, `SKIN_TYPE`, `FROG_COUNT` and `JUMP_HEIGHT` are all constants, not variables. ## Phrase options from I6 ^^{I6: inclusions: phrase options} ^^{phrases: defining in Inform 6} The Standard Rules use the Inform list-writer with the following definition, which shows how a much more complicated I6 routine can be given a natural-language expression. {*}To list the contents of (O - an object), with newlines, indented, giving inventory information, as a sentence, including contents, including all contents, tersely, giving brief inventory information, using the definite article, listing marked items only, prefacing with is/are, not listing concealed items, suppressing all articles and/or with extra indentation: (- I7WriteListFrom(child({O}), {phrase options}); -). This can be used by, say: list the contents of O, as a sentence, using the definite article `{phrase options}` is a special substitution: it is a bitmap which assigns the given options one bit each, starting with the least significant bit for the first-mentioned option (`with newlines` above) and going up to the most significant bit for the last (`with extra indentation`). ## Inclusions of I6 code {PM_BadI6Inclusion} {PM_BeforeTheLibrary} {PM_WhenDefiningUnknown} {PM_IncludeInsteadOf} ^^{I6: inclusions: long sections of code} ^^{kits (I6 code): replacing use of templates} ^^{kits (I6 code): including sections of I6} With some reluctance, we now need to come to an entirely new sentence meaning: `Include (- ... -)`, which allows the user to insert whole I6 "directives" into a story. When defining phrases with `(-` and `-)`, we were only contributing small fragments of functions: but now we can write entire functions, variables and so forth. Why the reluctance? The answer is that, where possible, it's always best to separate out Inform source text from any low-level I6 material. Any large quantities of I6 are much better placed in a kit: see the final chapter, [Kits]. So, for example, the source text for the `Standard Rules` and `Basic Inform` extensions do not make a single use of `Include (- ... -)`. Although they need a great deal of Inter code to back them up, all of that is in ```BasicInformKit```, ```WorldModelKit``` and so on. With that said, here for example is a directive which creates an I6 function: Include (- [ FauxMultiply a b; return a*b; ]; -). And that could then be used like so: To decide which number is the faux multiplication of (X - number) and (Y - number): (- (FauxMultiply({X}, {Y})) -). Inclusions like this can also use `(+` and `+)` — see [Inform values from I6] for those — but the use of these is strongly discouraged, and subject to a number of hazards. There was no problem creating a new function called `FauxMultiply`, but what if we tried to create, say, `SquareRoot`? We would then run into trouble because there is already a function of that name in ```BasicInformKit```. So we would get a problem message about the name clash. But what if the name clash was not an accident at all, and what we actually wanted to give our own definition of `SquareRoot`, to be used instead of the one in BasicInformKit? This is also possible: Include (- [ SquareRoot num; "Nobody cares about square roots, son."; ]; -) replacing "SquareRoot". And now whenever square roots are calculated, this snarky text will be printed, and the result will always be rather meaningless (since this I6 routine always returns 1). Unless one is very careful, the result of replacing kit definitions can be absolute chaos. ### Historical note Between about 2010 and 2021, kits did not exist, but there were "template files" which served roughly then same purpose. These had names like `Relations.i6t` or `Mathematics.i6t` and were internally divided into named subsections; and Inform supported syntax like the following: Include (- ... -) before "Relations.i6t". Include (- ... -) instead of "Relations.i6t". Include (- ... -) after "Symmetric One To One Relations" in "Relations.i6t". to allow new material to be placed at oddball positions in the final code. There is now no need to worry about the placement of code – Inform's final code generator manages things so that code-ordering issues do not arise; as a result, the `before` and `after` options are now unnecessary. For now, Inform ignores these usages, and just disregards the `before...` or `after...` parts. But in some later version of Inform they will begin to cause problem messages, so writers of extensions using these syntaxes should now please remove them. The `instead of` option now cannot work at all, and throws a problem message. The new way to substitute a fresh definition of something built-in is to use the `replacing` notation described above. ## How I6 differs from Inform 6 ^^{I6: syntax} ^^{I6: not quite the same as Inform 6} ^^{Inform 6: not quite the same as I6} To recap: I6 is the notation we are using when writing low-level code inside `(-` and `-)` markers. It looks very like the programming language Inform 6, but there are a handful of differences. In particular: 1) Only new-style `for` loops with colons in the header are allowed, so that `for (i=0: i<10: i++ )` is okay but `for (i=0; i<10; i++ )` is not. Moreover, `for` loops cannot contain empty clauses. 2) Local variable names are not allowed to be the same as an I6 statement keyword: for example, `style` and `spaces` are not allowed. 3) The (undocumented) Inform 6 function `indirect()` is not supported. But since `indirect(A)` is equivalent to `A()`, which does work, this is no real loss. Similarly, the `glk()` function is not supported: function calls to BasicInformKit should be used instead. 4) Conditional compilation cannot be placed around cases in a `switch` statement. 5) Compile-time constant expression evaluation can be used with arithmetic operations, so `Constant foo = bar + 1;` is okay, but not with bitwise or logical operations, so `Constant foo = (bar | 1);` does not work. 6) Calculated values cannot occur as assembly-language operands. 7) Calculated values can be used for array extents, but need to be put in brackets. For example: Include (- Array unit_captured_text --> (UNIT_CAPTURE_BUFFER_LEN + 1); -). # Kits ## About kits ^^{kits (I6 code) <-- templates: I6 template layer} ^^{I6: in kits} A _kit_ is a body of code written entirely in I6 syntax. It is compiled independently from the source text of a story which uses it, and the two are then merged together (or _linked_). Kits can be quite large: ```BasicInformKit```, which sits inside the `Basic Inform` extension, runs to over 12,000 lines. Equally, they do not have to be. It's fine to write a kit containing just a single function or two. Kits sit inside extensions, and provide them with support services. An extension can contain multiple kits, but of course does not need to contain any. Kits increase the power of extensions in a number of ways. They can access memory directly, and are not constrained by the kind-safety rules which would apply to higher-level code. For example, all the code to build, sort and dismantle lists is done by functions in ```BasicInformKit```. Kits can also create new fundamental kinds of value for Inform. This chapter is the most technical in the book. It's aimed at writers of extensions who need more power, and it assumes the reader is comfortable with the material in the [Extensions] and [Low-Level Programming] chapters, together with at least a passing knowledge of Inform 6 syntax, since that's essentially the same thing as writing I6. ## Adding a kit to an extension Suppose the extension `Roots of Equations by Peter Drake` wants to perform some mathematical algorithms which will be coded in I6. We will do this by placing the I6 material in ```RootsOfEquationsKit```, which will live inside the extension like so: ``` code Ducking Action-v1.i7xd extension_metadata.json Materials Inter RootsOfEquationsKit ... Source Ducking Action.i7x ``` All kits have to have names ending in `Kit`, and by convention if an extension contains a single kit then its name is the extension title in camel-casing with the spaces removed and `Kit` suffixed. So `Roots of Equations` becomes ```RootsOfEquationsKit```. Note that kits live inside the `Inter` subdirectory of the `Materials` directory private to the extension. See [Images and other resources] for more on `Materials`, which can also include all manner of other good things. ```RootsOfEquationsKit``` is itself a directory, which looks like this: ``` code RootsOfEquationsKit Contents.w kit_metadata.json Sections Roots.w ``` The actual I6 source for the kit code is in the file `Roots.w`, but before we can get to that, we have to do some book-keeping. 1) The `Contents.w` file doesn't look very interesting at first because there's only one source file, `Roots.w`, so this is currently like a contents page for a book with only one chapter: ``` code Title: RootsOfEquationsKit Author: Peter Drake Purpose: Some Newton-Raphson approximation functions. Language: Inform 6 Sections Roots ``` 2) There must also be a `kit_metadata.json` file: ``` code { "is": { "type": "kit", "title": "RootsOfEquationsKit" } } ``` This should look very similar to the `extension_metadata.json` file found in extensions, and indeed it has a great deal in common, though as we shall see it can be considerably extended. Although it's legal for a kit's metadata to supply a `"version"`, there is no need. A kit which is being distributed inside an extension has a public-facing version of its own: its functionality is part of the extension's offer to the world, so it is all under the wrapper extension's version number. Why are there two files like this, not one, given that both are basically descriptions of what the kit is? One answer is that they actually serve different purposes: `Contents.w` describes the _source code_ for the kit, whereas `kit_metadata.json` describes the resulting compiled kit. The other is that kits are designed to be compatible with the ```inweb``` system for "literate programming". This is how it is that annotated forms of the source for ```BasicInformKit``` and ```WorldModelKit```, for example, are hosted at the Inform source code website. So-called _section files_ also have a marked-up format suitable for ```inweb```. (The ```.w``` at the end of the two filenames ```Contents.w``` and ```Roots.w``` means "web".) Here is a minimal but legal form for ```Roots.w```: ``` code Roots Some functions for finding roots of polynomials by Newton-Raphson approximation. @ Just one placeholder for now: = [ EvaluatePolynomial f x; print "Not implemented yet.^"; ]; ``` Web files begin with a line giving the title of the section — here, ```Root``` — then skip a line, and give a sentence or two describing the content in slightly more detail. After that, they are a sequence of "paragraphs". Each paragraph begins with an ```@``` character on the left margin. There's then space for some commentary about what is coming up: authors usually use this space to document calling conventions for functions, or say why they work they way they do. There is then a line with an ```=``` character on the left margin. After that, the rest of the paragraph is I6 code. So the actual content of the above section, once all the annotations are peeled off, is just this: ``` code [ EvaluatePolynomial f x; print "Not implemented yet.^"; ]; ``` In other words, the kit — which is now complete — provides just a single function. We can now use it. As established, ```RootsOfEquationsKit``` is sitting inside the extension `Roots of Equations by Peter Drake`. We call this the _wrapper extension_ for the kit. That extension might now contain this phrase definition: To decide which real number is the evaluation of (polynomial - list of real numbers) at (x - real number): (- (EvaluatePolynomial({polynomial}, {x})) -). If we then run a test project which includes the extension, and if we are looking carefully, we might notice this message scroll by on the console: ``` code (Building RootsOfEquationsKit for architecture 16) (Building RootsOfEquationsKit for architecture 16d) (Building RootsOfEquationsKit for architecture 32) (Building RootsOfEquationsKit for architecture 32d) ``` This is because Inform can only use ```RootsOfEquationsKit``` once it has been built (i.e., compiled): and since Inform could see the source code for the kit, it went ahead and built the thing. Inform builds kits only when necessary. If the timestamp on the source code files is later than that of the built form of the kit, then Inform assumes the source code has been changed since the last time the kit was built, so it rebuilds. Otherwise, if the kit source remains unchanged, Inform won't build the kit again. In fact, it builds the kit not once but four times, once for each possible architecture the kit will run on. (Once built, a kit is what is sometimes called a "fat binary", in that it contains multiple different compiled versions in one.) ```16``` and ```32``` refer to the 16-bit and 32-bit versions used on Z-machine and Glulx respectively, and ```16d``` and ```32d``` the same but with debugging features enabled — in effect, not-for-release features. By default, in the app, a project will use the ```32d``` architecture, and then when released, the ```32``` architecture. Inform handles all of this automatically. If we look back at the directory, we see that more files have appeared: ``` code RootsOfEquationsKit arch-16.interb arch-16d.interb arch-32.interb arch-32d.interb Contents.w kit_metadata.json Sections Roots.w ``` The ```.interb``` filename endings mean "Inter binary code", and there's one for each architecture. Something else happened on that first run: the `extension_metadata.json` file for the wrapper extension was quietly rewritten. It now includes a _dependency_ of the extension on the kit: ``` code { "is": { "type": "extension", "title": "Roots of Equations", "author": "Peter Drake", "version": "1" }, "needs": [ { "need": { "type": "kit", "title": "RootsOfEquationsKit" } } ] } ``` This tracking goes on automatically and authors can usually just let it happen all by itself, but if we decided against the kit after all and removed it from the extension, then this dependency would have to be removed from `extension_metadata.json` before the extension would work again. The full set of features of ```inweb``` is extensive and this is not the place to go into that. In brief, though, kit section files like ```Roots.w``` can't use any of the interesting tangling features (such as ```@d```, or ```@< ... >@```); but they can use all the weaving features. Inform users don't need to have ```inweb``` in order to write or use kits, and don't need to understand what the last sentence said. ## Compatibility of kits Since kits are mostly used to provide low-level support functions, they often need to work slightly differently on Glulx versus the Z-machine, or as we should really say, on the 32-bit versus the 16-bit architecture. ### A one-architecture kit Suppose ```RootsOfEquationsKit``` can only be compiled for 32-bit architectures, which is not at all improbable if it wants to perform floating-point maths. It can be marked as such by editing its `kit_metadata.json` file as follows: ``` code { "is": { "type": "kit", "title": "RootsOfEquationsKit" }, "compatibility": "for 32-bit only" } ``` When Inform builds the kit, it compiles only the `arch-32.interb` and `arch-32d.interb` binaries. So what happens if the `Roots of Equations` extension is then compiled in a project with the Z-machine setting, i.e., to a 16-bit story file? It will then be impossible for Inform to link in the `arch-16.interb` binary for ```RootsOfEquationsKit```, because there isn't one. Inform does not halt with a problem message: instead it simply carries on. The likely result is that linking errors will be produced with certain functions not being found. This can be made be more graceful, of course, by simply declaring the _extension_ in a restricted way: Version 1 of Roots of Equations (for 32-bit only) by Peter Drake begins here. That way, any user trying to use the extension on the Z-machine will be told at once what the issue is, and no linking errors will ever be reached. ### Two alternative kits Suppose, on the other hand, we are more ambitious and want `Roots of Equations` to run on all architectures, even though the 16-bit and 32-bit implementations are completely different. The trick then is to equip `Roots of Equations` with _two_ kits. One will be called `RootsOfEquations16Kit`, with this metadata: ``` code { "is": { "type": "kit", "title": "RootsOfEquations16Kit" }, "compatibility": "for 16-bit only" } ``` and the other will be `RootsOfEquations32Kit`, with a similar set of metadata. The practical effect is that in any build including `Roots of Equations`, exactly one of `RootsOfEquations16Kit` and `RootsOfEquations32Kit` will be included. ### Conditional compilation If in fact most of ```RootsOfEquationsKit``` should be the same on all architectures, but just one function would differ, conditional compilation can be used. This means using more or less the same ```#if...``` directives as would be used in Inform 6, but in I6 there are significant restrictions: - ```#ifdef``` and ```#ifndef``` can be used only on certain symbols: - ```TARGET_ZCODE``` and ```TARGET_GLULX``` are defined only on 16-bit and only on 32-bit architectures, respectively. Their names are now a little misleading, but see below. - ```DEBUG``` is defined only on the debugging architectures `16d` and `32d`. What this means in practice is that ```DEBUG``` is defined when using Inform in the apps, but not usually defined when making a release compilation. - Otherwise, they can only be used on symbols defined (or not defined) higher up _in the same kit_. Because each kit is built independently of all others, I6 directives in one kit cannot know what symbols exist or do not exist in other kits. - ```#iftrue``` and ```#iffalse``` can only be used on "fundamental constants", and then only to test them for equality against constant values. For example, ```#iftrue CHARSIZE == 1;``` is legal. We now usually prefer to write `#Iftrue (WORDSIZE == 2);` rather than the more traditional `#ifdef TARGET_ZCODE`, and similarly `#Iftrue (WORDSIZE == 4);` rather than `#ifdef TARGET_GLULX`. These more clearly express the idea of being on a 16-bit or 32-bit architecture, respectively. Here, for reference, are all of the fundamental constants except ```DEBUG``` (for which see above), and their normal values: Symbol | 16-bit architectures | 32-bit architectures ------------------------- | -------------------- | -------------------- ```CHARSIZE``` | 1 | 4 ```WORDSIZE``` | 2 | 4 ```NULL``` | $ffff | $ffffffff ```WORD_HIGHBIT``` | $8000 | $80000000 ```WORD_NEXTTOHIGHBIT``` | $4000 | $40000000 ```IMPROBABLE_VALUE``` | $7fe3 | $deadce11 ```MAX_POSITIVE_NUMBER``` | 32767 | 2147483647 ```MIN_NEGATIVE_NUMBER``` | -32768 | -2147483648 ```TARGET_ZCODE``` | 1 | _undefined_ ```TARGET_GLULX``` | _undefined_ | 1 So, for example, this function is compiled very slightly differently according to whether ```DEBUG``` is in force or not: ``` code [ ReleaseLine i; print "Release ", VM_ReleaseNumber(), " / Serial number "; serial = VM_SerialNumber(); for (i=0 : i<6 : i++) print (char) serial->i; print " / Inform 7 v", (PrintI6Text) I7_VERSION_NUMBER; #Ifdef DEBUG; print " / D"; #Endif; ! DEBUG new_line; ]; ``` ## Run-time representations of Inform constructs Functions in kits frequently receive values passed to them from Inform source text. Some of those values are straightforward to deal with: a `number` value in source text behaves exactly as integers do in I6, for example. But others are not so easy to understand. If Inform passes an I6 function a `text`, or a `rule`, for example, what are we getting, and how can we deal with it? ### Text constants Values of the Inform kind `text` are _not_ the same as text constants in the I6 sense. This function may look plausible, but it does not return a valid Inform `text`: ``` code [ RedOrBlue N; if (N % 2 == 0) return "Red"; return "Blue"; ]; ``` This, however, does: ``` code Array RED_TEXT --> PACKED_TEXT_STORAGE "Red"; Array BLUE_TEXT --> PACKED_TEXT_STORAGE "Blue"; [ RedOrBlue N; if (N % 2 == 0) return RED_TEXT; return BLUE_TEXT; ]; ``` ```BasicInformKit``` already defines ```EMPTY_TEXT_VALUE```, which is a valid constant `text` holding no characters. These arrays are because `text` values are actually pointers to two-word blocks of memory, in which the first word defines one of a number of possible representations of the text, and the second gives details. See the source code for ```BasicInformKit``` for the gory details. ### List constants, stored action constants, and more While it is possible to write similar array declarations to simulate constant lists, this is not recommended; their run-time representation may change in future. Similarly for other complex kinds: it is better to find a way to define constant values of those kinds in Inform source text (for example in an extension) and then pass those values down to the kit code for usage. ### Variables ^^{defined by Inter as...+assert+: variables} ^^{Inter code: defined by Inter as...+assert+} ^^{variables: defining in I6} We can create a valid Inform variable by providing an I6 global variable to store the contents. (Not all Inform variables are stored this way: some are stored in array entries, or on a stack. Those other ways, we cannot imitate.) The extension which wraps the kit will need to define a name: The bounty on Spade is a number that varies. The bounty on Spade variable is defined by Inter as "Spade_bounty". In effect, this makes a promise, and the kit has to keep the promise, which it can do very easily: ``` code Global Spade_bounty = 0; ``` Note that the kit has the responsibility of seeing that the value in this variable is always valid for the kind it is supposed to have — but in this case, that's `number`, which is easy enough. ### Rules and responses ^^{defined by Inter as...+assert+: rules} ^^{rules: defining in I6} At run-time, a rule is represented by a function which must do one of three things: - return ```false``` to make no decision; - call ```RulebookSucceeds()``` and then return ```true``` to succeed; or - call ```RulebookFails()``` and then return ```true``` to fail. If the rule is for a rulebook which produces a value then it must pass the outcome value as a parameter if it succeeds: - call ```RulebookSucceeds(V)``` and then return ```true``` to succeed with value `V`. We can create a rule from a kit by writing such a function, and by giving it a name, and perhaps filing it in a rulebook, in the extension which wraps the kit: The blossom rule is defined by Inter as "BLOSSOM_R". The blossom rule is listed in the horticulture rules. The rule function can then go into the kit: ``` code [ BLOSSOM_R; if (real_location hasnt light) { RulebookSucceeds(); rtrue; } rfalse; ]; ``` And now `blossom rule` is a value of the kind `rule` in Inform source text, while ```BLOSSOM_R``` can validly refer to it from I6 code and, in particular, elsewhere in the kit. If the rule is going to print anything, it should ideally do so using Inform's system of responses. These responses must be defined in the wrapper extension: The blossom rule is defined by Inter as "BLOSSOM_R" with "The garden is in blossom." (A), "The garden is gloomily barren." (B). What then happens is that the Inform compiler creates a function ```BLOSSOM_RM``` (i.e., with the same name as the rule but with ```M``` appended) which can print a response on demand: ``` code [ BLOSSOM_R; if (real_location hasnt light) { BLOSSOM_RM('A'); RulebookSucceeds(); rtrue; } BLOSSOM_RM('B'); rfalse; ]; ``` If the rule is to be used in a rulebook based on a value, or more often an action, then it will need to be able to access that so-called "basis". - For action-based rules, it should look at the I6 global variables ```actor```, ```noun``` and ```second```. - For value-based rules, it should look at the I6 global variable ```parameter_object```, which despite its name is not necessarily an object: it will be a value of whatever kind the rulebook is based on. ### Rulebooks A rulebook is, like a rule, a function, and it has the same calling conventions. (In fact, a `rulebook` value is always a valid `rule` value at run-time.) Rulebooks can only be created by Inform source text: so if a kit needs a rulebook, it should be created in the wrapper extension. ### Objects and kinds of object At runtime, an Inform object is represented by a value ```ofclass Object``` in the I6 sense, and the absence of an object is represented by the I6 constant ```nothing```. A kind of object is represented by a value ```ofclass Class```. However, not every value ```ofclass Object``` is valid as an `object` in Inform. ```WorldModelKit``` continues, for historical reasons, to define two pseudo-object values ```thedark``` and ```compass```: these are ```ofclass Object``` in I6, but must not be stored in `object` variables in Inform. Objects and kinds of object can only be created by Inform source text: so if a kit needs these, they should be created in the wrapper extension. I6 code like this: ``` code Object oddity "an oddity"; ``` simply creates another pseudo-object like ```thedark```, which is not an `object` in the Inform 7 sense. ### Properties Although it is possible for kits to define Inform properties, this is no longer recommended. It's better to define them in the wrapper extension, and then simply make their names available to the kit code using `accessible to Inter as`. See [Inform values from I6]. ### Actions Values of the kind `action`, such as `taking action` or `looking`, are represented in the natural way as I6 action values. Kits can create their own actions, and also give them the equivalent of `Understand` grammar. For example, ```WorldModelKit``` provides a handful of debugging commands this way: ``` code Verb meta 'showheap' * -> ShowHeap; ``` This creates an action out of world called ```##ShowHeap```. ```WorldModelKit``` then provides a function called ```ShowHeapSub``` to implement the action. None of this is visible at the Inform 7 level. While kits _can_ do this, they probably shouldn't. It's better to define actions in the wrapper extension. I6 also has a concept of "fake actions". Inform 7 does not, and kits should create no further fake actions. ### Command grammar tokens ^^{defined by Inter as...+assert+: grammar tokens} ^^{grammar tokens: defining in I6} `Understand` tokens of command grammar are represented as functions which are, in the traditional Inform 6 sense, "general parsing routines" or GPRs. (Consult the DM4 for details.) To create one with a kit, the wrapper extension should give it a name: The Understand token squiggle is defined by Inter as "SQUIGGLE_TOKEN". The kit should then define the necessary function: ``` code [ SQUIGGLE_TOKEN; if (NextWordStopped() == '$$') return GPR_PREPOSITION; return GPR_FAIL; ]; ``` ## Assigning use options to kits Suppose we want to provide use options which affect the operation of ```AmphibianKit```. We have already seen ways to create such options: Use drifting lilypads translates as the configuration flag DRIFTING_LILYPADS. Use horny skin translates as the configuration value SKIN_TYPE = 1. Use scaly skin translates as the configuration value SKIN_TYPE = 2. Use frog count of at least 10 translates as the configuration value FROG_COUNT. Use maximum jump height of 6 translates as the configuration value JUMP_HEIGHT. But these simply define the names ```DRIFTING_LILYPADS```, ```SKIN_TYPE``` and so on, without assigning them to any kit. So instead we tack ```in AmphibianKit``` onto the end of each declaration: Use drifting lilypads translates as the configuration flag DRIFTING_LILYPADS in AmphibianKit. Use horny skin translates as the configuration value SKIN_TYPE = 1 in AmphibianKit. Use scaly skin translates as the configuration value SKIN_TYPE = 2 in AmphibianKit. Use frog count of at least 10 translates as the configuration value FROG_COUNT in AmphibianKit. Use maximum jump height of 6 translates as the configuration value JUMP_HEIGHT in AmphibianKit. When a configuration flag or value is tied to a kit, two things are different: * The constant name is moved into that kit's namespace, so, for example, we have ```AmphibianKit`DRIFTING_LILYPADS``` not ```DRIFTING_LILYPADS```. * As a result, if two different kits both have a configuration value called, say, ```MAX_CAPACITY```, both can be used without a conflict occurring, because one will be ```FirstKit`MAX_CAPACITY_CFGV``` and the other ```SecondKit`MAX_CAPACITY_CFGV```. * A problem message is thrown if the name is not one of those listed in the kit's metadata as being expected. As this last caveat implies, the ```kit_metadata.json``` file for ```AmphibianKit``` needs to be prepared to receive these options, like so: ``` code { "is": { "type": "kit", "title": "AmphibianKit" }, "kit-details": { "configuration-flags": [ "DRIFTING_LILYPADS" ], "configuration-values": [ "SKIN_TYPE", "FROG_COUNT", "JUMP_HEIGHT" ] } } ``` and then the above declarations would all work, but Use mayflies translates as the configuration flag MAYFLIES_AVAILABLE in AmphibianKit. would be rejected because ```AmphibianKit``` does not support ```MAYFLIES_AVAILABLE```. Similarly, it's an error to use as a value what the kit declares as a flag (unless the value being stored is either 0 or 1). This raises the question of what happens if the JSON metadata asks for a configuration flag or value which no use option talks about. The answer is that Inform silently creates this, with the value 0, so that no link failure can occur. For example, if we had had ``` code "configuration-values": [ "SKIN_TYPE", "FROG_COUNT", "JUMP_HEIGHT", "SECRET_POND" ] ``` then whenever Inform compiled a project with ```AmphibianKit``` it would define the constant ```AmphibianKit`SECRET_POND_CFGV``` to 0. Should a knowledgeable user come along and write Use secret pond of 10 translates to configuration value SECRET_POND in AmphibianKit. Use secret pond of 7. ...this would then take effect. Because it is not safe to use ```#ifdef```, ```#ifndef```, ```#iftrue``` or ```#iffalse``` on symbol names linked in from outside of a kit, Inform automatically throws an error on any attempt to use these directives with kit-linked configuration flags or values. Thus, for example, in a kit: ``` code #ifdef AmphibianKit`DRIFTING_LILYPADS_CFGF; ... #endif ``` would throw a problem message. Instead, the idea is to use the value, not the existence, of these symbols in the kit: ``` code if (AmphibianKit`DRIFTING_LILYPADS_CFGF) { .... } ``` Note that there's no prohibition on one kit being able to see the configuration values of another: for example, ```WorldModelKit``` can test ```if (BasicInformKit`AMERICAN_DIALECT_CFGF)```. The following table, for what it is worth, shows how the main use options belonging to ```BasicInformKit```, ```WorldModelKit``` and ```CommandParserKit``` are set: Use option | Now sets --------------------------------- | -------------------------------- no deprecated features | ```BasicInformKit`NO_DEPRECATED_CFGF``` dynamic memory allocation | ```BasicInformKit`STACK_FRAME_CAPACITY_CFGV``` maximum text length | ```BasicInformKit`TEXT_BUFFER_SIZE_CFGV``` maximum things understood at once | ```BasicInformKit`MULTI_OBJ_LIST_SIZE_CFGV``` authorial modesty | ```BasicInformKit`AUTHORIAL_MODESTY_CFGF``` numbered rules | ```BasicInformKit`NUMBERED_RULES_CFGF``` predictable randomisation | ```BasicInformKit`FIX_RNG_CFGF``` command line echoing | ```BasicInformKit`ECHO_COMMANDS_CFGF``` memory economy | ```BasicInformKit`MEMORY_ECONOMY_CFGF``` printed engineering notation | ```BasicInformKit`PRINT_ENGINEER_EXPS_CFGF``` American dialect | ```BasicInformKit`AMERICAN_DIALECT_CFGF``` serial comma | ```WorldModelKit`SERIAL_COMMA_CFGF``` no scoring | ```WorldModelKit`SCORING_CFGV``` = 0 scoring | ```WorldModelKit`SCORING_CFGV``` = 1 default route-finding | ```WorldModelKit`ROUTE_FINDING_CFGV``` = 0 fast route-finding | ```WorldModelKit`ROUTE_FINDING_CFGV``` = 1 slow route-finding | ```WorldModelKit`ROUTE_FINDING_CFGV``` = 2 full-length room descriptions | ```WorldModelKit`ROOM_DESC_DETAIL_CFGV``` = 2 abbreviated room descriptions | ```WorldModelKit`ROOM_DESC_DETAIL_CFGV``` = 3 VERBOSE room descriptions | ```WorldModelKit`ROOM_DESC_DETAIL_CFGV``` = 2 BRIEF room descriptions | ```WorldModelKit`ROOM_DESC_DETAIL_CFGV``` = 1 SUPERBRIEF room descriptions | ```WorldModelKit`ROOM_DESC_DETAIL_CFGV``` = 3 undo prevention | ```CommandParserKit`UNDO_PREVENTION_CFGF``` manual pronouns | ```CommandParserKit`MANUAL_PRONOUNS_CFGF``` unabbreviated object names | ```CommandParserKit`UNABBREVIATED_NAMES_CFGF``` ## Controlling how kits are linked Towards the end of building an Inform project, any kits needed by its extensions are _linked_ into it. (They may need to be built first.) Because certain extensions are automatically present in projects, certain kits are always part of the linking. Specifically: Kit | Belongs to | Included when ------------------------ | ------------------ | ------------- ```BasicInformKit``` | `Basic Inform` | Always ```Architecture16Kit``` | `Basic Inform` | If building for 16-bit architectures ```Architecture32Kit``` | `Basic Inform` | If building for 32-bit architectures ```WorldModelKit``` | `Standard Rules` | All non-basic projects ```CommandParserKit``` | `Standard Rules` | All non-basic projects ```DialogueKit``` | `Standard Rules` | Projects using dialogue features ```EnglishLanguageKit``` | `English Language` | All projects communicating in English So it is safe to say that our kit will not be the only one in the project, and besides the kits, of course, there is also the "trunk" of Inter code coming from compilation of the source text. ### Private and public names How do kits interact? For the most part, one kit can refer to functions, arrays and variables in another just by name. For example, ```RootsOfEquationsKit``` can call ```SquareRoot``` from ```BasicInformKit``` just as if it were one of its own functions. This is because ```SquareRoot``` is a _public_ function of ```BasicInformKit```. "Public" names are the ones which are visible to other kits. By default, all names are public. But this has a down side. We might want a tricky bit of memory manipulation to happen exactly right, and so would not want to let anybody else call a particularly delicate function from out of context. Or we might want just to hide names which aren't important, in order to avoid name-clashes. At present, if two kits both define a public function called ```SquareRoot```, and both are linked into a project, an error will halt linking. So perhaps kits ought to make only a limited and carefully chosen set of names public, and make the rest _private_. Here's how to make a private function: ``` code +private [ MyFunction; "Only I can use this."; ]; ``` Note the _annotation_ ```+private```. This is an I6 syntax allowed only in kits, and is not strictly speaking part of the Inform 6 language. The practical result is that other code in ```RootsOfEquationsKit``` can call ```MyFunction()```, but other kits cannot. Indeed, another kit could have its own function also called ```MyFunction```, without any clash of names occurring. To prevent confusion, Inform throws a problem message if these markers are used redundantly - for example, if a function is marked ```+public``` in a context where it would have been public anyway. ### Namespaces All code in a kit is considered as belonging to some _namespace_. Where none is declared, this will be ```main```, the global namespace. The annotation: ``` code +namespace(SomeName); ``` which must occur on its own (note the semicolon ```;``` rather than any directive following on from it) declares that the directives which follow all belong to the namespace ```SomeName``` This continues to the end of the kit, or to the next ```+namespace``` marker, whichever comes first. Within a namespace, all identifiers are implicitly prefixed with the namespace name and a backtick (except for `main`, where identifiers are as written). Thus: ``` code +namespace(Secret); [ Function x; ... ]; Constant z = 2; +namespace(main); Constant z = 1; ``` creates the identifiers ```Secret`Function```, ```Secret`z```, and ```z```. The two definitions of what looks like ```z``` are therefore not contradictory, because they define two different things. Within a namespace other than ```main```, writing an unqualified identifier will implicitly mean "the definition in this namespace if there is one, and the definition in ```main``` if not". For example: ``` code +namespace(Secret); [ Example; Hello(z); ! Calls Hello in the namespace Secret with argument 2 main`Example(); ! Calls Example in the namespace main ]; Constant z = 2; [ Hello x; print "Hello to ", x, ".^"; ]; +namespace(main); Constant z = 7; [ Example; Secret`Hello(z); ! Calls Hello in the namespace Secret with argument 7 Hello(13); ! An error: there is no Hello in the namespace main ]; ``` Namespaces cannot be nested and can be reopened at any point. If two different kits both use a namespace called ```SoundEffects```, then it's the same namespace. Optionally, ```+namespace``` can specify a default access. For example: ``` code +namespace(Secret, access private); ``` puts us in namespace ```Secret```, and says that until the next namespace marker, all definitions are by default private, as if they were all marked ```+private```. Similarly for ```access public```, though that is the default. Note that it's fine to write something like: ``` code +namespace(main, access public); [ MyAPIFunction; MyImplementation(1745); ]; +namespace(main, access private); [ MyImplementation undocumented_number; ... ]; ``` thus dividing a kit into a public half and a private half, but keeping all of the names in the default ```main``` namespace. The namespace ```replaced``` is reserved for the linker's own use, and attempting to create anything in it will throw an error. ### Replacing public definitions from other kits When the linker joins blocks of Inter code together, it looks for clashes between names. A clash can only occur if both names are the same, are in the same namespace, and are both public. Even then, if exactly one of these definitions was annotated ```+replacing``` then there is no clash: the replacing definition wins. So, for example, if ```SomeNewKit``` includes: ``` code +replacing [ SquareRoot num; "Nobody cares about square roots, son."; ]; ``` then both it and ```BasicInformKit``` define functions of the same name: but this definition wins, because it is marked ```+replacing```. And the practical effect is that ```SomeNewKit``` can therefore replace any public function it likes from ```BasicInformKit```, or ```WorldModelKit```. ```+replacing``` means "let this definition triumph over any other". If the linker finds two definitions both marked as ```+replacing``` in this way, there's once again an error message, since they can't both win. Optionally, the annotation can be more specific: ``` code +replacing(from BasicInformKit) [ SquareRoot num; ... ]; ``` allows this definition to replace the one in ```BasicInformKit```, but continue to throw a linking error if an unexpected rival appears from elsewhere. Replacement is a more slippery idea than it first seems. Some things to bear in mind: * If no clash ever occurs, no error is produced. The ```+replacing``` definition may not in fact have replaced anything, but it's still the valid one. So it's possible to mark a definition as ```+replacing``` which would overlap a definition in some other kit which might or might not be being used. * It is not possible to use ```+replacing``` to override a ```+private``` definition in another kit. Private names really are private. * By default, the replaced definition is simply thrown away, but if ```+replacing(keeping)``` is used instead then the discarded definition is kept alongside the new one. It clearly cannot have the same name as before, so it is moved into the namespace ```replaced```. For example, this effectively says "double the value of ```REQUISITION_STACK_SIZE```, whatever that is": ``` code +replacing(keeping) Constant REQUISITION_STACK_SIZE = (2 * replaced`REQUISITION_STACK_SIZE); ``` Whereas this would produce an error: ``` code +replacing Constant REQUISITION_STACK_SIZE = (2 * replaced`REQUISITION_STACK_SIZE); ``` since then ```replaced`REQUISITION_STACK_SIZE``` would not exist: the old definition would have been destroyed, and so could not have been used. Or for another example, the following "corrects" the output of the existing definition of ```SquareRoot``` from ```BasicInformKit``` by rounding up to the nearest natural number, rather than down: ``` code +replacing(keeping) [ SquareRoot num x; x = replaced`SquareRoot(num); if (x*x < num) x++; return x; ]; ``` so that `the square root of 17` will then evaluate to 5, not 4. Note that ```+replacing(keeping)``` can only be applied to global variables (```Global ...```), constants, arrays and functions: a problem message will be thrown for attempts to use it with any other constructs. ## Neptune and enumerative kinds Inform already provides a range of ways to create new kinds of object, and new kinds of value in general, using source text alone. If a kit simply needs, say, a concept of "bottle", then its wrapper extension can include something like this: A bottle is a kind of container. A bottle is usually openable. A bottle is usually transparent. The bottle kind is accessible to Inter as "K_bottle". And then code in the kit can do this sort of thing: ``` code if (obj ofclass K_bottle) ... ``` But certain kinds cannot be made in source text. For example, no source text defines `time`, or the `list of K` kind (or properly speaking, kind constructor, since it is a way of making a new kind out of an old one). All kinds which are _not_ defined in source text are defined in _Neptune files_. Neptune is a simple mini-language whose sole task is to define kinds for Inform. It's named for the fountain in the Place Neptune in Carcassonne, not the gas giant. We'll first use this mini-language to define an enumerative kind of value with values which are not 1, 2, 3, ... A kit can only use Neptune files if its JSON metadata says so. So we'll amend ```kit_metadata.json``` to: ``` code { "is": { "type": "kit", "title": "InternationalTelephonyKit" }, "kit-details": { "provides-kinds": [ "CountryCodes.neptune" ] } } ``` This simply says that it provides a Neptune file to declare one or more kinds. We will follow through on that by giving the kit a ```kinds``` directory, inside which we put ```CountryCodes.neptune```: ``` code InternationalTelephonyKit Contents.w kinds CountryCodes.neptune kit_metadata.json Sections Dialling Codes.w ``` And this will be our Neptune file ```CountryCodes.neptune```: ``` code new base COUNTRY_CODE_TY { conforms-to: ENUMERATED_VALUE_TY singular: country code plural: country codes instance: Saint Helena code = ST_HELENA_CC = 290 instance: New Caledonia code = NEW_CALEDONIA_CC = 687 instance: Montserrat code = MONTSERRAT_CC = 1664 instance: Svalbard code = SVALBARD_CC = 4779 } ``` When this kit is linked into a project, any source text in that project can now use the kind `country code`. So for example, this rule: When play begins: showme the Saint Helena code; showme the list of country codes; showme a random country code; showme the number of country codes. produces the text: ``` transcript country code: Saint Helena code "list of country codes" = list of country codes: {Saint Helena code, New Caledonia code, Montserrat code, Svalbard code} "a random country code" = country code: New Caledonia code "number of country codes" = number: 4 ``` On the face of it, that's not so interesting. We could just as easily have written: Country code is a kind of value. The country codes are Saint Helena code, New Caledonia code, Montserrat code and Svalbard code. But if we had done _that_, then the values representing these codes at runtime would be 1, 2, 3 and 4; instead of which, they are 290, 687, 1664 and 4779. For example, suppose we define: To dial (code - country code): (- Dialup({code}); -). and then provide the necessary ```Dialup``` function in ```InternationalTelephonyKit```: ``` code [ Dialup code; print "You dial ", code, "^"; if (code == SVALBARD_CC) print "The phone does feel a little chilly.^"; ]; ``` The result of the phrase `dial Svalbard code` is then to print: ``` transcript You dial 4779 The phone does feel a little chilly. ``` As this example function suggests, the constants ```ST_HELENA_CC```, ```NEW_CALEDONIA_CC```, ```MONTSERRAT_CC```, and ```SVALBARD_CC``` are all now accessible to code in the kit. To get back to the Neptune file syntax, let's unpick what is going on. The basic shape of our file was like so: ``` code new base COUNTRY_CODE_TY { ... } ``` It consisted of a single declaration, with all the details being inside the braces ```{``` and ```}```. The four main declarations are: * ```new base```. Makes a new base kind, on a par with `time` or `number`. * ```new constructor```. Makes a new constructor for kinds, on a par with `list of K` or `relation of K to L`. * ```builtin base```. Supplies details about a base kind which the compiler is expecting to be defined, like `time` or `number`. * ```builtin constructor```. Supplies details about a constructor for kinds which the compiler is expecting to be defined, like `time` or `number`. And for creating kinds which are not normally supplied with Inform, then, ```new base``` and ```new constructor``` are the ones which matter. `country code` is going to be a new base kind. Next after ```new base``` was the name ```COUNTRY_CODE_TY```. This is a defined constant accessible to I6, and its value is used inside kit-level code as the "kind ID" representing what kind this is. For example, the function call ```DefaultValueOfKOV(COUNTRY_CODE_TY)``` returns 290, the dialling code for the island of Saint Helena, and ```PrintKindValuePair(COUNTRY_CODE_TY, MONTSERRAT_CC)``` prints ``Montserrat``. By convention all kind IDs have names in ```ALL_CAPITALS_WITH_UNDERSCORES``` and ending in ```_TY```. This goes so far back into the early days of Inform that the letters "TY" here were short for "type", which we would now call "kind". Inside the braces, then, the Neptune file specifies some details about this new base kind `country code`, and begins like this: ``` code conforms-to: ENUMERATED_VALUE_TY singular: country code plural: country codes ``` The ```singular``` and ```plural``` lines are easily explained: they are the source-text names for the kind. We know from the header line of the declaration that it is called ```COUNTRY_CODE_TY``` at the I6 end; at the Inform source text end, it is called `country code`. ```conforms-to``` tells Inform that this kind behaves in the way you would expect from the _protocol_ ```ENUMERATED_VALUE_TY```, which is the I6 way to write `enumerated value`. A kind can conform to many protocols — for example, all kinds automatically conform to `value`, a.k.a. ```VALUE_TY```. Saying that `country code` conforms to `enumerated value` means that, for example, it would be valid to supply a country code when using the phrase: To speculate about (N - an enumerated value): ... Being an enumerated value means that Inform allows us to count the instances with `number of...`, or repeat through them, and so on. But Inform would not allow us to add together two country codes: it would throw a problem message if the source text asked to do that. If, however, we added: ``` code conforms-to: ENUMERATED_VALUE_TY conforms-to: ARITHMETIC_VALUE_TY singular: country code plural: country codes ``` then Inform would now allow us to add together the Saint Helena code and the Montserrat code, making 290 + 1664 = 1954. That isn't one of our four possible values, so this would quickly lead to disaster. In any case, it really doesn't mean anything to add together two phone numbers, so it's easy to see why we want `country code` to conform to `enumerated value` but not `arithmetic value`. All base kinds should conform to one or more of the following: Source text name | I6-level name | What conforms to this ----------------------- | ------------------------ | --------------------- `value` | VALUE_TY | All kinds by definition _none_ | STORED_VALUE_TY | All kinds whose values can be stored in a variable or property `sayable value` | SAYABLE_VALUE_TY | All kinds whose values can sensibly be printed `understandable value` | UNDERSTANDABLE_VALUE_TY | All kinds whose values can be recognised in typed commands `arithmetic value` | ARITHMETIC_VALUE_TY | All kinds whose values can sensibly and safely be added, multiplied and so on `real arithmetic value` | REAL_ARITHMETIC_VALUE_TY | Ditto, but using real not integer arithmetic `enumerated value` | ENUMERATED_VALUE_TY | All kinds with a limited range _none_ | POINTER_VALUE_TY | All kinds with values represented by I6 pointers In practice, it's not necessary to give much of a list, though, because: * Saying that a kind conforms to ```REAL_ARITHMETIC_VALUE_TY``` automatically makes it conform to ```ARITHMETIC_VALUE_TY``` too. * Saying that a kind conforms to either ```ARITHMETIC_VALUE_TY``` or ```ENUMERATED_VALUE_TY``` automatically makes it conform to ```UNDERSTANDABLE_VALUE_TY``` too. * Saying that a kind conforms to ```UNDERSTANDABLE_VALUE_TY``` automatically makes it conform to ```SAYABLE_VALUE_TY``` too. * Saying that a kind conforms to ```SAYABLE_VALUE_TY``` automatically makes it conform to ```STORED_VALUE_TY``` too. * All kinds always conform to ```VALUE_TY```. So although we only declared `country code` as conforming to ```ENUMERATED_VALUE_TY```, we picked up conformance to ```UNDERSTANDABLE_VALUE_TY```, ```SAYABLE_VALUE_TY```, ```STORED_VALUE_TY``` and ```VALUE_TY``` automatically. That is quite enough about conformance. The rest of the declaration is simply a list of the _instances_ of this kind: i.e., of what those specific values are. ``` code instance: Saint Helena code = ST_HELENA_CC = 290 instance: New Caledonia code = NEW_CALEDONIA_CC = 687 instance: Montserrat code = MONTSERRAT_CC = 1664 instance: Svalbard code = SVALBARD_CC = 4779 ``` In an enumerated kind like this, at least one instance must be provided, and they must be given in strictly increasing value order. Values are actually optional. For example: ``` code instance: Fellowship of the Ring = FOTR_LOTR instance: Two Towers = TT_LOTR instance: Return of the King = ROTK_LOTR ``` would create a three-element enumeration with values 1, 2, 3. This: ``` code instance: cyan = CYAN_COL = 10 instance: blue = BLUE_COL instance: grey = GREY_COL = 20 instance: pink = PINK_COL ``` creates the values as 10, 11, 20, 21. Values can alternatively be given in Inform 6 hexadecimal or binary notation: ``` code instance: JSR instruction = JSR_6502 = $20 instance: RTS instruction = RTS_6502 = $60 instance: STA instruction = STA_6502 = $85 ``` Once enumerations are numbered other than in the obvious way 1, 2, 3, ..., it becomes convenient to have ways to distinguish their sequence position from their numerical value. So: > phrase: {ph_numericalvalue} numerical value of (V - enumerated value) ... number > > The value stored at run-time to represent `V`. For a typical enumeration, the first-created value of its kind is internally stored as the number 1, the second 2, and so on. But for some non-standard enumerations, this is not always true. > phrase: {ph_sequencenumber} sequence number of (V - enumerated value) ... number > > 1 if `V` is the first-created value of its kind, 2 if it is the second, and so on. For a typical enumeration, this the same thing as `numerical value of V`. But for some non-standard enumerations, this is not always true. For example, `numerical value of Svalbard code` is 4779, whereas `sequence number of Svalbard code` is 4. ## Neptune and arithmetic kinds For our next trick, we'll create a new kind of arithmetic value. This will be `memory address`, and will hold locations in the virtual machine memory map. We will need three ingredients: First, the kit has to include some supporting code for the kind. Here's a section file for the kit: ``` code Memory Address Support This section provides functions to support the kind "memory address". @ This function is used to say a value of memory address, which we do in hexadecimal, padding to the theoretical maximum width of addresses on the architecture. = [ MEMORY_ADDRESS_TY_Say N; print "$"; #iftrue (WORDSIZE == 2); PrintInBase(N, 16, 4); #ifnot; PrintInBase(N, 16, 8); #endif; ]; @ This dumps C bytes from address N onwards: = [ MEMORY_ADDRESS_TY_ShowBytes N C i; for (i=0: i 0) print " "; PrintInBase(N->i, 16, 2); } print " ~"; for (i=0: ii >= $20) && (N->i < $7f)) print (char) N->i; else print "?"; } print "~"; ]; @ And here we parse a word of the player's command to see if it could be an address in hexadecimal - up to 4 or 8 hex digits with a dollar sign in front. If it can't be that, we revert to trying the DECIMAL_TOKEN instead, which is what BasicInformKit uses to parse numbers in decimal. = [ MEMORY_ADDRESS_TY_Understand wa wl ch n digit; wa = WordAddress(wn); wl = WordLength(wn); #Iftrue CHARSIZE == 1; ch = wa->0; if (wl > 5) return DECIMAL_TOKEN(); #Ifnot; ch = wa-->0; if (wl > 9) return DECIMAL_TOKEN(); #Endif; ! CHARSIZE if (ch ~= '$') return DECIMAL_TOKEN(); wa = wa + CHARSIZE; wl--; n = 0; while (wl > 0) { #Iftrue CHARSIZE == 1; ch = wa->0; #Ifnot; ch = wa-->0; #Endif; ! CHARSIZE if (ch >= 'a') digit = ch - 'a' + 10; else if (ch >= 'A') digit = ch - 'A' + 10; else digit = ch - '0'; if (digit >= 0 && digit < 16) n = 16*n + digit; else return GPR_FAIL; wl--; wa = wa + CHARSIZE; } parsed_number = n; wn++; return GPR_NUMBER; ]; ``` Second, the wrapper extension should provide some convenient phrases: To decide which memory address is (N - number) in memory: (- {N} -). To decide which memory address is the address of the serial code: (- (VM_SerialNumber()) -). To say dump of (N - number) bytes at (address - memory address): (- MEMORY_ADDRESS_TY_Say({address}); print ": "; MEMORY_ADDRESS_TY_ShowBytes({address}, {N}); -); Because we don't want to get into difficulties with dimensional restrictions on arithmetic, which would not let us add numbers to addresses, we will imitate the (not always great) convention also used by the `time` kind, which is that a small number can represent both a time of day and also a duration in minutes. Here, `16 bytes` and `16 in memory` are both the same value under the hood. So: To decide which memory address is (N - number) byte/bytes: (- {N} -). Section on dumping (not for release) Dumping memory at is an action out of world applying to one memory address. Carry out dumping memory at: say dump of 32 bytes at the memory address understood; say line break. Understand "dump [memory address]" as dumping memory at. That just leaves the Neptune file needed to declare this kind. It starts very much like the declaration of `country code` above, but this time conforms to ```ARITHMETIC_VALUE_TY``` not ```ENUMERATED_VALUE_TY```. ``` code new base MEMORY_ADDRESS_TY { conforms-to: ARITHMETIC_VALUE_TY singular: memory address plural: memory addresses default-value: 0 can-exchange: yes compare-function: UnsignedCompare understand-function: MEMORY_ADDRESS_TY_Understand say-function: MEMORY_ADDRESS_TY_Say index-priority: 2 index-default-value: 0 specification-text: An address within the virtual machine the story runs in. } ``` As can be seen, though, it defines no instances — only enumerated kinds can do that — and instead sets many more details. Let's start with these settings, which affect how the kind is handled inside the Inform compiler: ``` code default-value: 0 can-exchange: yes ``` * ```default-value``` gives an I6 expression for the default value for the kind. Here, that will be the address 0. * ```can-exchange``` being ```yes``` means that values of this kind, if printed out by one story and then read in by another story entirely, would still have the same meaning. For example, that's true of `number` because all Inform stories use the same bits to represent the number 17, say. But it is not true of `action name`, because one story may have an action for `swimming`, say, and the other story not; and even if both of them have, they may number it differently. The default for ```can-exchange``` is very much ```no```, but we're saying ```yes``` here. An address means the same in all stories, even though the data stored at that address may be different in each of them. Next we have some settings for how values are handled at run-time: ``` code compare-function: UnsignedCompare understand-function: MEMORY_ADDRESS_TY_Understand say-function: MEMORY_ADDRESS_TY_Say ``` Taking these in turn: * ```compare-function``` is the name of a function ```f``` to compare two values of the kind, such that ```f(x, y)``` is 1 if ```x``` is greater than ```y```, 0 if they are equal, and -1 if ```x``` is less than ```y```. We want to compare memory addresses as unsigned numbers, so that addresses above the halfway point in the address space aren't misunderstood as negative numbers. The function ```UnsignedCompare``` is defined in ```BasicInformKit```, so we can just use that. (If we want regular signed comparison of numbers, the special value ```signed``` can also be used, which tells Inform not to make a function call but to use comparison operations on the virtual machine, which is a little faster.) * ```understand-function``` is the name of a function which can act as an `Understand` token for this kind: that is, it implements the grammar token `"[memory address]"`. This function has to comply with the calling conventions for general parsing routines (GPR) in the Inform 6 sense. ```MEMORY_ADDRESS_TY_Understand``` above is an example of that. * ```distinguish-function``` isn't specified for this kind, but it would be a function ```f``` such that ```f(x, y)``` is 1 if there is anything the player could type in a command which would distinguish the value ```x``` from ```y```. If ```understand-function``` is capable of understanding all possible values then the test performed by ```distinguish-function``` can just be to call the ```compare-function``` and return 1 if and only if it says that ```x``` and ```y``` are equal. * ```say-function``` is the name of a function to print a value of this kind. Finally, how the kind is presented in the Kinds part of the Index for a project which uses it: ``` code index-priority: 2 index-default-value: 0 specification-text: An address within the virtual machine the story runs in. ``` * ```index-priority``` controls how high up in the running order of the Index listing of kinds this comes. It really doesn't matter, but arithmetic kinds are usually given index priority 2. * ```index-default-value``` is just text: it's what the Index says the default value is. * ```specification-text``` is a brief verbal description. With all of this work in place, we can run, say: When play begins: let the header be 0 in memory; showme the header; showme the header plus 4 bytes; showme the address of the serial code; say "Looking inside, I see [dump of 64 bytes at the header]."; say "At the serial code, [dump of 6 bytes at the address of the serial code]."; On the Z-machine, that might produce something like this: ``` transcript "header" = memory address: $0000 "header plus 4 bytes" = memory address: $0004 "address of the serial code" = memory address: $0012 Looking inside, I see $0000: 08 9D 00 01 9F 38 9F 39 92 67 01 0A 1B 1A 8B 02 00 50 32 34 30 34 31 37 00 42 BC 04 A9 C4 03 5A 30 58 00 58 00 30 01 01 00 00 00 00 09 02 8B 01 00 00 01 01 00 00 01 02 00 00 00 00 36 2E 34 33 "?????8?9?g???????P240417?B?????Z0X?X?0??????????????????????6.43". At the serial code, $0012: 32 34 30 34 31 37 "240417". ``` And on Glulx, something broadly similar, but with different layout and longer addresses. ## Neptune and other base kinds ### Oddball kinds We have seen examples of new base kinds created which conform to ```ENUMERATED_VALUE_TY``` and ```ARITHMETIC_VALUE_TY```, but not everything does. If we have a kind which has a scatter of values, perhaps unlimited in extent, and where arithmetic makes no sense, then neither of these models would work. For example, `action name` is a kind which has a finite set of possible values, but those values are not predictable and can't exchange; and it makes no sense to add or subtract them. Such kinds should given one of the following conformances: - ```conforms-to: UNDERSTANDABLE_VALUE_TY``` if we can give them both a ```understand-function``` and a ```say-function```; - ```conforms-to: SAYABLE_VALUE_TY``` if we can give them a ```say-function``` but not a ```understand-function```; - ```conforms-to: STORED_VALUE_TY``` if not even that. For example, `action name`, which is defined by a Neptune file in ```WorldModelKit```, conforms to ```SAYABLE_VALUE_TY```. This is why action names can be said, but cannot be understood in players' commands. As it happens, `action name` is an example of a kind which, even though it doesn't conform to ```ENUMERATED_VALUE_TY```, _does_ have a finite range of values. We want Inform to be able to take advantage of this, because that means that `number of action names`, `list of action names` and so on can work. The Neptune file defining `action name` therefore contains this unlovely line: ``` code loop-domain-schema: for (*2=0,*1=ActionNumberIndexed(*2): *2*2: *2<=ArrayOfGadgetValues-->0: *2++,*1=ArrayOfGadgetValues-->*2) ``` would go through the values stored in an I6 table array like this one: ``` code Array ArrayOfGadgetValues --> 5 10 20 30 40 50; ``` But of course if the values were really so regular, then this would also do it: ``` code loop-domain-schema: for (*1 = 10: *1 <= 50: *1 = *1 + 10) ``` ### Kinds of object In general, Neptune cannot define kinds of object. But it does support one feature allowing those to be tweaked, though the feature is intentionally limited and should be used as little as possible. Suppose, for nefarious reasons of our own, we need to assign virtual machine attributes or properties — these do not quite correspond to Inform properties, but the concepts all overlap — to objects at run-time; but we don't want the Inform compiler to do this higher up, through assertions in the source text in the regular way. Inform used to have a crude feature which looked like this: Include (- has enterable supporter, with max_capacity 10, -) when defining a rideable animal. That is no longer allowed. All forms of `Include (- ... -)` are on the way out (kits are a better solution all round), but this one has already gone. But its functionality can be replicated by placing this declaration in a Neptune file in the kit in question: ``` code properties of rideable animal { attribute: enterable attribute: supporter property: max_capacity = 10 } ``` Note that the kind named must be a valid kind of `object` (though it can be one with no instances), and can give the name either in the singular or the plural. Inside this declaration, only the following are allowed: ``` code attribute: ATTRIBUTENAME attribute: ~ATTRIBUTENAME property: PROPERTYNAME property: PROPERTYNAME = NUMBER ``` The syntax ```~ATTRIBUTENAME``` means the attribute is set to ```false```, not ```true```; this is traditional Inform 6 notation. The short form ```property: PROPERTYNAME``` means ```property: PROPERTYNAME = 0```. ## Pointer-value kinds A _word_ is the quantity of memory needed to store one ```-->``` array entry: two bytes on 16-bit architectures (because 2 bytes times 8 bits per byte is 16 bits), four bytes on 32-bit architectures. This is also the amount of data stored in a local or global variable, and in a property. So it would be both tidy and efficient if every kind could fit all its possible values into a single word. And for some kinds, this is exactly what does happen: `time`, for example, fits easily in a word, and `number` fits exactly in a word. But there is simply more potential data in a `text`, say, or a `list of texts`, than can possibly squeeze into 16 or 32 bits. Data like that is stored instead as a _pointer_, that is, as an address in memory. Whether a value is stored as a single word or as a pointer depends entirely on the kind. If the kind is declared as ``` code conforms-to: POINTER_VALUE_TY ``` ...then all values of this kind are stored as pointers; and if not, all values of the kind are stored as words. Perhaps surprisingly, the values of all kinds of object are stored as single words, even though an object seems like a complicated mass of detail. Copying the value `brass samovar` (an instance of the kind `thing`, let's say) from one variable to another does not make a second samovar appear in the story. It simply means that both variables contain an ID number identifying which object is meant, and that both mean the one and only samovar. These ID numbers fit comfortably into a word. So ```OBJECT_TY``` does not conform to ```POINTER_VALUE_TY```. ### The weak kind ID determines whether a kind uses pointer values Kinds also have IDs: in fact, two sorts of ID, a _weak kind ID_ and a _strong kind ID_. We'll only need to work with weak kind IDs here. Several have appeared already: the weak kind ID of `number` is ```NUMBER_TY```, and so on. All of the constants ending ```_TY``` mentioned in Neptune files are in fact weak IDs. What makes them weak is that they cannot always tell different kinds apart. For example, `room`, `thing` and `vehicle`, along with all other kinds of object, all have weak ID ```OBJECT_TY```. And `list of numbers`, `list of texts` and `list of lists of lists of times`, for example, all have weak ID ```LIST_OF_TY```. Strong kind IDs, by contrast, do distinguish these, which is what makes them strong. But weak kind IDs are nevertheless useful because the I6 code needed to handle values of a given kind generally depends only on its weak ID. All lists have weak ID ```LIST_OF_TY```, but then all lists are created, copied and destroyed by the same functions. In this section we will go through how pointer values are stored in memory, and lay out a set of functions from ```BasicInformKit``` which other kits can use when dealing with pointer values. > --- > > ```KindConformsTo_POINTER_VALUE_TY(weak_kind_ID)``` > > Returns ```true``` if ```weak_kind_ID``` refers to a kind with pointer values, and ```false``` otherwise. Thus ```KindConformsTo_POINTER_VALUE_TY(NUMBER_TY)``` is false, but ```KindConformsTo_POINTER_VALUE_TY(TEXT_TY)``` is true. > > --- > > ```WeakKindOfPV(pv)``` > > Can only be called on a valid (i.e., created and not yet destroyed) pointer value: returns its weak kind ID. > > --- ### Pointer values can be passed by reference We have already seen that these two potential phrase definitions are subtly different: To decide what number is the number of entries in (L - a list of values): (- LIST_OF_TY_GetLength({L}) -). To decide what number is the number of entries in (L - a list of values): (- LIST_OF_TY_GetLength({-by-reference:L}) -). In the first, ```LIST_OF_TY_GetLength``` is given a duplicate of `L`; in the second, it is passed `L` itself. Copying takes memory and time, so it should only be done when necessary. Here there's no need to duplicate, because the length is the same either way. So although both definitions work, the second is faster. In this case, though, _only_ the second potential definition works: To sort (L - a list of values) (- LIST_OF_TY_Sort({L}, SORT_ASCENDING); -). To sort (L - a list of values) (- LIST_OF_TY_Sort({-lvalue-by-reference:L}, SORT_ASCENDING); -). The issue here is that the first phrase duplicates the list, sorts the duplicate, and then throws it away as no longer needed. The second phrase sorts the original list, which is what we wanted to happen. In Inform, only pointer values can be passed by reference. It's not possible to pass a reference to the number 20, say: you can only pass 20. There can be no pointers to local or global variables, because these do not exist in the memory map. Moreover, once a pointer value has passed down into I6 code, all further function calls are always by reference. If ```LIST_OF_TY_Sort``` receives a list value ```L``` and then passes it on to some other function, it is only passing a reference (i.e., pointer) to the data, not the data itself. ### Pointer values usually store data in fields Suppose, then, that the source text does this: let L be { 4, 2, 71 }; sort L; so that the function call ```LIST_OF_TY_Sort(L)``` is performed. Now we're down at the I6 level, inside some kit. What can we do with ```L```? ```L``` is the address in memory of a small ```-->``` array called the _short block_. These are truthfully named, usually having only 1 or 2 entries. In most cases, one of those entries is a further address, of a larger ```-->``` array called the _long block_. The exact configuration differs from kind to kind. For a `stored action`, for example, the short block has size 1, and contains only a pointer to the long block, which holds exactly 6 entries, called _fields_. For a `list of numbers`, on the other hand, the long block may need to be much larger, and may shrink or grow. ```BasicInformKit``` handles all of that automatically. In some kinds, fields are single bytes, and in others words. > --- > > ```PVFieldCapacity(pv)``` > > Returns the number of fields of data in the long block of the PV. This is always positive. It may be larger than expected, because the memory manager tends to allocate memory up to powers of 2 in size. > > If this PV has no long block, then the capacity is 0. > > --- > > ```SetPVFieldCapacity(pv, new_capacity)``` > > Resizes the PV so that it can now hold at least ```new_capacity``` fields. This must be a positive number. This can contract as well as expand PVs. Note that this does not properly destroy any data which might have been trimmed off: it is the caller's responsibility to see that that is done before calling. After this call, ```PVFieldCapacity(pv)``` will be at least ```new_capacity```, but may be a little greater, for the same reason mentioned above. > > If this PV has no long block, then the capacity cannot be set and remains 0. > > --- > > ```PVField(pv, field)``` > > Returns the current contents of the entry numbered ```field``` in the long block. If the PV has field capacity C, then fields are numbered 0 to C-1, so that ```PVField(pv, 0)``` is the first field. Calling this function with a ```field``` value out of range triggers an error. > > --- > > ```WritePVField(pv, field, value)``` > > Writes ```value``` to the entry numbered ```field``` in the long block. If the PV has field capacity C, then fields are numbered 0 to C-1, so that ```PVField(pv, 0)``` is the first field. Calling this function with a ```field``` value out of range triggers an error. > > --- > > ```WritePVFieldsFromByteArray(pv, array, extent)``` > > Copies the entries ```array->0``` to ```array->(extent-1)``` as the first ```extent``` fields of the PV, whose capacity is enlarged if necessary to make room. Should only be used if the PV stores byte-sized fields. > > --- > > ```WritePVFieldsFromWordArray(pv, array, extent)``` > > Copies the entries ```array-->0``` to ```array-->(extent-1)``` as the first ```extent``` fields of the PV, whose capacity is enlarged if necessary to make room. Should only be used if the PV stores word-sized fields. > > --- ### Creation and destruction If we want to obtain a completely new PV value, we have to use: > --- > > ```CreatePV(weak_kind_ID)``` > > Returns a completely new value of the given kind. This must be a pointer value, of course, so ```CreatePV(TEXT_TY)``` creates a new text, but ```CreatePV(NUMBER_TY)``` is an error. The value is initially equal to the default value for the kind in question: an empty text, an empty list, and so on. > > --- Note that Inform is _not_ a system with garbage collection, where unwanted objects linger for a while in memory and are then disposed of automatically. If we create a new value, we need to be certain that it will some day be destroyed. > --- > > ```DestroyPV(pv)``` > > Destroys the PV. If that in turn contained further PV data, those are automatically destroyed first. So destroying a list of texts causes all the texts to be destroyed, and then finally the list: only one call is needed. Once destroyed, a PV is gone, gone, gone: do not ever use the ```pv``` address again. > > --- ### Copying and comparison Copying cannot be done as simply as with regular data. The following is an attempt to take a list as an argument, and return a shortened version: ``` code [ ShortenedList list shorter_list; shorter_list = list; LIST_OF_TY_SetLength(shorter_list, 4); return shorter_list; ]; ``` Unfortunately the statement ```shorter_list = list;``` does not make a duplicate copy of the data in the list: it only makes a duplicate copy of the pointer to the list. It leaves both ```shorter_list``` and ```list``` pointing to the same actual data. So although ```LIST_OF_TY_SetLength``` does indeed truncate that data, the effect is that the original list is also truncated. What's actually needed is this: ``` code [ ShortenedList list shorter_list; shorter_list = CreatePV(LIST_OF_TY); CopyPV(shorter_list, list); LIST_OF_TY_SetLength(shorter_list, 4); return shorter_list; ]; ``` > --- > > ```CopyPV(to_pv, from_pv)``` > > Makes a duplicate copy of ```from_pv``` in ```to_pv```, both of which must already be valid PVs and with the same weak kind ID. > > --- The very fact that duplication is possible means that comparison is also tricky. For example, the ```if``` condition here: ``` code shorter_list = CreatePV(LIST_OF_TY); CopyPV(shorter_list, list); if (list == shorter_list) { ... } ``` ...would be false. ```shorter_list``` is a duplicate of ```list``` in terms of the contents they each have, but they are stored at different locations in memory, and all that ```list == shorter_list``` tests is whether the locations are equal. The correct way to do this is: ``` code shorter_list = CreatePV(LIST_OF_TY); CopyPV(shorter_list, list); if (ComparePV(list, shorter_list) == 0) { ... } ``` > --- > > ```ComparePV(pv1, pv2)``` > > Tests to see if ```pv1``` is less than, equal to, or greater than ```pv2```, both of which must already be valid PVs and with the same weak kind ID. Returns 0 if they are equal, a positive number if ```pv1``` is the greater one, and a negative number if ```pv2``` is greater. > > --- This test is used not only to see if one pointer value `is` another one, but also when sorting lists or tables of pointer values. ### Casting _Casting_ is taking a value from one kind and converting to a value of another kind. Inform does relatively little casting, but for example it can convert a `number` to a `real number`, or a `snippet` to a `text`. Here we're only concerned with the case where the target kind, i.e., the kind which the data ends up in, is a pointer-valued kind: so the `snippet` to `text` example would be done as the call ```CastPV(to_txt, SNIPPET_TY, snip)```. > --- > > ```CastPV(to_pv, original_weak_kind_ID, original_value)``` > > Should only be called where the caller is certain that the cast is possible. Takes the value ```original_value```, of the kind given in ```original_weak_kind_ID```, and converts it as faithfully as possible to become the new contents of ```to_pv```, which must already be a valid PV. > > --- ### Serialising _Serialising_ is converting data to or from a text file which can be exchanged with another program. Two functions are provided for this, ```PVFromFile``` and ```WritePVToFile```, but their use is beyond the scope of these notes. See the source code of ```BasicInformKit``` for more. Pointer values rarely allow serialisation, in practice. ## Neptune and kinds stored in multiple words of data In this section, we'll make a base kind which takes 5 words of data to store. It'll be a CMYK colour value, used by photographers and printers to specify colours in terms of the proportions of cyan, magenta, yellow and black ink needed, with each value a percentage ranging from 0 to 100; and then a name, in text form. For example, royal blue in CMYK is roughly 71, 53, 0, 12, `"royal blue"`. For this kind, we will make this Neptune declaration: ``` code new base CMYK_COLOUR_TY { conforms-to: POINTER_VALUE_TY conforms-to: SAYABLE_VALUE_TY singular: CMYK colour plural: CMYK colours long-block-size: 5 create-function: CMYK_COLOUR_TY_Create say-function: CMYK_COLOUR_TY_Say compare-function: CMYK_COLOUR_TY_Compare hash-function: CMYK_COLOUR_TY_Hash copy-function: CMYK_COLOUR_TY_Copy destroy-function: CMYK_COLOUR_TY_Destroy index-priority: 2 index-default-value: 0 specification-text: A cyan-magenta-yellow-black description of an ink colour. } ``` Let's look first at the setting ```long-block-size: 5```. The memory used by a pointer value is normally split between a _short block_ and a _long block_. There are basically two and a half strategies for kinds to follow: - Put all the data in the short block, and have no long block. We'll see examples of this later. To get this, set ```short-block-size``` to the number of fields of data needed, and do not set ```long-block-size```. - Have a 1-word short block (they're not called short for nothing) which consists only of a pointer to a long block, where the data is. This is what `CMYK colour` will do. To get this, set ```long-block-size``` to the number of fields of data needed, and do not set ```short-block-size```. If the long block needs to be able to expand or contract during use, set ```flexible-long-block-size``` to an overestimate of what is usually needed, and do not set either of the other two settings. - Have a 2-word short block and sometimes but not always have a long block as well. The `text` kind is currently the only one to do this, and it's not recommended for anything else. Note that the ```long block size``` is measured in _fields_, and we will need 5 in all: name, cyan, magenta, yellow, black. Next we come to a whole set of functions needed for `CMYK colour` to operate: ``` code create-function: CMYK_COLOUR_TY_Create say-function: CMYK_COLOUR_TY_Say compare-function: CMYK_COLOUR_TY_Compare hash-function: CMYK_COLOUR_TY_Hash copy-function: CMYK_COLOUR_TY_Copy destroy-function: CMYK_COLOUR_TY_Destroy ``` To start with the creation function: this will be called as ```CMYK_COLOUR_TY_Create(kind_id, sb_address)```. The long block must be created first, and then the short block, which incorporates a pointer to it, always in the last word of the short block. ``` code Constant CMYK_LONG_BLOCK_SIZE = 5; Constant CMYK_NAME_F = 0; Constant CMYK_CYAN_F = 1; Constant CMYK_MAGENTA_F = 2; Constant CMYK_YELLOW_F = 3; Constant CMYK_BLACK_F = 4; Array CMYK_DEFAULT_NAME_TEXT --> PACKED_TEXT_STORAGE "black"; [ CMYK_COLOUR_TY_Create kind_id sb_address short_block long_block txt; long_block = CreatePVLongBlock(CMYK_COLOUR_TY); txt = CreatePV(TEXT_TY); CopyPV(txt, CMYK_DEFAULT_NAME_TEXT); TEXT_TY_Mutable(txt); InitialisePVLongBlockField(long_block, CMYK_NAME_F, txt); InitialisePVLongBlockField(long_block, CMYK_CYAN_F, 0); InitialisePVLongBlockField(long_block, CMYK_MAGENTA_F, 0); InitialisePVLongBlockField(long_block, CMYK_YELLOW_F, 0); InitialisePVLongBlockField(long_block, CMYK_BLACK_F, 100); short_block = CreatePVShortBlock(sb_address, kind_id); short_block-->0 = long_block; return short_block; ]; ``` It is very important that the ```sb_address``` value is passed through to ```CreatePVShortBlock```. The deal here is that if this is 0 then the short block is created somewhere in the heap, but if it is non-zero, then the short block is created at the given location (often on the stack). We don't need to care about any of that, but we do need to pass the address on. The words of actual data in the long block are called _fields_. They're indexed 0 to 4, since we're using just 5. We put initial contents into the five words with the special function ```InitialisePVLongBlockField```. Note the ```LB```, for long block, at the end of this function name, and do not confuse this function with the usual ```WritePVField```. ```InitialisePVLongBlockField``` should never be used except in create functions. The interesting field of the five is ```CMYK_NAME_F```, of course, since it's a text value which itself needs creation. When created by ```CreatePV(TEXT_TY)```, the result will be a copy of the default text, which is the empty text `""`. We actually want to start with `"black"`, so we must _copy_ that constant value into our new text, but any use of packed text is always tricksy, and we make it mutable so that its value will sort correctly as against text. We don't simply execute ```InitialisePVLongBlockField(long_block, CMYK_NAME_F, CMYK_DEFAULT_NAME_TEXT);``` because values like text must always be copied in a way which keeps reference counts accurate. So here's how to say a CMYK once we have one: ``` code [ CMYK_COLOUR_TY_Say cmyk; TEXT_TY_Say(PVField(cmyk, CMYK_NAME_F)); print " ink = "; print "C:", PVField(cmyk, CMYK_CYAN_F), "% "; print "M:", PVField(cmyk, CMYK_MAGENTA_F), "% "; print "Y:", PVField(cmyk, CMYK_YELLOW_F), "% "; print "K:", PVField(cmyk, CMYK_BLACK_F), "%"; ]; ``` And here's a comparison function. These follow just the same calling conventions that they do for non-pointer-valued kinds. We're going to compare first alphabetically on the ink name, and then, within the same name, use the cyan level as a tiebreaker, failing that the magenta, and so on. ``` code [ CMYK_COLOUR_TY_Compare cmyk1 cmyk2 i d; d = TEXT_TY_Compare( PVField(cmyk1, CMYK_NAME_F), PVField(cmyk2, CMYK_NAME_F)); if (d ~= 0) return d; for (i=CMYK_CYAN_F: i