X-Git-Url: https://jxself.org/git/?p=ibg.git;a=blobdiff_plain;f=chapters%2F10.rst;h=fd9cbf57a414d98d8dcb8385375a4cddb48f3908;hp=0d51d8af1af731678b16581a11c6740dea18f357;hb=4381288eeb792adb3672ef747013c02815fa760a;hpb=95b5702817b987123d71d432f81eeb0c7101b59c diff --git a/chapters/10.rst b/chapters/10.rst index 0d51d8a..fd9cbf5 100644 --- a/chapters/10.rst +++ b/chapters/10.rst @@ -14,51 +14,50 @@ Captain Fate: take 1 |S|\imple though they are, our two games have covered most of the basic functionality of Inform, providing enough solid ground underfoot for you to -start creating simple stories. Even if some of what you've encountered +start creating simple stories. Even if some of what you've encountered doesn't make sense yet, you should be able to browse a game's source code and form a general understanding of what is going on. -We'll now design a third game, to show you a few additional features and -give you some more sample code to analyse. In "Heidi" we tried to make -progress step by step, explaining every bit of code that went into the -game as we laid the objects sequentially; in "William Tell" you'll have -noticed that we took a few necessary explanatory detours, as the -concepts grew more interesting and complicated. Here we'll organise the -information in logical didactic chunks, defining some of the objects -minimally at first and then adding complexity as need arises. Again, -this means that you won't be able to compile for testing purposes after -the addition of every code snippet, so, if you're typing in the game as -you read, you’ll need to check the advice in :ref:`compile-as-you-go`. - -A lot of what goes into this game we have already seen; you may deduce -from this that the game design business is fairly repetitious and that -most games are, when you reach the programming bottom line, another -remake of the same old theme. Well, yes and no: you've got a camera and -have seen some short home videos in the making, but it’s a long way from -here to Casablanca. To stick with the analogy, we'll now construct the -opening sequence of an indie B-movie, a tribute to the style of -super-hero made famous by a childhood of comic books: +We'll now design a third game, to show you a few additional features and +give you some more sample code to analyse. In "Heidi" we tried to make +progress step by step, explaining every bit of code that went into the game +as we laid the objects sequentially; in "William Tell" you'll have noticed +that we took a few necessary explanatory detours, as the concepts grew more +interesting and complicated. Here we'll organise the information in +logical didactic chunks, defining some of the objects minimally at first +and then adding complexity as need arises. Again, this means that you +won't be able to compile for testing purposes after the addition of every +code snippet, so, if you're typing in the game as you read, you’ll need to +check the advice in :ref:`compile-as-you-go`. + +A lot of what goes into this game we have already seen; you may deduce from +this that the game design business is fairly repetitious and that most +games are, when you reach the programming bottom line, another remake of +the same old theme. Well, yes and no: you've got a camera and have seen +some short home videos in the making, but it’s a long way from here to +Casablanca. To stick with the analogy, we'll now construct the opening +sequence of an indie B-movie, a tribute to the style of super-hero made +famous by a childhood of comic books: .. pull-quote:: - "Impersonating mild mannered John Covarth, assistant help boy at an - insignificant drugstore, you suddenly STOP when your acute hearing - deciphers a stray radio call from the POLICE. There’s some MADMAN - attacking the population in Granary Park! You must change into your - Captain FATE costume fast...!" + "Impersonating mild mannered John Covarth, assistant help boy at an + insignificant drugstore, you suddenly STOP when your acute hearing + deciphers a stray radio call from the POLICE. There’s some MADMAN + attacking the population in Granary Park! You must change into your + Captain FATE costume fast...!" -which won't be so easy to do. In this short example, players will win -when they manage to change into their super-hero costume and fly away to -meet the foe. The confrontation will -- perhaps -- take place in some -other game, where we can but hope that Captain Fate will vanquish the -forces of evil, thanks to his mysterious (and here unspecified) -superpowers. +which won't be so easy to do. In this short example, players will win when +they manage to change into their super-hero costume and fly away to meet +the foe. The confrontation will -- perhaps -- take place in some other +game, where we can but hope that Captain Fate will vanquish the forces of +evil, thanks to his mysterious (and here unspecified) superpowers. Fade up on: a nondescript city street ===================================== -The game starts with meek John Covarth walking down the street. We set -up the game as usual: +The game starts with meek John Covarth walking down the street. We set up +the game as usual: .. code-block:: inform @@ -134,32 +133,36 @@ Almost everything is familar, apart from a few details: Constant OBJECT_SCORE 1; Constant ROOM_SCORE 1; -By default, Inform uses a system of automatic pronouns: as the player -character moves into a room, the library assigns pronouns like IT and -HIM to likely objects (if you play "Heidi" or "William Tell" and type -PRONOUNS, you can see how the settings change). There is another option. -If we declare the ``MANUAL_PRONOUNS`` onstant, we force the library to -assign pronouns to objects only as the player mentions them (that is, IT -will be unassigned until the player types, say, EXAMINE TREE, at which -point, IT becomes the TREE ). The behaviour of pronoun assignment is a -matter of personal taste; no system is objectively perfect. - -Apart from the constant ``MAX_SCORE`` that we have seen in "William -Tell", which defines the maximum number of points to be scored, we now -see two more constants: ``OBJECT_SCORE`` and ``ROOM_SCORE``. There are -several scoring systems predefined in Inform. In "William Tell" we've -seen how you can manually add (or subtract) points by changing the value -of the variable ``score``. Another approach is to award points to -players on the first occasion that they (a) enter a particular room, or -(b) pick up a particular object. To define that a room or object is -indeed “particular”, all you have to do is give it the attribute -``scored``; the library take cares of the rest. The predefined scores -are five points for finally reached rooms and four points for wondrous -acquisition of objects. With the constants ``OBJECT_SCORE`` and -``ROOM_SCORE`` we can change those defaults; for the sake of example, -we've decided to modestly award one point for each. By the way, the use -of an equals sign ``=`` is optional with ``Constant``; these two lines -have identical effect: +By default, Inform uses a system of automatic pronouns: as the player +character moves into a room, the library assigns pronouns like IT and HIM +to likely objects (if you play "Heidi" or "William Tell" and type PRONOUNS, +you can see how the settings change). There is another option. If we +declare the ``MANUAL_PRONOUNS`` constant, we force the library to assign +pronouns to objects only as the player mentions them (that is, IT will be +unassigned until the player types, say, EXAMINE TREE, at which point, IT +becomes the TREE ). The behaviour of pronoun assignment is a matter of +personal taste; no system is objectively perfect. + +.. Generated by autoindex +.. index:: + pair: score; library variable + pair: scored; library attribute + +Apart from the constant ``MAX_SCORE`` that we have seen in "William Tell", +which defines the maximum number of points to be scored, we now see two +more constants: ``OBJECT_SCORE`` and ``ROOM_SCORE``. There are several +scoring systems predefined in Inform. In "William Tell" we've seen how you +can manually add (or subtract) points by changing the value of the variable +:var:`score`. Another approach is to award points to players on the first +occasion that they (a) enter a particular room, or (b) pick up a particular +object. To define that a room or object is indeed “particular”, all you +have to do is give it the attribute :attr:`scored`; the library take cares +of the rest. The predefined scores are five points for finally reached +rooms and four points for wondrous acquisition of objects. With the +constants ``OBJECT_SCORE`` and ``ROOM_SCORE`` we can change those defaults; +for the sake of example, we've decided to modestly award one point for +each. By the way, the use of an equals sign ``=`` is optional with +``Constant``; these two lines have identical effect: .. code-block:: inform @@ -167,9 +170,8 @@ have identical effect: Constant ROOM_SCORE = 1; -Another difference has to do with a special short-hand method that -Inform provides for displaying strings of text. Until now, we have shown -you: +Another difference has to do with a special short-hand method that Inform +provides for displaying strings of text. Until now, we have shown you: .. code-block:: inform @@ -177,27 +179,31 @@ you: ... print_ret "And now for something completely different..."; -Both lines do the same thing: they display the quoted string, output a -newline character, and return true. As you have seen in the previous -example games, this happens quite a lot, so there is a yet shorter way -of achieving the same result: +Both lines do the same thing: they display the quoted string, output a +newline character, and return true. As you have seen in the previous +example games, this happens quite a lot, so there is a yet shorter way of +achieving the same result: .. code-block:: inform "And now for something completely different..."; -That is, *in a routine* (where the compiler is expecting to find a -collection of statements each terminated by a semicolon), a string in -double quotes by itself, without the need for any explicit keywords, -works exactly as if there were a ``print_ret`` in front of it. Remember -that this way of displaying text implies a ``return true`` at the end -(which therefore exits from the routine immediately). This detail -becomes important if we *don't* want to return true after the string -has been displayed on the screen -- we should use the explicit ``print`` -statement instead. +That is, *in a routine* (where the compiler is expecting to find a +collection of statements each terminated by a semicolon), a string in +double quotes by itself, without the need for any explicit keywords, works +exactly as if there were a ``print_ret`` in front of it. Remember that +this way of displaying text implies a ``return true`` at the end (which +therefore exits from the routine immediately). This detail becomes +important if we *don't* want to return true after the string has been +displayed on the screen -- we should use the explicit ``print`` statement +instead. + +.. Generated by autoindex +.. index:: + pair: name; library property You'll notice that -- unusually for a room -- our ``street`` object has -a ``name`` property: +a :prop:`name` property: .. code-block:: inform @@ -205,21 +211,25 @@ a ``name`` property: with name 'city' 'buildings' 'skyscrapers' 'shops' 'apartments' 'cars', ... -Rooms aren't normally referenced by name, so this may seem odd. In fact, -we're illustrating a feature of Inform: the ability to define dictionary -words as "known but irrelevant" in this location. If the player types -EXAMINE CITY here, the interpreter will reply "That's not something you -need to refer to in order to SAVE the day", rather than the misleading -"You can't see any such thing". We mostly prefer to deal with such -scenic words using classes like ``Prop`` and ``Furniture``, but -sometimes a room's ``name`` property is a quick and convenient solution. - -In this game, we provide a class named ``Appliance`` to take care of -furniture and unmovable objects. You’ll notice that the starting room we -have defined has no connections yet. The description mentions a phone -booth and a café, so we might want to code those. While the café will be -a normal room, it would seem logical that the phone booth is actually a -big box on the sidewalk; therefore we define a ``container`` set in the +Rooms aren't normally referenced by name, so this may seem odd. In fact, +we're illustrating a feature of Inform: the ability to define dictionary +words as "known but irrelevant" in this location. If the player types +EXAMINE CITY here, the interpreter will reply "That's not something you +need to refer to in order to SAVE the day", rather than the misleading "You +can't see any such thing". We mostly prefer to deal with such scenic words +using classes like ``Prop`` and ``Furniture``, but sometimes a room's +:prop:`name` property is a quick and convenient solution. + +.. Generated by autoindex +.. index:: + pair: container; library attribute + +In this game, we provide a class named ``Appliance`` to take care of +furniture and unmovable objects. You’ll notice that the starting room we +have defined has no connections yet. The description mentions a phone +booth and a café, so we might want to code those. While the café will be a +normal room, it would seem logical that the phone booth is actually a big +box on the sidewalk; therefore we define a :attr:`container` set in the street, which players may enter: .. code-block:: inform @@ -242,28 +252,28 @@ street, which players may enter: ], has enterable container open; -What's interesting are the attributes at the end of the definition. -You'll recall from Heidi's ``nest`` object that a ``container`` is an -object capable of having other objects placed in it. If we make -something ``enterable``, players count as one of those objects, so that -they may squeeze inside. Finally, ``containers`` are, by default, -supposed to be closed. You can make them ``openable`` if you wish -players to be able to OPEN and CLOSE them at will, but this doesn't seem -appropriate behaviour for a public cabin -- it would become tedious to -have to type OPEN BOOTH and CLOSE BOOTH when these actions provide -nothing special -- so we add instead the attribute ``open`` (as we did -with the nest), telling the interpreter that the container is open from -the word go. Players aren't aware of our design, of course; they may -indeed try to OPEN and CLOSE the booth, so we trap those actions in a -``before`` property which just tells them that these are not relevant -options. The ``after`` property gives a customised message to override -the library’s default for commands like ENTER BOOTH or GO INSIDE BOOTH. - -Since in the street's description we have told players that the phone -booth is to the south, they might also try typing SOUTH. We must -intercept this attempt and redirect it (while we're at it, we add a -connection to the as-yet-undefined café room and a default message for -the movement which is not allowed): +What's interesting are the attributes at the end of the definition. You'll +recall from Heidi's ``nest`` object that a :attr:`container` is an object +capable of having other objects placed in it. If we make something +:attr:`enterable`, players count as one of those objects, so that they may +squeeze inside. Finally, ``containers`` are, by default, supposed to be +closed. You can make them :attr:`openable` if you wish players to be able +to OPEN and CLOSE them at will, but this doesn't seem appropriate behaviour +for a public cabin -- it would become tedious to have to type OPEN BOOTH +and CLOSE BOOTH when these actions provide nothing special -- so we add +instead the attribute :attr:`open` (as we did with the nest), telling the +interpreter that the container is open from the word go. Players aren't +aware of our design, of course; they may indeed try to OPEN and CLOSE the +booth, so we trap those actions in a :prop:`before` property which just +tells them that these are not relevant options. The :prop:`after` property +gives a customised message to override the library’s default for commands +like ENTER BOOTH or GO INSIDE BOOTH. + +Since in the street's description we have told players that the phone booth +is to the south, they might also try typing SOUTH. We must intercept this +attempt and redirect it (while we're at it, we add a connection to the +as-yet-undefined café room and a default message for the movement which is +not allowed): .. code-block:: inform @@ -279,12 +289,12 @@ the movement which is not allowed): "No time now for exploring! You'll move much faster in your Captain FATE costume."; -That takes care of entering the booth. But what about leaving it? -Players may type EXIT or OUT while they are inside an enterable -container and the interpreter will oblige but, again, they might type -NORTH. This is a problem, since we are actually in the street (albeit -inside the booth) and to the north we have the café. We may provide for -this condition in the room's ``before`` property: +That takes care of entering the booth. But what about leaving it? Players +may type EXIT or OUT while they are inside an enterable container and the +interpreter will oblige but, again, they might type NORTH. This is a +problem, since we are actually in the street (albeit inside the booth) and +to the north we have the café. We may provide for this condition in the +room's :prop:`before` property: .. code-block:: inform @@ -293,11 +303,11 @@ this condition in the room's ``before`` property: if (player in booth && noun == n_obj) <>; ], -Since we are outdoors and the booth provides a shelter, it's not -impossible that a player may try just IN, which is a perfectly valid -connection. However, that would be an ambiguous command, for it could -also refer to the café, so we express our bafflement and force the -player to try something else: +Since we are outdoors and the booth provides a shelter, it's not impossible +that a player may try just IN, which is a perfectly valid connection. +However, that would be an ambiguous command, for it could also refer to the +café, so we express our bafflement and force the player to try something +else: .. code-block:: inform @@ -305,9 +315,9 @@ player to try something else: s_to [; <>; ], in_to "But which way?", -Now everything seems to be fine, except for a tiny detail. We've said -that, while in the booth, the player character’s location is still the -``street`` room, regardless of being inside a ``container``; if players +Now everything seems to be fine, except for a tiny detail. We've said +that, while in the booth, the player character’s location is still the +``street`` room, regardless of being inside a :attr:`container`; if players chanced to type LOOK, they'd get: .. code-block:: transcript @@ -317,19 +327,19 @@ chanced to type LOOK, they'd get: there's an open cafe now serving lunch. To the south, you can see a phone booth. -Hardly an adequate description while *inside* the booth. There are -several ways to fix the problem, depending on the result you wish to -achieve. The library provides a property called ``inside_description`` -which you can utilise with enterable containers. It works pretty much -like the normal ``description`` property, but it gets printed only when -the player is inside the container. The library makes use of this -property in a very clever way, because for every LOOK action it checks -whether we can see outside the container: if the container has the -``transparent`` attribute set, or if it happens to be ``open``, the -library displays the normal ``description`` of the room first and then -the ``inside_description`` of the container. If the library decides we -can’t see outside the container, only the inside_description is -displayed. Take for instance the following (simplified) example: +Hardly an adequate description while *inside* the booth. There are several +ways to fix the problem, depending on the result you wish to achieve. The +library provides a property called :prop:`inside_description` which you can +utilise with enterable containers. It works pretty much like the normal +:prop:`description` property, but it gets printed only when the player is +inside the container. The library makes use of this property in a very +clever way, because for every LOOK action it checks whether we can see +outside the container: if the container has the :attr:`transparent` +attribute set, or if it happens to be :attr:`open`, the library displays +the normal :prop:`description` of the room first and then the +:prop:`inside_description` of the container. If the library decides we +can’t see outside the container, only the :prop:`inside_description` is +displayed. Take for instance the following (simplified) example: .. code-block:: inform @@ -349,7 +359,7 @@ displayed. Take for instance the following (simplified) example: ... has container openable enterable light; -Now, the player would be able to OPEN BOX and ENTER BOX. A player who +Now, the player would be able to OPEN BOX and ENTER BOX. A player who tried a LOOK would get: .. code-block:: transcript @@ -368,14 +378,14 @@ If now the player closes the box and LOOKs: The inside panels of the magic box are covered with black velvet. There is a tiny switch by your right foot. -In our case, however, we don't wish the description of the street to be -displayed at all (even if a caller is supposedly able to see the street -while inside a booth). The problem is that we have made the booth an -``open`` container, so the street's description would be displayed every -time. There is another solution. We can make the ``description`` -property of the ``street`` room a bit more complex, and change its -value: instead of a string, we write an embedded routine. Here's the -(almost) finished room: +In our case, however, we don't wish the description of the street to be +displayed at all (even if a caller is supposedly able to see the street +while inside a booth). The problem is that we have made the booth an +:attr:`open` container, so the street's description would be displayed +every time. There is another solution. We can make the +:prop:`description` property of the ``street`` room a bit more complex, and +change its value: instead of a string, we write an embedded routine. +Here's the (almost) finished room: .. code-block:: inform @@ -402,7 +412,7 @@ value: instead of a string, we write an embedded routine. Here's the Captain FATE costume."; The description while inside the booth mentions the sidewalk, which -might invite the player to EXAMINE it. No problem: +might invite the player to EXAMINE it. No problem: .. code-block:: inform @@ -415,7 +425,7 @@ might invite the player to EXAMINE it. No problem: the CITY!"; Unfortunately, both descriptions also mention the café, which will be a -room and therefore not, from the outside, an examinable object. The +room and therefore not, from the outside, an examinable object. The player may enter it and will get whatever description we code as the result of a LOOK action (which will have to do with the way the café looks from the *inside*); but while we are on the street we need @@ -437,55 +447,61 @@ something else to describe it: ], has enterable proper; +.. index:: accented characters + .. note:: Although the text of our guide calls Benny's establishment a "café" -- note the acute "e" -- the game itself simplifies this to "cafe". We do this for clarity, not because Inform doesn't support accented - characters. The |DM4| explains in detail how to display these characters - in :dm4:`§1.11 ` "*How text is printed*" and provides the - whole Z-machine character set in Table 2. In our case, we could have - displayed this:: + characters. The |DM4| explains in detail how to display these + characters in :dm4:`§1.11 ` "*How text is printed*" and + provides the whole Z-machine character set in Table 2. In our case, we + could have displayed this:: The town's favourite for a quick snack, Benny's café has a 50's ROCKETSHIP look. - by defining the ``description`` property as any of these: + by defining the :prop:`description` property as any of these: .. code-block:: inform - description - "The town's favourite for a quick snack, Benny's caf@'e has a 50's - ROCKETSHIP look.", + description + "The town's favourite for a quick snack, Benny's caf@'e has a 50's + ROCKETSHIP look.", - description - "The town's favourite for a quick snack, Benny's caf@@170 has a 50's - ROCKETSHIP look.", + description + "The town's favourite for a quick snack, Benny's caf@@170 has a 50's + ROCKETSHIP look.", - description - "The town's favourite for a quick snack, Benny's caf@{E9} has a 50's - ROCKETSHIP look.", + description + "The town's favourite for a quick snack, Benny's caf@{E9} has a 50's + ROCKETSHIP look.", - However, all three forms are harder to read than the vanilla "cafe", so + However, all three forms are harder to read than the vanilla "cafe", so we've opted for the simple life. -Unlike the sidewalk object, we offer more than a mere description. Since -the player may try ENTER CAFE as a reasonable way of access -- which -would have confused the interpreter immensely -- we take the opportunity -of making this object also ``enterable``, and we cheat a little. The -attribute ``enterable`` has permitted the verb ENTER to be applied to -this object, but this is not a ``container``; we want the player to be -sent into the *real* café room instead. The ``before`` property handles -this, intercepting the action, displaying a message and teleporting the -player into the café. We ``return true`` to inform the interpreter that -we have taken care of the ``Enter`` action ourselves, so it can stop -right there. - -As a final detail, note that we now have two ways of going into the -café: the ``n_to`` property of the ``street`` room and the ``Enter`` -action of the ``outside_of_cafe`` object. A perfectionist might point -out that it would be neater to handle the actual movement of the player -in just one place of our code, because this helps clarity. To achieve -this, we redirect the street's ``n_to`` property thus: +Unlike the sidewalk object, we offer more than a mere description. Since +the player may try ENTER CAFE as a reasonable way of access -- which would +have confused the interpreter immensely -- we take the opportunity of +making this object also :attr:`enterable`, and we cheat a little. The +attribute :attr:`enterable` has permitted the verb ENTER to be applied to +this object, but this is not a :attr:`container`; we want the player to be +sent into the *real* café room instead. The :prop:`before` property handles +this, intercepting the action, displaying a message and teleporting the +player into the café. We ``return true`` to inform the interpreter that we +have taken care of the :act:`Enter` action ourselves, so it can stop right +there. + +.. Generated by autoindex +.. index:: + pair: n_to; library property + +As a final detail, note that we now have two ways of going into the café: +the :prop:`n_to` property of the ``street`` room and the :act:`Enter` +action of the ``outside_of_cafe`` object. A perfectionist might point out +that it would be neater to handle the actual movement of the player in just +one place of our code, because this helps clarity. To achieve this, we +redirect the street's :prop:`n_to` property thus: .. code-block:: inform @@ -495,10 +511,10 @@ You may think that this is unnecessary madness, but a word to the wise: in a large game, you want action handling going on just in one place when possible, because it will help you to keep track of where things are a-happening if something goes *ploof* (as, believe us, it will; see -:doc:`16`). You don't need to be a perfectionist, just cautious. +:doc:`16`). You don't need to be a perfectionist, just cautious. A booth in this kind of situation is an open invitation for the player to -step inside and try to change into Captain Fate's costume. We won't let +step inside and try to change into Captain Fate's costume. We won't let this happen -- the player isn't Clark Kent, after all; later we'll explain how we forbid this action -- and that will force the player to go inside the café, looking for a discreet place to disrobe; but first, let's freeze @@ -509,29 +525,36 @@ A hero is not an ordinary person Which is to say, normal actions won't be the same for him. -As you have probably inferred from the previous chapters, some of the -library’s standard defined actions are less important than others in -making the game advance towards one of its conclusions. The library -defines PRAY and SING, for instance, which are of little consequence in -a normal gaming situation; each displays an all-purpose message, -sufficiently non-committal, and that's it. Of course, if your game -includes a magic portal that will reveal itself only if the player lets -rip with a snatch of Wagner, you may intercept the ``Sing`` action in a -``before`` property and alter its default, pretty useless behaviour. If -not, it's "Your singing is abominable" for you. +.. Generated by autoindex +.. index:: + pair: Sing; library action + +As you have probably inferred from the previous chapters, some of the +library’s standard defined actions are less important than others in making +the game advance towards one of its conclusions. The library defines PRAY +and SING, for instance, which are of little consequence in a normal gaming +situation; each displays an all-purpose message, sufficiently +non-committal, and that's it. Of course, if your game includes a magic +portal that will reveal itself only if the player lets rip with a snatch of +Wagner, you may intercept the :act:`Sing` action in a :prop:`before` +property and alter its default, pretty useless behaviour. If not, it's +"Your singing is abominable" for you. All actions, useful or not, have a stock of messages associated with them (the messages are held in the ``english.h`` library file and listed in -:dm4:`Appendix 4 ` of the |DM4|). We have already seen one way of -altering the player character's description -- "As good looking as ever" -- -in "William Tell", but the other defaults may also be redefined to suit +:dm4:`Appendix 4 ` of the |DM4|). We have already seen one way +of altering the player character's description -- "As good looking as ever" +-- in "William Tell", but the other defaults may also be redefined to suit your tastes and circumstantial needs. -John Covarth, aka Captain Fate, could happily settle for most of these -default messages, but we deem it worthwhile to give him some customised -responses. If nothing else, this adds to the general atmosphere, a -nicety that many players regard as important. For this mission, we make -use of the ``LibraryMessages`` object. +.. index:: + pair: LibraryMessages; library object + +John Covarth, aka Captain Fate, could happily settle for most of these +default messages, but we deem it worthwhile to give him some customised +responses. If nothing else, this adds to the general atmosphere, a nicety +that many players regard as important. For this mission, we make use of +the :obj:`LibraryMessages` object. .. code-block:: inform @@ -569,38 +592,37 @@ use of the ``LibraryMessages`` object. Include "VerbLib"; -If you provide it, the ``LibraryMessages`` object must be defined -*between* the inclusion of ``Parser`` and ``VerbLib`` (it won't work -otherwise and you’ll get a compiler error). The object contains a single -property -- ``before`` -- which intercepts display of the default -messages that you want to change. An attempt to SING, for example, will -now result in "Alas! That is not one of your many superpowers" being +If you provide it, the :obj:`LibraryMessages` object must be defined +*between* the inclusion of ``Parser`` and ``VerbLib`` (it won't work +otherwise and you’ll get a compiler error). The object contains a single +property -- :prop:`before` -- which intercepts display of the default +messages that you want to change. An attempt to SING, for example, will +now result in "Alas! That is not one of your many superpowers" being displayed. -In addition to such verb-specific responses, the library defines other -messages not directly associated with an action, like the default -response when a verb is unrecognised, or if you refer to an object which -is not in scope, or indeed many other things. Most of these messages can -be accessed through the ``Miscellany entry``, which has a numbered list -of responses. The variable ``lm_n`` holds the current value of the -number of the message to be displayed, so you can change the default -with a test like this: +In addition to such verb-specific responses, the library defines other +messages not directly associated with an action, like the default response +when a verb is unrecognised, or if you refer to an object which is not in +scope, or indeed many other things. Most of these messages can be accessed +through the ``Miscellany entry``, which has a numbered list of responses. +The variable ``lm_n`` holds the current value of the number of the message +to be displayed, so you can change the default with a test like this: .. code-block:: inform if (lm_n == 39) "That's not something you need to refer to in order to SAVE the day."; -where 39 is the number for the standard message "That's not something -you need to refer to in the course of this game" -- displayed when the -player mentions a noun which is listed in a room's name property, as we -did for the ``street``. +where 39 is the number for the standard message "That's not something you +need to refer to in the course of this game" -- displayed when the player +mentions a noun which is listed in a room's name property, as we did for +the ``street``. .. note:: - Remember that when we are testing for different values of the - same variable, we can also use the switch statement. For the - Miscellany entry, the following code would work just as nicely: + Remember that when we are testing for different values of the same + variable, we can also use the switch statement. For the Miscellany + entry, the following code would work just as nicely: .. code-block:: inform @@ -622,21 +644,28 @@ did for the ``street``. "That's not something you need to refer to in order to SAVE the day."; } -Not surprisingly, the default message for self-examination: "As good -looking as ever" is a ``Miscellany`` entry -- it's number 19 -- so we -can change it through the ``LibraryMessages`` object instead of, as -before, assigning a new string to the ``player.description property``. -In our game, the description of the player character has two states: -with street clothes as John Covarth and with the super-hero outfit as -Captain Fate; hence the ``if (clothes has worn)`` clause. - -This discussion of changing our hero's appearance shows that there are -different ways of achieving the same result, which is a common situation -while designing a game. Problems may be approached from different -angles; why use one technique and not another? Usually, the context tips -the balance in favour of one solution, though it might happen that you -opt for the not-so-hot approach for some overriding reason. Don't feel -discouraged; choices like this become more common (and easier) as your +.. index:: + pair: LibraryMessages; library object + +.. Generated by autoindex +.. index:: + pair: Miscellany; library action + +Not surprisingly, the default message for self-examination: "As good +looking as ever" is a :act:`Miscellany` entry -- it's number 19 -- so we +can change it through the :obj:`LibraryMessages` object instead of, as +before, assigning a new string to the ``player.description`` property. In +our game, the description of the player character has two states: with +street clothes as John Covarth and with the super-hero outfit as Captain +Fate; hence the ``if (clothes has worn)`` clause. + +This discussion of changing our hero's appearance shows that there are +different ways of achieving the same result, which is a common situation +while designing a game. Problems may be approached from different angles; +why use one technique and not another? Usually, the context tips the +balance in favour of one solution, though it might happen that you opt for +the not-so-hot approach for some overriding reason. Don't feel +discouraged; choices like this become more common (and easier) as your experience grows. .. Ugh. Ghastly, but it does the job. @@ -650,18 +679,18 @@ experience grows. Going back to our example, an alternative approach would be to set the variable ``player.description`` in the ``Initialise`` routine (as we did with "William Tell") to the "ordinary clothes" string, and then later - change it as the need arises. It is a variable, after all, and you can + change it as the need arises. It is a variable, after all, and you can alter its value with another statement like ``player.description =`` - |WNL_LATEX| |WNL_HTML| anywhere in your code. This alternative solution + |WNL_LATEX| |WNL_HTML| anywhere in your code. This alternative solution might be better if we intended changing the description of the player - many times through the game. Since we plan to have only two states, the - ``LibraryMessages`` approach will do just fine. - -A final warning: as we explained when extending the standard verb -grammars, you *could* edit the appropriate library file and change all -the default messages, but that wouldn't be a sound practice, because -your library file will probably not be right for the next game. Use of -the ``LibraryMessages`` object is strongly advised. + many times through the game. Since we plan to have only two states, the + :obj:`LibraryMessages` approach will do just fine. + +A final warning: as we explained when extending the standard verb grammars, +you *could* edit the appropriate library file and change all the default +messages, but that wouldn't be a sound practice, because your library file +will probably not be right for the next game. Use of the +:obj:`LibraryMessages` object is strongly advised. If you're typing in the game, you'll probably want to read the brief section on :ref:`compile-as-you-go` prior to performing a test compile.