X-Git-Url: https://jxself.org/git/?p=ibg.git;a=blobdiff_plain;f=chapters%2F08.rst;h=45c54d2bee6a543902e56f84a6d605aa2ed4e323;hp=5ee56f86ef5c1731be4028c3a91c5b5c1d49c4fd;hb=8009937904cf79341a9c23c9c5e7b541606bfcb6;hpb=f9eb50b5024de49b2df4b5daab471731840195d3 diff --git a/chapters/08.rst b/chapters/08.rst index 5ee56f8..45c54d2 100644 --- a/chapters/08.rst +++ b/chapters/08.rst @@ -6,28 +6,30 @@ .. epigraph:: - | *O was an oyster girl, and went about town;* - | *P was a parson, and wore a black gown.* + | |CENTER| *O was an oyster girl, and went about town;* + | |CENTER| *P was a parson, and wore a black gown.* .. only:: html .. image:: /images/picO.png :align: left -.. raw:: latex +|O|\ur game's action nears its climax in the town's central square. In +this chapter we define the square's constituent rooms and deal with +Wilhelm's approach to the hat on the pole -- does he salute it, or does he +remain proudly defiant? - \dropcap{o} - -ur game's action nears its climax in the town's central square. In this -chapter we define the square's constituent rooms and deal with Wilhelm's -approach to the hat on the pole -- does he salute it, or does he remain -proudly defiant? +.. _south-side: The south side of the square ============================ The town square, notionally one enormous open space, is represented by -three rooms. Here's the south side:: +three rooms. Here's the south side: + +.. include:: /config/typethis.rst + +:: Room south_square "South side of the square" with description @@ -67,22 +69,32 @@ It's all pretty standard stuff: just a ``Room`` and two ``Prop``\s. The players can't EXAMINE it from this room (technically, it's "not in scope"). However, since we're pretending that Wilhelm can see the whole of the square from where he's standing, we need to provide a dummy hat on a pole, -``found_in`` both this room and the north side of the square, even if it's +:prop:`found_in` both this room and the north side of the square, even if it's "too far away" for a detailed description. +.. Generated by autoindex +.. index:: + pair: Examine; library action + pair: before; library property + In fact, it's "too far away" for anything. We've replaced the standard -``before`` action for the ``Prop`` class (which permits ``Examine``, but -rejects other actions with "You don't need to worry about...") with one +:prop:`before` action for the ``Prop`` class (which permits :act:`Examine`, +but rejects other actions with "You don't need to worry about...") with one rejecting *all* actions. Since Wilhelm's hatred of the vogt's activities is central to our plot, a message saying "You don't need to worry about the hat" would be unacceptably misleading. +.. Generated by autoindex +.. index:: + pair: FireAt; library action + pair: Talk; library action + The obnoxious soldiers are also implemented very sketchily; they need to be there, but they don't do much. Their most interesting characteristic is -probably that they trap two actions -- ``FireAt`` and ``Talk`` -- which are -*not* part of the library, but instead new actions that we've defined -specially for this game. We'll talk about those actions in "Verbs, verbs, -verbs" on page 111, at which time the role of this ``before`` property will +probably that they trap two actions -- :act:`FireAt` and :act:`Talk` -- +which are *not* part of the library, but instead new actions that we've +defined specially for this game. We'll talk about those actions in +:ref:`verbs`, at which time the role of this :prop:`before` property will make more sense. The middle of the square @@ -103,10 +115,16 @@ on top. He can do three things: attempt, patience runs out, and Wilhelm is hauled off to perform his party piece. -So, there are two actions that we need to look out for: ``Salute`` (trapped -by the pole), and ``Go`` (which can be trapped by the room itself). ``Go`` -is a standard library action. ``Salute`` is one that we've devised; let's -deal with it first. Here's a first cut of the room:: +.. Generated by autoindex +.. index:: + pair: Go; library action + pair: Salute; library action + +So, there are two actions that we need to look out for: :act:`Salute` +(trapped by the pole), and :act:`Go` (which can be trapped by the room +itself). :act:`Go` is a standard library action. :act:`Salute` is one +that we've devised; let's deal with it first. Here's a first cut of the +room:: Room mid_square "Middle of the square" with description @@ -117,7 +135,11 @@ deal with it first. Here's a first cut of the room:: n_to north_square, s_to south_square; -and the pole:: +and the pole: + +.. include:: /config/typethis.rst + +:: Furniture pole "hat on a pole" mid_square with name 'wooden' 'pole' 'pine' 'hat' 'black' 'red' 'brim' 'feathers', @@ -140,19 +162,23 @@ and the pole:: The room will need some more work in a minute, but the pole object is complete (note that we've simplified matters slightly by making one object represent both the pole and the hat which it supports). It mentions a -property which we've not met before: ``has_been_saluted``. What a +property which we've not met before: :prop:`has_been_saluted`. What a remarkable coincidence: the library provides a property with a name that's exactly right for our game; surely not? -No, of course not. ``has_been_saluted`` isn't a standard library property; -it's one that we've just invented. Notice how easily we did it -- we -simply included the line:: +.. Generated by autoindex +.. index:: + pair: has_been_saluted; library property + +No, of course not. :prop:`has_been_saluted` isn't a standard library +property; it's one that we've just invented. Notice how easily we did it +-- we simply included the line:: has_been_saluted false, in the object definition and voilà, we've added our own home-made property, -and initialised it to ``false``. To switch the state of the property, we -can simply write:: +and initialised it to :const:`false`. To switch the state of the property, +we can simply write:: pole.has_been_saluted = true; pole.has_been_saluted = false; @@ -183,16 +209,16 @@ assigns a value to a variable. Compare these examples: * - ``score = 10;`` - ``score == 10;`` - * - assigns the value 10 to ``score`` - - does nothing; ``score`` is unchanged + * - assigns the value 10 to :var:`score` + - does nothing; :var:`score` is unchanged * - ``if (score == 10) ...`` - ``if (score = 10) ...`` - * - executes the next statement only if the value of ``score`` is 10 - - assigns 10 to ``score``, then always executes the next statement -- + * - executes the next statement only if the value of :var:`score` is 10 + - assigns 10 to :var:`score`, then always executes the next statement -- because ``score = 10`` evaluates to 10, which is treated as - ``true``, so the test is always ``true`` + :const:`true`, so the test is always :const:`true` Defining a new property variable which, instead of applying to every object in the game (as do the standard library properties), is specific only to a @@ -208,12 +234,12 @@ that the salute was "gratefully" received. Creating new property variables like this -- at the drop of a hat, as it were -- is the recommended approach, but it isn't the only possibility. - We briefly mention some alternative approaches in "Reading other - people's code" on page 181. + We briefly mention some alternative approaches in + :ref:`reading-other-code`. Back to the ``mid_square`` room. We've said that we need to detect Wilhelm -trying to leave this room, which we can do by trapping the ``Go`` action in -a ``before`` property. Let's sketch the coding we'll need:: +trying to leave this room, which we can do by trapping the :act:`Go` action +in a :prop:`before` property. Let's sketch the coding we'll need:: before [; Go: @@ -221,18 +247,28 @@ a ``before`` property. Let's sketch the coding we'll need:: if (noun == n_obj) { Wilhelm is trying to move north } ]; -We can easily trap the ``Go`` action, but which direction is he moving? +.. Generated by autoindex +.. index:: + pair: Go; library action + pair: s_to; library property + +We can easily trap the :act:`Go` action, but which direction is he moving? Well, it turns out that the interpreter turns a command of GO SOUTH (or -just SOUTH) into an action of ``Go`` applied to an object ``s_obj``. This -object is defined by the library; so why isn't it called just "``south``"? -Well, because we already have another kind of south, the property ``s_to`` -used to say what lies in a southerly direction when defining a room. To -avoid confusing them, ``s_to`` means "south to" and ``s_obj`` means "south -when the player types it as the object of a verb". +just SOUTH) into an action of :act:`Go` applied to an object ``s_obj``. +This object is defined by the library; so why isn't it called just +"``south``"? Well, because we already have another kind of south, the +property :prop:`s_to` used to say what lies in a southerly direction when +defining a room. To avoid confusing them, :prop:`s_to` means "south to" +and ``s_obj`` means "south when the player types it as the object of a +verb". + +.. Generated by autoindex +.. index:: + pair: noun; library variable The identity of the object which is the target of the current action is -stored in the ``noun`` variable, so we can write the statement ``if (noun -== s_obj)`` to test whether the contents of the ``noun`` variable are equal +stored in the :var:`noun` variable, so we can write the statement ``if (noun +== s_obj)`` to test whether the contents of the :var:`noun` variable are equal to the ID of the ``s_obj`` object -- and, if so, Wilhelm is trying to move south. Another similar statement tests whether he's trying to move north, and that's all that we're interested in; we can let other movements take @@ -323,16 +359,21 @@ not). In effect, we're pretending that the soldier has such a short memory, he'll completely forget Wilhelm if our hero should move away from the pole. +.. Generated by autoindex +.. index:: + pair: has_been_saluted; library property + pair: warnings_count; library property + To do all this, we've added a new property and two statements. The -property is ``warnings_count``, and its value will count how many times +property is :prop:`warnings_count`, and its value will count how many times Wilhelm has tried to go north without saluting the pole: 0 initially, 1 after his first warning, 2 after his second warning, 3 when the soldier's -patience finally runs out. The property ``warnings_count`` isn't a -standard library property; like the pole's ``has_been_saluted`` property, -it's one that we've created to meet a specific need. +patience finally runs out. The property :prop:`warnings_count` isn't a +standard library property; like the pole's :prop:`has_been_saluted` +property, it's one that we've created to meet a specific need. Our first statement is ``self.warnings_count = 0``, which resets the value -of the ``warnings_count`` property of the current object -- the +of the :prop:`warnings_count` property of the current object -- the ``mid_square`` room -- to 0. The second statement is ``pole.has_been_saluted = false``, which signifies that the pole has not be saluted. That's it: the soldier's memory is erased, and Wilhelm's actions @@ -471,15 +512,23 @@ isn't the 1, 2 or 3 you'd anticipated. Here's the remainder of the code return true; } +.. Generated by autoindex +.. index:: + pair: Go; library action + The first part is really just displaying a lot of text, made slightly messier because we're adding emphasis to the word "Herr" by using underlining (which actually comes out as *italic type* on most interpreters). Then, we make sure that Walter has the apple (just in case we didn't give it to him earlier in the game), relocate to the final room using ``PlayerTo(marketplace)``, and finally ``return true`` to tell the -interpreter that we've handled this part of the ``Go`` action ourselves. +interpreter that we've handled this part of the :act:`Go` action ourselves. And so, at long last, here's the complete code for the ``mid_square``, the -most complicated object in the whole game:: +most complicated object in the whole game: + +.. include:: /config/typethis.rst + +:: Room mid_square "Middle of the square" with description @@ -535,7 +584,11 @@ The north side of the square ============================ The only way to get here is by saluting the pole and then moving north; not -very likely, but good game design is about predicting the unpredictable. :: +very likely, but good game design is about predicting the unpredictable. + +.. include:: /config/typethis.rst + +:: Room north_square "North side of the square" with description @@ -549,14 +602,14 @@ very likely, but good game design is about predicting the unpredictable. :: ], s_to "You hardly feel like going through all that again."; -There's one new feature in this room: the value of the ``n_to`` property is +There's one new feature in this room: the value of the :prop:`n_to` property is a routine, which the interpreter runs when Wilhelm tries to exit the square northwards. All that the routine does is set the value of the library -variable ``deadflag`` to 3, print a confirmation message, and ``return +variable :var:`deadflag` to 3, print a confirmation message, and ``return true``, thus ending the action. -At this point, the interpreter notices that ``deadflag`` is no longer zero, -and terminates the game. In fact, the interpreter checks ``deadflag`` at +At this point, the interpreter notices that :var:`deadflag` is no longer zero, +and terminates the game. In fact, the interpreter checks :var:`deadflag` at the end of every turn; these are the values that it's expecting to find: * 0 -- this is the normal state; the game continues. @@ -567,16 +620,20 @@ the end of every turn; these are the values that it's expecting to find: :term:`entry point` routine called ``DeathMessage`` -- which we must provide -- where we can define our own tailored "end messages". -In this game, we never set ``deadflag`` to 1, but we do use values of 2 +In this game, we never set :var:`deadflag` to 1, but we do use values of 2 and 3. So we'd better define a ``DeathMessage`` routine to tell players -what they've done:: +what they've done: + +.. include:: /config/typethis.rst + +:: [ DeathMessage; print "You have screwed up a favourite folk story"; ]; Our game has only one customised ending, so the simple ``DeathMessage`` routine we've written is sufficient for our purposes. Were you to conceive multiple endings for a game, you could specify suitable messages by -checking for the current value of the ``deadflag`` variable:: +checking for the current value of the :var:`deadflag` variable:: [ DeathMessage; if (deadflag == 3) print "You leave Scarlett O'Hara for good"; @@ -585,7 +642,7 @@ checking for the current value of the ``deadflag`` variable:: ... ]; -Of course, you must assign the appropriate value to ``deadflag`` at the +Of course, you must assign the appropriate value to :var:`deadflag` at the point when the game arrives at each of those possible endings. We've nearly finished. In the concluding chapter of this game, we'll talk