!==============================================================================! ! RUINS - an Inform example game, with answers to the exercises. !==============================================================================! ! The Inform Designer's Manual (16May97) includes various references to a ! sample game called "Ruins", which unfortunately is not supplied with the ! compiler. This file attempts to knit together several of the fragments from ! the DM into a small but complete game, intended primarily as an example for ! novices of a typical way to use Inform features, and as a starting point ! for experimentation. ! ! In order to keep the game manageably small, the following references from ! the DM have been omitted: ! parrot, low mist, chasm, pumice-stone ball, glyphs, dictionary, ! food rations, sodium lamp, cage. ! Other items have been changed as necessary for simplicity and consistency. ! ! Object definitions explicitly state the name of their parent object (if ! appropriate), rather than using the "->" construct. ! ! Once you've played the game and (hopefully) understood how it works, you ! are strongly encouraged to try modifying or extending it. For instance: ! - add the low mist in the Forest and Square_Chamber. In the DM it smells of ! broth, so perhaps you should provide a source for the smell (or just ! change the description)? [EASY] ! - implement the parrot, perhaps having it fly into the Forest once the plane ! has departed? [EASY] ! - extend the number of rooms. There's a suggestion that you could Down from ! the Shrine, or perhaps you could add a dark passage leading West from the ! Corridor? [EASY/MIDDLING] ! - if the passage is dark, perhaps a lamp would be useful? [EASY] ! - if you've got a lamp, the maze in the Web becomes much less daunting. ! So perhaps it's the lamp rather than the bangle which you find on your ! exit from the darkened Web? [EASY] ! - there are a couple of daemons in the example, but no timer. How about ! extending the Honeycomb so that if dropped it starts a timer object ! causing itself to melt unless picked up again pretty quickly? [EASY] ! - a routine called SmartCantGo prints a helpful message if you try to move ! in an illegal direction. The routine, not in the standard library, is ! commonly Included from a separate file. Download the file from: ! ftp://ftp.gmd.de/if-archive/infocom/compilers/inform6/library/contributions/ ! [EASY] ! - the DM is a bit unclear about the role(!) of the pumice-stone ball, but ! it seems to need pushing into the chasm. Maybe it blocks the gap and ! allows you to cross to the other side (in order to reach the bangle)? ! Maybe there's more to moving it than just one push? [MIDDLING/TRICKY] ! - finally, many games accept an XYZZY command (in tribute to the magic word ! in the original Adventure). Implement such a verb which transports the ! player to At_End_of_Road for one turn, then restores the original ! location (you can copy the room description from Advent.inf). [MIDDLING] ! ! You can find another version of this game, without answers to these ! exercises, in the file Ruins.inf. ! ! Of course, it isn't worth spending too long on Ruins, since it's only a ! somewhat dull and well-visited example. As soon as you start to feel ! comfortable with the way that an Inform game is constructed... ! ! ...have a go at writing one of your own. Good luck! !==============================================================================! ! Every game needs a Story and Headline, and must include parser and verblib. ! As DM 7 except: constants MANUAL_PRONOUNS and MAX_SCORE defined (the former ! is in the Library 6/7 Release Notes, not the DM). Also specified values for ! Release and Serial, but only to aid in identifying any variants in this file ! over time; normally, you'd omit these two lines and use Inform's defaults. ! Constant Story "RUINS"; Constant Headline "^An Interactive Worked Example^ Copyright (c) 1995 by Graham Nelson.^ Revisited 1998 by Roger Firth.^"; Release 4; Serial "981127"; !!!!Constant MANUAL_PRONOUNS; ! <-- Causes compilation warning; ignore... Constant MAX_SCORE 100; Include "parser"; Include "verblib"; !Include "SmartCantGo"; !! !==============================================================================! ! Every game needs an Initialise routine, whose primary role is to set the ! player's location (i.e. you) at the start of the game. ! As DM 7 and 19 except: StartDaemon() call added, no TitlePage(). ! [ Initialise; location = Forest; thedark.description = "The darkness of ages presses in on you, and you feel claustrophobic."; move Bangle to Rocky_Alcove; !! StartDaemon(Packing_Case); "^^^^^Days of searching, days of thirsty hacking through the briars of the forest, but at last your patience was rewarded. A discovery!^"; ]; !==============================================================================! ! As DM 20. PrintRank, if defined, is called when printing the score. ! [ PrintRank; print ", earning you the rank of "; switch (score) { 0 to 9: "humble rainforest Tourist."; 10 to 39: "Investigator."; 40 to 69: "Acquisitor."; 70 to 99: "Archaeologist."; 100: "Master Archaeologist."; } ]; !==============================================================================! ! As DM 11 except: daemon added, to bring the immovable crate at the start, ! and take it (and you) away at the end. ! Object Packing_Case "packing case" with name 'packing' 'case' 'crate' 'box' 'strongbox', initial "Your packing case rests here, ready for you to hold any important cultural finds you might make, for shipping back to civilisation.", description "A stout wooden crate, only slightly battered by its fall through the branches.", before [; PushDir, Remove, Take: "The case is too heavy to bother moving, as long as your expedition is still incomplete. It'll probably have to be taken out by helicopter."; ], number 0, ! <-- used by the daemon daemon [; switch (++self.number) { !-- Start of game 1: "^You hear the distant drone of an aeroplane."; 2: "^The plane is much louder, and seems to be flying very low. Terrified birds rise in screeching flocks."; 3: move self to Forest; if (location == Forest) "^You involuntarily crouch as the plane flies directly overhead, seemingly only inches above the treetops. With a loud thump, something drops heavily to the ground."; "^Even underground, the engine roar is deafening. Then there's a dull thump overhead and a little dust falls from the ceiling."; 4: StopDaemon(self); move Parrot to Forest; !! if (location == Forest) !! "^The roar dies away; calm returns to the forest. A brightly-coloured parrot alights on a nearby branch."; !! "^The roar dies away."; !! !-- End of game 5: remove Parrot; !! "^A deep throbbing noise can be heard. The parrot flies off in alarm."; !! 6: "^A helicopter appears, hovering overhead."; 7: StopDaemon(self); remove self; deadflag = 2; ! <-- You win! "^The helicopter lowers a rope; you tie it around the packing case, which is hauled up into the air, then a rope ladder comes dangling down. With one last look around the clearing, you climb the ladder into the waiting craft. Back to civilisation, and a decent pint of Brakspear's!"; } ], has container open openable static; !==============================================================================! ! As DM 8 except: started endgame processing when all treasure has been ! found. Added Bangle and Ruby treasures. "Undiscovered" is useful when ! ensuring that treasures can't be found twice. ! Class Treasure with cultural_value 10, before [; Remove, Take: if (self in Packing_Case) "Unpacking such a priceless artifact had best wait until the Metropolitan Museum can do it."; ], after [; Insert: if (second == Packing_Case) { parrot.squawk("Thief"); !! score = score + self.cultural_value; print "Safely packed away.^"; } if (score == MAX_SCORE) { StartDaemon(Packing_Case); "^The case is full, and you're feeling really homesick. Now, how to get out of here?"; } rtrue; ! <-- print nothing further ]; Object Undiscovered "hidden treasure room" with description "How the heck did you get here!?."; Treasure Statuette "pygmy statuette" Undiscovered with name 'pygmy' 'statuette' 'statue' 'mayan' 'snake' 'spirit', description "A menacing, almost cartoon-like statuette of a pygmy spirit with an enormous snake around its neck."; Treasure Bangle "silver bangle" Undiscovered with name 'silver' 'bangle' 'bracelet' 'ring', cultural_value 20, description "An intricately chased piece of jewellery."; Treasure Ruby "blood-red ruby" Undiscovered with name 'blood' 'red' 'blood-red' 'ruby' 'stone' 'jewel', cultural_value 30, description "A vivid red jewel, as large as a hen's egg."; Treasure Honeycomb "lump of wax" Undiscovered with name 'ancient' 'honeycomb' 'old' 'honey' 'comb' 'wax' 'lump', cultural_value 40, description "On closer examination, the lump appears to be an old honeycomb.", after [; Eat: "Perhaps the most expensive meal of your life. The honey tastes odd, perhaps because it was used to store the entrails of the king buried here, but still like honey."; Drop: !! StartTimer(self, 2); !! "The honeycomb immediately starts to soften."; !! Take: !! StopTimer(self); !! "The wax, though very soft, still forms a honeycomb."; !! ], time_left 0, !! time_out [; !! if (self in location) !! print "The honeycomb suddenly turns to liquid wax, spreads to a puddle and immediately vapourises.^"; !! remove self; !! ], !! has edible; !==============================================================================! ! Not in the DM as such, but useful (a) to distinguish room definitions from ! those of ordinary objects in the file, and (b) to provide light everywhere ! (unless overruled). See DM 3.8. ! Class Room ! with cant_go [; SmartCantGo(); ], !! has light; !==============================================================================! ! As DM 7 and 10. ! Room Forest "Dark Forest" with name 'forest' 'jungle' 'clearing' 'olive' 'tree' 'trees' 'midges', description "In this tiny clearing, the pine-needle carpet is broken by stone-cut steps leading down into the darkness. Dark olive trees crowd in on all sides, the air steams with warm recent rain, midges hang in the air.", d_to Stone_Steps, u_to "The trees are spiny and you'd cut your hands to ribbons trying to climb them.", after [; Go: parrot.squawk("Where you been?"); ], !! cant_go "The rainforest-jungle is dense, and you haven't hacked through it for days to abandon your discovery now. Really, you need a good few artifacts to take back to civilisation before you can justify giving up the expedition."; !==============================================================================! ! As DM 7 and 8 except: added discovery of Statuette on picking the ! mushroom. ! Object Mushroom "speckled mushroom" Forest with name 'speckled' 'mushroom' 'fungus' 'toadstool', initial "A speckled mushroom grows out of the sodden earth, on a long stalk.", description "The mushroom is capped with blotches, and you aren't at all sure it's not a toadstool.", before [; Eat: if (random(100) > 30) "You nibble at one corner, but the curious taste repels you."; deadflag = 1; ! <-- You die! "The tiniest nibble is enough. It was a toadstool, and a poisoned one at that!"; ], after [; Drop: parrot.squawk("Who's a good boy?"); !! "The mushroom drops to the ground, battered slightly."; Take: parrot.squawk("Nasty mushroom"); !! if (self has general) "You pick up the slowly-disintegrating mushroom."; give self general; move Statuette to location; "You stoop to pick the mushroom, neatly cleaving its thin stalk. As you straighten up, you notice what looks like a snake in the grass."; ], has edible; !==============================================================================! ! As DM 7 and 8 except: replaced "first feet" by cobwebs. ! Object Stone_Steps "stone-cut steps" Forest with name 'stone' 'stone-cut' 'steps' 'stairs' 'cobwebs', description [; print "The cracked and worn steps descend into a dim chamber. "; if (Square_Chamber has visited) "The filmy cobwebs which once spanned the entrance now hang in tatters."; else "Cobwebs form a flimsy barrier, unlikely to impede your descent."; ], door_to Square_Chamber, door_dir d_to, has door open scenery; !==============================================================================! ! As DM 10 except: added examination of floor, word on east lintel, ! insect trails when mushroom bursts. ! Room Square_Chamber "Square Chamber" with name 'square' 'chamber' 'sand' 'dust' 'lintel' 'lintels' 'lintelled' 'east' 'south' 'doorways' 'doors' 'steps', description "A sunken, gloomy stone chamber, ten yards across, whose floor is covered with fine sandy dust. A shaft of sunlight cuts in from the steps above, giving the chamber a diffuse light, but in the shadows low lintelled doorways to east and south lead into the deeper darkness of the Temple.", before [; Drop: if (noun == mushroom) <>; Examine: if (noun == d_obj) { if (Trails in location) <>; "Only your own footprints disturb the dust."; } Go: if (noun == e_obj) { print "As you move into the eastern shadows, you seem to glimpse the word SENE scratched on the lintel, but before you can stop to inspect it more closely, you find yourself in...^"; rfalse; ! <-- continue with the regular action } Insert: if ((noun == Mushroom) && (second == Sunlight)) { remove Mushroom; move Trails to location; "You drop the mushroom on the floor, in the glare of the shaft of sunlight. It bubbles obscenely, distends and then bursts into a hundred tiny insects which run for the darkness in every direction, leaving strange trails in the sandy floor. No trace of fungus remain."; } ], u_to Forest, e_to Inner_Web, s_to Corridor; !==============================================================================! ! As DM 10. ! Object Sunlight "shaft of sunlight" Square_Chamber with name 'shaft' 'of' 'sunlight' 'sun' 'light' 'beam' 'sunbeam' 'ray' 'rays' 'sun^s', description "The shaft of sunlight glimmers motes of dust in the air, making it seem almost solid.", before [; Examine, Search: ; default: "It's only an insubstantial shaft of sunlight."; ], has scenery; !==============================================================================! ! Not in the DM as such, but useful because employed twice. It seemed easier ! to have two sets of carvings rather just one plus a lot of if... tests. ! See DM 3.8. ! Class Carved with name 'carved' 'inscription' 'inscriptions' 'carving' 'carvings' 'group' 'of', initial "Carved inscriptions crowd the walls and ceiling.", has container open pluralname static; !==============================================================================! ! As DM 10 except: changed to include insect trails suggesting a carving, ! and pressable carving which reveals cavity. ! Carved Carvings "carved inscriptions" Square_Chamber with description [; print "The carvings cut deep into the rocks from which the chamber is built, forming swirling sinuous patterns."; if (cavity in self) print " In the middle of one wall, a small cavity can be seen."; new_line; ], before [; Push: "Pressing the carved rock walls at random is unlikely to be revealing."; Touch: "The carvings are warm and smooth to the touch."; ]; Carved Other_Carvings "carved inscriptions" with description "You stare at a group of carvings in the middle of one wall, uncannily resembling the insects' trail left in the sand, and feel your hand reaching out in that direction.", before [; Push: remove Other_Carvings; move Carvings to location; move Cavity to Carvings; "The carvings slide inwards, revealing a small cavity."; Touch: "The carvings seems to shift slightly under your hand. Perhaps with a little more pressure...?"; ]; Object Cavity "cavity among the carvings" with name 'cavity' 'hole' 'deep' 'gloomy', description "The cavity, a few inches across, is deep and gloomy.", has container open static; Object Trails "trails in the sand" with name 'trail' 'trails' 'sand' 'sandy' 'pattern' 'insect' 'insects', initial "Strange trails swirl on the sandy floor.", description [; if (self has general) { remove Carvings; move Other_Carvings to location; give self ~general; } "The insect trails seem to resemble one particular group of carvings on the wall."; ], has general pluralname static; !==============================================================================! ! A Web room is implied at DM 10, but not defined. Here, it's implemented ! as a simple dark maze of two rooms, once of which is home to the ! scuttling claws described in Example 37. The Sodium_Lamp is here. ! Class Maze class Room, with name 'dark' 'darkness' 'web', description "Gloomy passages lead in all directions.", before [; Go: give self ~visited; ], cant_go "Blundering around in the gloom, it's impossible to tell which direction is which.", has ~light; Maze Inner_Web "Web of Darkness" with se_to Outer_Web, ne_to Inner_Web, n_to Inner_Web, s_to Inner_Web, e_to Inner_Web, w_to Inner_Web, nw_to Inner_Web, sw_to Inner_Web, u_to Inner_Web, d_to Inner_Web; Maze Outer_Web "Web of Darkness" with se_to Outer_Web, ne_to Square_Chamber, n_to Inner_Web, s_to Inner_Web, e_to Inner_Web, w_to Inner_Web, nw_to Inner_Web, sw_to Inner_Web, u_to Inner_Web, d_to Inner_Web, before [; Go: if ((noun == ne_obj) && (Sodium_Lamp in Undiscovered)) { !! move Sodium_Lamp to player; !! print "Sensing a slight draught you move in that direction, stumbling over something lying on the ground in the dark. Almost inadvertently you grab it before gratefully emerging into the gloomy chamber.^"; rfalse; ! <-- continue with the regular action } ]; !==============================================================================! ! As DM Ex.37 except: daemon runs only in the Inner_Web room. ! Object Tiny_Claws "sound of tiny claws" thedark with name 'tiny' 'claws' 'sound' 'of' 'scuttling' 'scuttle' 'things' 'creatures' 'insects' 'monsters', article "the", initial "Somewhere, tiny claws are scuttling.", description "Without a light, you'll never see anything here!", before [; Attack: "They easily avoid your flailing about in the dark."; Listen: "How intelligent they sound, for mere insects."; Smell: "You can smell only your own fear."; Taste, Touch: "You wouldn't want to. Really."; default: "The creatures evade you, chittering."; ], number 0, ! <-- used by the daemon each_turn [; StartDaemon(self); ], daemon [; if (real_location ~= Inner_Web) { ! location just has "thedark" self.number = 0; StopDaemon(self); rtrue; ! <-- ? } switch(++self.number) { 1: "^The scuttling draws a little nearer, and your breathing grows load and hoarse."; 2: "^The perspiration of terror runs off your brow. The creatures are almost here!"; 3: "^You feel a tickling at your extremities and kick outward, shaking something chitinous off. Their sound alone is a menacing rasp."; 4: deadflag = 1; ! <-- You die! "^Suddenly there is a tiny pain, of a hypodermic-sharp fang at your calf. Almost at once your limbs go into spasm, your shoulders and knee-joints lock, your tongue swells..."; } ]; !==============================================================================! ! As DM 12 except: added the moss concealing the Ruby. ! Room Corridor "Stooped Corridor" with name 'low' 'stooped' 'corridor', description "A low, square-cut corridor, running north to south, stooping over you. Patches of moss emit a faint green fluorescent glow, just enough that you can see your surroundings.", n_to Square_Chamber, s_to Stone_Door, w_to Junction, !! has ; Object Moss "mossy patches" Corridor with name 'moss' 'mossy' 'patches' 'green' 'fluorescent' 'glow' 'clumps', description [; if (Ruby in Undiscovered) "The moss grows in rough clumps, surprisingly thick in places. Is that a hint of red hidden among all the greenery?"; "The moss, now somewhat raggy, grows in rough clumps."; ], before [; Search: if (Ruby in Undiscovered) { move Ruby to location; "Something rolls from the moss onto the ground."; } ], has pluralname scenery; !==============================================================================! ! As DM 12. The key isn't actually defined in the DM. ! Object Stone_Door "stone door" with name 'stone' 'door' 'big' 'massive' 'yellow', description "It's just a big stone door.", when_closed "The passage is barred by a massive door of yellow stone.", when_open "The massive yellow stone door is open.", door_to [; if (location == Corridor) return Shrine; return Corridor; ], door_dir [; if (location == Corridor) return s_to; return n_to; ], with_key Stone_Key, found_in Corridor Shrine, has door lockable locked openable static; Object Stone_Key "huge iron key" Cavity with name 'huge' 'iron' 'key', description "It must be a pretty big door to need a key like this."; !==============================================================================! ! A Shrine room is implied at DM 10, but not defined. ! Room Shrine "Lofty Shrine" with name 'lofty' 'shrine' 'haze' 'hazy' 'craggy' 'walls' 'quartz', description "For an underground chamber, the Shrine is remarkably high, though its upper half is hazy and difficult to see clearly. The craggy walls are polished natural rock, in which tiny flecks of quartz catch the light of the flickering candle.", n_to Stone_Door; !==============================================================================! ! As DM 14 except: added processing of objects placed on the altar. ! Object Stone_Table "slab altar" Shrine with name 'stone' 'table' 'slab' 'altar' 'great', initial "A great stone slab of a table dominates the Shrine.", description "It's big enough to lie on, though in the circumstances that might prove to be a A Really Bad Idea.", after [; Enter: deadflag = 1; ! <-- You die! "With astonishing speed, the horror-struck priest plucks a bronze dagger from his tattered robe, and stabs you in your sacrilegious heart."; Receive: remove noun; switch (noun) { Stone_Key: move Honeycomb to player; "His eyes dimly agleam with gratitude, the priest takes the key and conceals it among his rags. Then, lifting the candle, he carefully detaches a large lump of the mottled wax, and gives it to you."; Honeycomb: move Honeycomb to player; "~For returning the key, that is yours to keep.~"; } print "The priest takes ", (the) noun, " and conceals it among his rags.^"; rtrue; ! <-- print nothing further ], has enterable supporter static; !==============================================================================! ! Not in the DM as such, but added to provide light, and as a source for ! the Honeycomb. ! Object Candle "flickering candle" Stone_Table with name 'flickering' 'candle' 'flame', initial "A flickering candle at one end of the slab casts grotesque shadows on the walls.", description "The candle is little more than a crudely moulded lump of wax. Its texture is vaguely crystalline, with small fragments embedded within.", has static; !==============================================================================! ! As DM 16 except: the priest deal in objects, not the dictionary. ! Object Priest "mummified priest" Shrine with name 'mummified' 'priest' 'old' 'ancient' 'dessicated', initial "Behind the slab, a mummified priest stands waiting, barely alive at best, impossibly venerable.", description "He is dessicated and hangs together only by will-power. Though his first language is presumably local Mayan, you have the curious instinct that he will understand your speech.", life [; Answer: switch (noun) { 'hello', 'hi', 'bye', 'goodbye', 'good-bye', 'cheerio', 'thanks', 'thank', 'thankyou', 'you', 'cheers', 'ta': "Silently, carefully, the priest nods his head."; } "The priest coughs, and almost falls apart."; Ask: switch (second) { 'king', 'tomb', 'shrine', 'temple', 'altar', 'slab': "~The King (life! propserity! !happiness!) is buried deep under this Shrine, where you will never go.~"; 'silver', 'bangle', 'bracelet', 'ring', 'blood', 'red', 'blood-red', 'ruby', 'stone', 'jewel', 'pygmy', 'statuette', 'statue', 'mayan', 'snake', 'spirit': "~That is one of my people's sacred relics.~"; 'ancient', 'honeycomb', 'old', 'honey', 'comb', 'wax', 'lump': "~That is the most sacred of all my people's relics.~"; 'huge', 'iron', 'key': if (parent(Stone_Key) == nothing) "~Now my people will be able to visit the Shrine.~"; "~That has been lost for generations. My gratitude to anyone who returns it will be overwhelming.~"; } "~You must find your own answer.~"; Attack, Kiss: remove self; "The priest desiccates away into dust until nothing remains, not a breeze or a bone."; Give, Show: switch (noun) { Bangle, Ruby, Statuette: "~I would be grateful if you placed that before me.~"; Honeycomb: "~For returning the key, that is yours to keep.~"; Stone_Key: "~I would be profoundly grateful if you placed that before me.~"; } "The priest is indifferent to earthly things."; Tell: "The priest has no interest in your sordid life."; ThrowAt: move noun to location; <>; ], orders [; Go: "~I must not leave the Shrine.~"; NotUnderstood: switch (noun) { 'hello', 'hi', 'bye', 'goodbye', 'good-bye', 'cheerio', 'thanks', 'thank', 'thankyou', 'you', 'cheers', 'ta': "Silently, carefully, the priest nods his head."; } "~You speak in riddles~"; default: "~It is not your orders that I serve.~"; ], has animate; !==============================================================================! ! ANSWERS TO EXERCISES !==============================================================================! ! Exercise: low mist ! Object Low_Mist "low mist" with name 'low' 'swirling' 'mist', initial "A low mist swirls about your feet.", description "The mist smells slightly of rotting vegetation.", found_in Forest Square_chamber, before [; Examine, Search: ; Smell: <>; default: "The mist is too insubstantial."; ], has static; !==============================================================================! ! Exercise: parrot ! Object Parrot "red-tailed parrot" with name 'red' 'tailed' 'red-tailed' 'parrot' 'bird', description "Beautiful plumage.", squawk [ utterance; if (self in location) print "The parrot squawks, ~", (string) utterance, "! ", (string) utterance, "!~^"; ], has animate; !==============================================================================! ! Exercise: lamp ! Object Sodium_Lamp "sodium lamp" Undiscovered with name 'sodium' 'lamp' 'light' 'lantern', describe [; if (self has on) "The lamp is burning brightly."; "The lamp isn't lit."; ], battery_power 40, before [; Burn: <>; Examine: print "It is a heavy-duty archaeologist's lamp, "; if (self hasnt on) "currently off."; if (self.battery_power < 10) "glowing a dim yellow."; "blazing with brilliant yellow light."; ], after [; SwitchOff: give self ~light; SwitchOn: give self light; ], has switchable; !==============================================================================! ! Exercise: five rooms west of the Corridor ! Room Junction "Junction between passages" with name 'junction', description "A rough-hewn circular passage from the south forks to the northwest and northeast. A narrower passage leads east.", e_to Corridor, nw_to Northwest_Passage, ne_to Northeast_Passage, s_to South_Passage, has ~light; Room Northwest_Passage "North west passage" with name 'north' 'west' 'northwest' 'nw' 'passage', description "The passage ends abruptly at a rocky wall. In the far east corner, you can just see a narrow crack.", before [; Go: if (Huge_Ball in location) { if ((noun == e_obj && self hasnt general) || (noun == s_obj && self has general)) "The ball almost fills the passage - you can't get past."; } if (noun == e_obj) { give Northeast_Passage general; print "It's tight, but you just squeeze through.^"; } ], s_to Junction, e_to Narrow_Crack, has ~general ~light; Room Northeast_Passage "North east passage" with name 'north' 'east' 'northeast' 'ne' 'passage', description "The passage ends abruptly at a rocky wall. In the far west corner, you can just see a narrow crack.", before [; Go: if (Huge_Ball in location) { if ((noun == w_obj && self hasnt general) || (noun == s_obj && self has general)) "The ball almost fills the passage - you can't get past."; } if (noun == w_obj) { give Northwest_Passage general; print "It's tight, but you just squeeze through.^"; } ], s_to Junction, w_to Narrow_Crack, has ~general ~light; Object Narrow_Crack "narrow crack" with name 'narrow' 'crack', description "Not much more than a fault in the rock, but it might just be passable.", door_to [; if (location == Northwest_Passage) return Northeast_Passage; return Northwest_Passage; ], door_dir [; if (location == Northwest_Passage) return e_to; return w_to; ], found_in Northwest_Passage Northeast_passage, has door open scenery; Room South_Passage "Southerly passage" with name 'south' 'passage', description [; print "The passage ends abruptly at a narrow ledge, where a bottomless chasm opens at your feet. "; if (Huge_Ball in Chasm) print "The pumice-stone ball is wedged in the gap, forming a precarious bridge to the cave on the southern side."; else print "To the east and west, the narrow ledge fades to nothing. There's a small cave in the opposite wall, but it's too far away to reach."; if (Bangle in Rocky_Alcove) " In the cave, something faintly gleams."; ""; ], n_to Junction, s_to [; if (Huge_Ball in Chasm) return Rocky_Alcove; return nothing; ], cant_go [; if (noun == s_obj) "The chasm presents an impossible gap."; if (Huge_Ball in Chasm) "You can only go north or (gulp) south."; "The only safe way is back to the north."; ], has ~light; Room Rocky_Alcove "Rocky alcove" with name 'south' 'alcove' 'cave' 'rocky', description "This little cave is just a rough excavation in the wall above the chasm; you can only go back the way that you came.", n_to South_Passage, has ~light; !==============================================================================! ! Exercise: ball and chasm ! Object Huge_Ball "huge pumice-stone ball" Junction with name 'huge' 'pumice' 'stone' 'pumice-stone' 'ball', initial "A huge pumice-stone ball rests here, nearly filling the room.", description "A good eight feet across, though fairly lightweight.", before [; Pull, Push, Turn: "With a firm sense of direction, you could probably push it ahead of you."; PushDir: if (location == Junction) switch (second) { nw_obj: give Northwest_Passage ~general; ne_obj: give Northeast_Passage ~general; e_obj: "The corridor entrance is but seven feet across."; s_obj: if (self has general) { print "Now that it's got started, the ball rolls easily. You pause for breath.^"; move Huge_Ball to Chasm; move Bangle to Rocky_Alcove; rtrue; } else "The ball rocks slightly, but won't start moving."; } if ((location == Northwest_Passage && second == e_obj) || (location == Northeast_Passage && second == w_obj)) "Get real - the crack's barely a foot wide."; if ((location == Northwest_Passage or Northeast_Passage) && (location hasnt general) && (second == s_obj)) "You need to be behind the ball to do that."; AllowPushDir(); rtrue; Remove, Take: "There's a lot of stone in an eight-foot sphere."; ], after [; PushDir: if (second == s_obj) { give self general; StartTimer(self, 1); "The ball rolls away; you follow close behind."; } if (second == nw_obj or ne_obj) "You strain to push the ball along the passage."; ], time_left 0, time_out [; give self ~general; ], has ~general static; Object Chasm "horrifying chasm" with name 'chasm' 'pit' 'depths' 'horrifying' 'bottomless' 'depths', react_before [; Go: if (noun == d_obj) <>; Jump: <>; ], before [; Enter: deadflag = 1; ! <-- you die! "You plummet through the silent voids of darkness."; ], after [; Receive: remove noun; print_ret (The) noun, " tumbles silently into the darkness of the chasm."; Search: "The chasm is deep and murky."; ], found_in South_Passage Rocky_Alcove, has container open scenery; !==============================================================================! ! Exercise: XYZZY ! Room At_End_Of_Road "At End Of Road" with name 'road' 'street' 'path' 'forest' 'stream' 'building' 'gully', description "You are standing at the end of a road before a small brick building. Around you is a forest. A small stream flows out of the building and down a gully.", before [; Examine, Look: ; default: "There'll be time for that later. Your immediate concern is, where on earth are you?."; ], original_location 0, time_left 0, time_out [; print "^Before you can get your bearings, the landscape swirls again and you're back in...^"; PlayerTo(self.original_location); ]; [ XyzzySub; print "Your surroundings swirl before you in a painful blur. Instinctively, you close your eyes. When you cautiously re-open them, the Ruins have gone...^"; At_End_Of_Road.original_location = location; StartTimer(At_End_Of_Road, 1); PlayerTo(At_End_Of_Road); ]; !==============================================================================! ! END OF ANSWERS TO EXERCISES !==============================================================================! ! Every game needs to include the Grammar. ! Include "grammar"; !==============================================================================! ! Added to enable you to "pick" the mushroom (as well as the usual "take", ! "get", "pick up", etc). See DM 26. ! Extend "pick" * edible -> Take; Verb "xyzzy" * -> Xyzzy; !! !==============================================================================!