X-Git-Url: https://jxself.org/git/?p=ibg.git;a=blobdiff_plain;f=chapters%2F14.rst;h=0b99b449c05ca7a95e2c796c266ed37c7e812683;hp=234f502f45e8e6e0aef977a3ad693620451792aa;hb=fd8f547191457928785b8bc38570b05205f369ac;hpb=a94081289bc21041a8daac44d8c8b6714a831281 diff --git a/chapters/14.rst b/chapters/14.rst index 234f502..0b99b44 100644 --- a/chapters/14.rst +++ b/chapters/14.rst @@ -1,6 +1,10 @@ -====================== -Some last lousy points -====================== +======================== + Some last lousy points +======================== + +.. highlight:: inform + +.. default-role:: samp .. only:: html @@ -20,27 +24,25 @@ omissions, to give you a better feel for what's important, and what can be ignored for the time being; when you become an accomplished designer, you will decide what matters and what can be left on the shelf. -We'll also talk, in "Reading other people's code" on page 181, about a -few ways of doing things that we've chosen not to tell you about, but -which you're quite likely to encounter if you look at Inform code -written by other designers. - -The tone here is perhaps a little dry, but trust us: in walking this -dusty ground we touch on just about everything that is fundamental in -your overall understanding of Inform. And as always, the *Inform -Designer's Manual* provides rounder and more comprehensive coverage. +We'll also talk, in :ref:`reading-other-code`, about a few ways of doing +things that we've chosen not to tell you about, but which you're quite +likely to encounter if you look at Inform code written by other designers. +The tone here is perhaps a little dry, but trust us: in walking this dusty +ground we touch on just about everything that is fundamental in your +overall understanding of Inform. And as always, the |DM4| provides rounder +and more comprehensive coverage. Expressions =========== -In this guide we’ve used the placeholder ``expression`` a few times; +In this guide we’ve used the placeholder `{expression}` a few times; here's roughly what we mean. -* An ``expression`` is a single ``value``, or several ``values`` - combined using ``operators`` and sometimes parentheses ``(...)``. +* An `{expression}` is a single `{value}`, or several `{values}` + combined using `{operators}` and sometimes parentheses ``(...)``. -* Possible ``values`` include: +* Possible `{values}` include: * a literal number (-32768 to 32767) @@ -53,7 +55,7 @@ here's roughly what we mean. * (only in a run-time statement, not in a compile-time directive) the contents of a variable, or the return value from a routine. -* Possible ``operators`` include: +* Possible `{operators}` include: * an arithmetic operator: ``+ - * / % ++`` * a bitwise logical operator: ``& | ~`` @@ -61,7 +63,6 @@ here's roughly what we mean. * an object conditional operator: ``ofclass in notin provides has hasnt`` * a boolean combinational operator: ``&& || ~~`` - Internal IDs ============ @@ -69,8 +70,8 @@ Many of the items which you define in your source file -- objects, variables, routines, etc. -- need to be given a name so that other items can refer to them. We call this name an item's internal identifier (because it's used only within the source file and isn't visible to the -player), and we use the placeholders ``obj_id``, ``var_id``, -``routine_id``, etc. to represent where it's used. An internal ID +player), and we use the placeholders `{obj_id}`, `{var_id}`, +`{routine_id}`, etc. to represent where it's used. An internal ID * can be up to thirty-two characters long @@ -83,34 +84,32 @@ player), and we use the placeholders ``obj_id``, ``var_id``, used (except that a routine's local variables are not visible outside that routine). +.. _statements: Statements ========== -A **statement** is an instruction intended for the interpreter, telling -it what to do at run-time. It *must* be given in lower-case, and always -ends with a semicolon. - -Some statements, like ``if``, control one or more other statements. We -use the placeholder ``statement_block`` to represent either a single -``statement``, or any number of ``statements`` enclosed in braces: - .. todo:: - We might need some custom syntax highlighting here + We might need some custom syntax highlighting here. -.. code-block:: inform +A :term:`statement` is an instruction intended for the interpreter, telling +it what to do at run-time. It *must* be given in lower-case, and always +ends with a semicolon. + +Some statements, like ``if``, control one or more other statements. We +use the placeholder `{statement_block}` to represent either a single +`{statement}`, or any number of `{statements}` enclosed in braces:: statement; { statement; statement; ... statement; } -.. rubric:: Statements that we've met +Statements that we've met +------------------------- Our games have used these statements, about half of the Inform -possibilities: - -.. code-block:: inform +possibilities:: give obj_id attribute; give obj_id attribute attribute ... attribute; @@ -152,13 +151,11 @@ possibilities: <>; <>; - -.. rubric:: Statements that we've not met +Statements that we've not met +----------------------------- Although our example games haven't needed to use them, these looping -statements are sometimes useful: - -.. code-block:: inform +statements are sometimes useful:: break; continue; @@ -171,9 +168,7 @@ statements are sometimes useful: On the other hand, we suggest that you put the following statements on hold for now; they're not immediately relevant to everyday code and have -mostly to do with printing and formatting: - -.. code-block:: inform +mostly to do with printing and formatting:: box font @@ -184,46 +179,45 @@ mostly to do with printing and formatting: In particular, avoid using the deprecated jump statement if you possibly can. -.. rubric:: Print rules +Print rules +----------- -In ``print`` and ``print_ret`` statements, each ``value`` can be: +In ``print`` and ``print_ret`` statements, each `{value}` can be: -* a numeric ``expression``, displayed as a signed decimal number, +* a numeric `{expression}`, displayed as a signed decimal number, -* a ``"string"``, displayed literally, or +* a `"{string}"`, displayed literally, or * a print rule. You can create your own, or use a standard one, including: .. tabularcolumns:: ll +-------------------------+---------------------------------------------------+ - | ``(a) obj_id`` | the object's name, preceded by "a", "an" or "some"| + | `(a) {obj_id}` | the object's name, preceded by "a", "an" or "some"| +-------------------------+---------------------------------------------------+ - | ``(A) obj_id`` | as ``(a)`` but using "A", "An" or "Some" | + | `(A) {obj_id}` | as ``(a)`` but using "A", "An" or "Some" | +-------------------------+---------------------------------------------------+ - | ``(the) obj_id`` | the object's name, preceded by "the" | + | `(the) {obj_id}` | the object's name, preceded by "the" | +-------------------------+---------------------------------------------------+ - | ``(The) obj_id`` | as ``(the)`` but using "The" | + | `(The) {obj_id}` | as ``(the)`` but using "The" | +-------------------------+---------------------------------------------------+ - | ``(number) expression`` | the numeric expression's value in words | + | `(number) {expression}` | the numeric expression's value in words | +-------------------------+---------------------------------------------------+ - Directives ========== -A **directive** is an instruction intended for the compiler, telling it -what to do at compile-time, while the source file is being translated -into Z-code. By convention it's given an initial capital letter (though -the compiler doesn't enforce this) and always ends with a semicolon. +A :term:`directive` is an instruction intended for the compiler, telling it +what to do at compile-time, while the source file is being translated into +Z-code. By convention it's given an initial capital letter (though the +compiler doesn't enforce this) and always ends with a semicolon. -.. rubric:: Directives that we've met +Directives that we've met +------------------------- We've used all of these directives; note that for ``Class``, ``Extend``, ``Object`` and ``Verb`` the full supported syntax is more sophisticated -than the basic form presented here: - -.. code-block:: inform +than the basic form presented here:: Class class_id with property value, @@ -269,12 +263,11 @@ than the basic form presented here: #Ifdef any_id; ... #Endif; -.. rubric:: Directives that we've not met +Directives that we've not met +----------------------------- There's only a handful of useful directives which we haven't needed to -use: - -.. code-block:: inform +use:: Attribute attribute; @@ -286,9 +279,7 @@ use: Statusline score; Statusline time; -but there's a whole load which are of fairly low importance for now: - -.. code-block:: inform +but there's a whole load which are of fairly low importance for now:: Abbreviate Array @@ -306,6 +297,8 @@ but there's a whole load which are of fairly low importance for now: System_file Zcharacter +.. _objects: + Objects ======= @@ -314,7 +307,8 @@ represent the capabilities and current status of some specific component of the model world. Full variables are called properties; simpler two-state variables are attributes. -.. rubric:: Properties +Properties +---------- The library defines around forty-eight standard property variables (such as ``before`` or ``name``), but you can readily create further ones just @@ -322,82 +316,67 @@ by using them within an object definition. You can create and initialise a property in an object's ``with`` segment: -.. code-block:: inform - property, ! set to zero / false property value, ! set to a single value property value value ... value, ! set to a list of values -In each case, the ``value`` is either a compile-time ``expression``, or -an embedded routine: - -.. code-block:: inform +In each case, the `{value}` is either a compile-time `{expression}`, or +an embedded routine:: property expression, property [; statement; statement; ... statement; ], - -You can refer to the value of a property: - -.. code-block:: inform +You can refer to the value of a property:: self.property ! only within that same object obj_id.property ! everywhere -and you can test whether an object definition includes a given property: - -.. code-block:: inform +and you can test whether an object definition includes a given property:: (obj_id provides property) ! is true or false +.. _routines: Routines ======== Inform provides standalone routines and embedded routines. -.. rubric:: Standalone routines +Standalone routines +------------------- -Standalone routines are defined like this: - -.. code-block:: inform +Standalone routines are defined like this:: [ routine_id; statement; statement; ... statement; ]; -and called like this: - -.. code-block:: inform +and called like this:: routine_id() -.. rubric:: Embedded routines +Embedded routines +----------------- -These are embedded as the value of an object's property: - -.. code-block:: inform +These are embedded as the value of an object's property:: property [; statement; statement; ... statement; ], -and are usually called automatically by the library, or manually by: - -.. code-block:: inform +and are usually called automatically by the library, or manually by:: self.property() ! only within that same object obj_id.property() ! everywhere -.. rubric:: Arguments and local variables +Arguments and local variables +----------------------------- Both types of routine support up to fifteen local variables -- variables which can be used only by the statements within the routine, and which are automatically initialised to zero every time that the routine is -called: - -.. code-block:: inform +called:: [ routine_id var_id var_id ... var_id; statement; statement; ... statement; ]; @@ -406,9 +385,7 @@ called: You can pass up to seven arguments to a routine, by listing those arguments within the parentheses when you call the routine. The effect is simply to initialise the matching local variables to the argument -values rather than to zero: - -.. code-block:: inform +values rather than to zero:: routine_id(expression, expression, ... expression) @@ -416,29 +393,23 @@ Although it works, this technique is rarely used with embedded routines, because there is no mechanism for the library to supply argument values when calling the routine. - -.. rubric:: Return values +Return values +------------- Every routine returns a single value, which is supplied either -explicitly by some form of return statement: - -.. code-block:: inform +explicitly by some form of return statement:: [ routine_id; statement; statement; ... return expr; ]; ! returns expr property [; statement; statement; ... return expr; ], ! returns expr -or implicitly when the routine runs out of statements. If none of these -``statements`` is one -- ``return``, ``print_ret``, ``"..."` or -``<<...>>`` -- that causes an explicit return, then: - -.. code-block:: inform +or implicitly when the routine runs out of statements. If none of these +``statements`` is one -- ``return``, ``print_ret``, ``"..."`` or +``<<...>>`` -- that causes an explicit return, then:: [ routine_id; statement; statement; ... statement; ]; -returns ``true`` and - -.. code-block:: inform +returns ``true`` and :: property [; statement; statement; ... statement; ] @@ -449,16 +420,12 @@ left to themselves, Standalone routines return True, Embedded routines return False. Here's an example standalone routine which returns the larger of its two -argument values: - -.. code-block:: inform +argument values:: [ Max a b; if (a > b) return a; else return b; ]; and here are some examples of its use (note that the first example, -though legal, does nothing useful whatsoever): - -.. code-block:: inform +though legal, does nothing useful whatsoever):: Max(x,y); @@ -468,16 +435,13 @@ though legal, does nothing useful whatsoever): switch (Max(3,y)) { ... - -.. rubric:: Library routines versus entry points - +Library routines versus entry points +------------------------------------ A library routine is a standard routine, included within the library files, which you can optionally call from your source file if you require the functionality which the routine provides. We've mentioned -these library routines: - -.. code-block:: inform +these library routines:: IndirectlyContains(parent_obj_id, obj_id) @@ -492,23 +456,19 @@ these library routines: By contrast, an entry point routine is a routine which you can provide in your source file, in which case the library calls it at an -appropriate time. We've mentioned these optional entry point routines: - -.. code-block:: inform +appropriate time. We've mentioned these optional entry point routines:: DeathMessage() InScope(actor_obj_id) -And this, the only mandatory one: - -.. code-block:: inform +And this, the only mandatory one:: Initialise() -There are full lists in "Library routines" on page 264 and "Optional -entry points" on page 270. +There are full lists in :ref:`library-routines` and :ref:`entry-points`. +.. _reading-other-code: Reading other people's code =========================== @@ -524,7 +484,8 @@ to find a style that suits you and, this is the important bit, be *consistent* about its use. In this section, we highlight some of the more obvious differences which you may encounter. -.. rubric:: Code layout +Code layout +----------- Every designer has his or her own style for laying out their source code, and they're all worse than the one you adopt. Inform's flexibility @@ -537,9 +498,7 @@ your code, about making it as readable as you can. This is doubly true if you ever contemplate sharing a library extension with the rest of the community. This example, with the name changed, is -from a file in the Archive: - -.. code-block:: inform +from a file in the Archive:: [xxxx i j; if (j==0) rtrue; @@ -567,9 +526,7 @@ from a file in the Archive: Here's the same routine after a few minutes spent purely on making it more comprehensible; we haven't actually tested that it (still) works, -though that second ``else`` looks suspicious: - -.. code-block:: inform +though that second ``else`` looks suspicious:: [ xxxx i j; if (i in player || i has static or scenery || j == nothing) return true; @@ -590,14 +547,13 @@ though that second ``else`` looks suspicious: We hope you'll agree that the result was worth the tiny extra effort. Code gets written once; it gets read dozens and dozens of times. -.. rubric:: Shortcuts +Shortcuts +--------- There are a few statement shortcuts, some more useful than others, which you'll come across. -* These five lines all do the same thing: - - .. code-block:: inform +* These five lines all do the same thing:: return true; return 1; @@ -605,65 +561,49 @@ you'll come across. rtrue; ]; ! at the end of a standalone routine -* These four lines all do the same thing: - - .. code-block:: inform +* These four lines all do the same thing:: return false; return 0; rfalse; ]; ! at the end of an embedded routine -* These four lines all do the same thing: - - .. code-block:: inform +* These four lines all do the same thing:: print "string"; new_line; return true; print "string^"; return true; print_ret "string"; "string"; -* These lines are the same: - - .. code-block:: inform +* These lines are the same:: print value1; print value2; print value3; print value1, value2, value3; -* These lines are the same: - - .. code-block:: inform +* These lines are the same:: ; return true; <>; -* These lines are also the same: - - .. code-block:: inform +* These lines are also the same:: print "^"; new_line; -* These ``if`` statements are equivalent: - - .. code-block:: inform +* These ``if`` statements are equivalent:: if (MyVar == 1 || MyVar == 3 || MyVar == 7) ... if (MyVar == 1 or 3 or 7) ... -* These ``if`` statements are equivalent as well: - - .. code-block:: inform +* These ``if`` statements are equivalent as well:: if (MyVar ~= 1 && MyVar ~= 3 && MyVar ~= 7) ... if (MyVar ~= 1 or 3 or 7) ... * In an ``if`` statement, the thing in parentheses can be *any* expression; all that matters is its value: zero (false) or anything - else (true). For example, these statements are equivalent: - - .. code-block:: inform + else (true). For example, these statements are equivalent:: if (MyVar ~= false) ... if (~~(MyVar == false)) ... @@ -673,17 +613,13 @@ you'll come across. Note that the following statement specifically tests whether ``MyVar`` contains ``true`` (1), *not* whether its value is anything other than - zero. - - .. code-block:: inform + zero. :: if (MyVar == true) ... * If ``MyVar`` is a variable, the statements ``MyVar++;`` and ``++MyVar;`` work the same as ``MyVar = MyVar + 1;`` For example, - these lines are equivalent: - - .. code-block:: inform + these lines are equivalent:: MyVar = MyVar + 1; if (MyVar == 3) ... if (++MyVar == 3) ... @@ -697,9 +633,7 @@ you'll come across. value. In the example, if ``MyVar`` currently contains 2 then ``++MyVar`` returns 3 and ``MyVar++`` returns 2, even though in both cases the value of ``MyVar`` afterwards is 3. As another example, - this code (from Helga in "William Tell"): - - .. code-block:: inform + this code (from Helga in "William Tell"):: Talk: self.times_spoken_to = self.times_spoken_to + 1; switch (self.times_spoken_to) { @@ -710,9 +644,7 @@ you'll come across. } ], - could have been written more succinctly like this: - - .. code-block:: inform + could have been written more succinctly like this:: Talk: switch (++self.times_spoken_to) { 1: score++; @@ -723,15 +655,14 @@ you'll come across. ], * Similarly, the statements ``MyVar--;`` and ``--MyVar;`` work the same - as ``MyVar = MyVar - 1;`` Again, these lines are equivalent: - - .. code-block:: inform + as ``MyVar = MyVar - 1;`` Again, these lines are equivalent:: MyVar = MyVar - 1; if (MyVar == 7) ... if (--MyVar == 7) ... if (MyVar-- == 8) ... -.. rubric:: "number" property and "general" attribute +"number" property and "general" attribute +----------------------------------------- The library defines a standard ``number`` property and a standard ``general`` attribute, whose roles are undefined: they are @@ -744,19 +675,19 @@ meaningless. Your game will be clearer and easier to debug if you instead create new property variables -- with appropriate names -- as part of your ``Object`` and ``Class`` definitions. -.. rubric:: Common properties and attributes +.. _common-props: -As an alternative to creating new individual properties which apply only -to a single object (or class of objects), it's possible to devise -properties and new attributes which, like those defined by the library, -are available on *all* objects. The need to do this is actually quite -rare, and is mostly confined to library extensions (for example, the -``pname.h`` extension which we encountered in "Captain Fate: take 3" on -page 147 gives every object a ``pname`` property and a -``phrase_matched`` attribute). To create them, you would use these -directives near the start of your source file: +Common properties and attributes +-------------------------------- -.. code-block:: inform +As an alternative to creating new individual properties which apply only to +a single object (or class of objects), it's possible to devise properties +and new attributes which, like those defined by the library, are available +on *all* objects. The need to do this is actually quite rare, and is mostly +confined to library extensions (for example, the ``pname.h`` extension +which we encountered in :doc:`12` gives every object a ``pname`` property +and a ``phrase_matched`` attribute). To create them, you would use these +directives near the start of your source file:: Attribute attribute; @@ -770,7 +701,10 @@ properties (of which the library currently defines around forty-eight). On the other hand, the number of individual properties which you can add is virtually unlimited. -.. rubric:: Setting up the object tree +.. _setting-up-tree: + +Setting up the object tree +-------------------------- Throughout this guide, we've defined the initial position of each object within the overall object tree either by explicitly mentioning its @@ -780,9 +714,7 @@ objects which crop up in more than one place, by using their ``found_in`` properties. For example, in "William Tell" we defined twenty-seven objects; omitting those which used ``found_in`` to define their placement at the start of the game, we're left with object -definitions starting like this: - -.. code-block:: inform +definitions starting like this:: Room street "A street in Altdorf" @@ -819,9 +751,7 @@ the last item of header information. There's an alternative object syntax which is available to achieve the same object tree, using "arrows". That is, we could have defined those -parent-and-child objects as: - -.. code-block:: inform +parent-and-child objects as:: Room below_square "Further along the street" Furniture -> stall "fruit and vegetable stall" @@ -856,9 +786,7 @@ example, the ``tree`` and ``governor`` objects are both children of the ``-> ->``, and so on. In "William Tell", that situation doesn't occur; to illustrate how it works, imagine that at the start of the game the potatoes and the other fruit and vegetables where actually *on* the -stall. Then we might have used: - -.. code-block:: inform +stall. Then we might have used:: Room below_square "Further along the street" Furniture -> stall "fruit and vegetable stall" @@ -896,16 +824,14 @@ The disadvantages include: We prefer to explicitly name the parent, but you'll encounter both forms very regularly. -.. rubric:: Quotes in "name" properties - -We went to some lengths, way back in "Things in quotes" on page 55, to -explain the difference between double quotes ``"..."`` (strings to be -output) and single quotes ``'...'`` (input tokens -- dictionary words). -Perhaps somewhat unfortunately, Inform allows you to blur this clean -distinction: you can use double quotes in name properties and Verb -directives: +Quotes in "name" properties +--------------------------- -.. code-block:: inform +We went to some lengths, way back in :ref:`things-in-quotes`, to explain +the difference between double quotes ``"..."`` (strings to be output) and +single quotes ``'...'`` (input tokens -- dictionary words). Perhaps +somewhat unfortunately, Inform allows you to blur this clean distinction: +you can use double quotes in name properties and Verb directives:: NPC stallholder "Helga" below_square with name "stallholder" "greengrocer" "monger" "shopkeeper" "merchant" @@ -920,7 +846,8 @@ directives: dictionary words, not strings; it's just as easy -- and far clearer -- to stick rigidly to the preferred punctuation. -.. rubric:: Obsolete usages +Obsolete usages +--------------- Finally, remember that Inform has been evolving since 1993. Over that time, Graham has taken considerable care to maintain as much @@ -932,5 +859,3 @@ example, see games using ``Nearby`` directives (denotes parentage, roughly the same as ``->``) and ``near`` conditions (roughly, having the same parent), or with ``" \ "`` controlling line breaks in long ``print`` statements. Try to understand them; try *not* to use them. - -