============================= Mapping and solving example ============================= .. include:: refs.rst .. highlight:: ifm Here's a more detailed example of how to use IFM, using the example game *Ruins* to produce a full IFM map containing items and game-solving tasks. *Ruins* originally existed only in snippets throughout Graham Nelson's *Inform Designer's Manual* until Roger Firth produced a playable version of it. It serves as a good demo of IFM capabilities, since it doesn't give away any secrets from a "real" game. The source code for *Ruins* can be found bundled with the `Inform 6 sources`_. Mapping the game ================ OK, let's go. First, let's set the title for the map, which gets printed out (for example) at the top of each PostScript output page:: title "Ruins"; On starting the game, we see this: .. code-block:: transcript Days of searching, days of thirsty hacking through the briars of the forest, but at last your patience was rewarded. A discovery! RUINS An Interactive Worked Example Copyright (c) 1995 by Graham Nelson. Revisited 1998 by Roger Firth. Release 2 / Serial number 981117 / Inform v6.31 Library 6/11 S Dark Forest 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. A speckled mushroom grows out of the sodden earth, on a long stalk. Ooh, that mushroom looks interesting. Let's map out what we have so far:: room "Dark Forest" tag Dark_Forest; item "speckled mushroom" tag mushroom; Let's have a closer look at that mushroom: .. code-block:: transcript >GET SPECKLED MUSHROOM 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. You hear the distant drone of an aeroplane. >EXAMINE SNAKE A menacing, almost cartoon-like statuette of a pygmy spirit with an enormous snake around its neck. The plane is much louder, and seems to be flying very low. Terrified birds rise in screeching flocks. >GET STATUETTE Taken. 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. >LOOK Dark Forest 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. Your packing case rests here, ready for you to hold any important cultural finds you might make, for shipping back to civilisation. The roar dies away; calm returns to the forest. We've found a statuette that was hidden until we picked the mushroom:: item "statuette" tag statue hidden need mushroom; And a packing crate just fell out of the sky! Looks like that was going to happen regardless, so nothing to do, map-wise. Let's continue exploring: .. code-block:: transcript >D Square Chamber 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. Carved inscriptions crowd the walls and ceiling. We went down to get here, and have to decide on a compass direction to represent this on the map; let's choose south. This might clash with other rooms later, but we can always come back and change it if needed. We can also see some exits to other rooms, and can indicate those too, for later reference:: room "Square Chamber" tag Chamber dir s go down exit s e; item "carvings"; OK, let's have a bit of a look around. .. code-block:: transcript >EXAMINE INSCRIPTIONS The carvings cut deep into the rocks from which the chamber is built, forming swirling sinuous patterns. >EXAMINE MUSHROOM The mushroom is capped with blotches, and you aren't at all sure it's not a toadstool. >EXAMINE SUNLIGHT The shaft of sunlight glimmers motes of dust in the air, making it seem almost solid. Hmm... mushroom, sunlight. Sunlight, mushroom. Hey, let's do it! .. code-block:: transcript >PUT MUSHROOM IN SUNLIGHT 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. Well, that was unexpected. Now what? .. code-block:: transcript >EXAMINE TRAILS The insect trails seem to resemble one particular group of carvings on the wall. >EXAMINE CARVINGS 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. >PRESS CARVINGS The carvings slide inwards, revealing a small cavity. >SEARCH CAVITY In the cavity among the carvings is a huge iron key. >GET IRON KEY Taken. Aha! A key. I predict there'll be at least one door in this game. But I hope we didn't need that mushroom any more... Recording what we just did:: task "Put mushroom in sunlight" need mushroom lose it; task "Press carvings" after last; item "iron key" tag key hidden after last; Let's explore a bit more: .. code-block:: transcript >S Stooped Corridor 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. The passage is barred by a massive door of yellow stone. >EXAMINE MOSS The moss grows in rough clumps, surprisingly thick in places. Is that a hint of red hidden among all the greenery? >SEARCH MOSS Something rolls from the moss onto the ground. >LOOK Stooped Corridor 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. The passage is barred by a massive door of yellow stone. You can also see a blood-red ruby here. >GET BLOOD-RED RUBY Taken. Haha, more not-very-well-hidden goodies. And look---a door! What a surprise. Let's do some mapping:: room "Stooped Corridor" dir s; item "moss"; task "Search moss"; item "blood-red ruby" tag ruby hidden after last; OK, let's use that key! .. code-block:: transcript >UNLOCK DOOR WITH KEY You unlock the stone door. >OPEN DOOR You open the stone door. >S Lofty Shrine 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. The massive yellow stone door is open. A great stone slab of a table dominates the Shrine. On the slab altar is a flickering candle. Behind the slab, a mummified priest stands waiting, barely alive at best, impossibly venerable. How atmospheric. Continuing with mapping:: task "Unlock door with key" need key; task "Open door" after last; room "Lofty Shrine" dir s after last; item "stone slab"; item "mummified priest"; Let's see what we have here: .. code-block:: transcript >EXAMINE SLAB It's big enough to lie on, though in the circumstances that might prove to be a A Really Bad Idea. >EXAMINE PRIEST 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. Hmm... let's press him for information, then: .. code-block:: transcript >ASK PRIEST ABOUT RUBY "That is one of my people's sacred relics." >ASK PRIEST ABOUT SLAB "The King (life! propserity! happiness!) is buried deep under this Shrine, where you will never go." >ASK PRIEST ABOUT KEY "That has been lost for generations. My gratitude to anyone who returns it will be overwhelming." OK, er, let's give it back: .. code-block:: transcript >PUT KEY ON SLAB 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. >EXAMINE WAX On closer examination, the lump appears to be an old honeycomb. Looks like it might be worth something. Time for a bit of mapping:: task "Put key on slab" need key lose it give wax; item "wax" tag wax hidden; Right, let's go back and try another direction we haven't been yet: .. code-block:: transcript >N Stooped Corridor The massive yellow stone door is open. >N Square Chamber Carved inscriptions crowd the walls and ceiling. Strange trails swirl on the sandy floor. >E 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... Darkness The darkness of ages presses in on you, and you feel claustrophobic. Somewhere, tiny claws are scuttling. Crikey. Don't like the sound of that. .. code-block:: transcript >E Darkness Somewhere, tiny claws are scuttling. The scuttling draws a little nearer, and your breathing grows load and hoarse. >S Darkness Somewhere, tiny claws are scuttling. The perspiration of terror runs off your brow. The creatures are almost here! OK, this is bad. Think before acting. What did the word *SENE* mean? Hmm, maybe it's *two* words... .. code-block:: transcript >SE Darkness Somewhere, tiny claws are scuttling. >NE 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. Square Chamber Carved inscriptions crowd the walls and ceiling. Strange trails swirl on the sandy floor. Now that was close. But what have we grabbed? .. code-block:: transcript >I You are carrying: a silver bangle a lump of wax a blood-red ruby a pygmy statuette Ooh, a silver bangle. Plus, we didn't die! Let's map what we just did. We moved east from the Square Chamber into the Web of Darkness. There are essentially two of those rooms, corresponding to the two right directions to move in. Let's give the Web rooms a ``Dark`` style to show they're dark (we can define what ``Dark`` means, style-wise, later):: room "Web of Darkness" style Dark dir e from Chamber oneway; item "scuttling claws"; room "Web of Darkness" style Dark dir se oneway; item "scuttling claws"; The act of going northeast gave us a bangle (we tripped over it and picked it up). There are two ways of doing this: with an explicit movement task that puts you back in the Square Chamber, or a "dummy" task that hands you the bangle in this room without you doing anything (using ``cmd none``). Let's use the first method:: item "silver bangle" hidden tag bangle; task "Stumble over bangle" give bangle cmd "NE" goto Chamber; This second room is a one-way trip back to the Square Chamber. As it stands, that won't be apparent on the map. Let's add the connection in the most direct way:: link last to Chamber dir ne n w 2 oneway; Well, there doesn't seem to be anywhere else to go. Let's get all this stuff stashed! .. code-block:: transcript >U Dark Forest Your packing case rests here, ready for you to hold any important cultural finds you might make, for shipping back to civilisation. >PUT STATUETTE IN CASE Safely packed away. [Your score has just gone up by ten points.] >PUT BANGLE IN CASE Safely packed away. [Your score has just gone up by twenty points.] >PUT RUBY IN CASE Safely packed away. [Your score has just gone up by thirty points.] >PUT WAX IN CASE Safely packed away. The case is full, and you're feeling really homesick. Now, how to get out of here? A deep throbbing noise can be heard. [Your score has just gone up by forty points.] OK, we've stashed all the loot we found. But what's that noise? .. code-block:: transcript >WAIT Time passes. A helicopter appears, hovering overhead. >WAIT Time passes. 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! *** You have won *** In that game you scored 100 out of a possible 100, in 44 turns, earning you the rank of Master Archaeologist. Huzzah! We found all the "cultural finds" and just need to get them to the museum. [1]_ Let's add some tasks that record storing all the treasure. This happens in the starting room, so we'll just go back and put them just after the declaration for that room. We could just have a single task that requires all the treasure together and gets the full 100 points, but let's spell out the points for each one:: task "Put statuette in case" tag pack_statue need statue lose it score 10; task "Put bangle in case" tag pack_bangle need bangle lose it score 20; task "Put ruby in case" tag pack_ruby need ruby lose it score 30; task "Put wax in case" tag pack_wax need wax lose it score 40; After the treasure is stashed, we just waited for the helicopter and won the game:: task "Wait for helicopter" after pack_statue pack_bangle pack_ruby pack_wax cmd "WAIT" 2 finish; The only thing remaining to do, map-wise, is to define the display style we've used for the dark rooms. Let's just set the room background colour to be darker. Note that we could also define the ``Dark`` style by putting it in a file called :file:`Dark.ifm`, and then putting that file in a directory which is searched by IFM. That way, many maps could use the same style definition. Here's the definition:: room_colour = "gray70" in style Dark; Putting all these IFM snippets together (and indenting in my preferred style) the completed map looks like this: .. literalinclude:: examples/ruins.ifm .. highlight:: text Drawing the map =============== At any point during the mapping of the game, we could run IFM and get a map of where we've been (and where to explore next, since we marked room exits with :samp:`exit`). We can do that, for example, like this:: ifm -m -o ruins.ps ruins.ifm and using our favourite PostScript viewer to view the map. Here's what the completed *Ruins* map looks like: .. image:: images/ruins.png :align: center Listing items ============= We can see a complete item list using:: ifm -i ruins.ifm Here's what gets output with the completed *Ruins* map: .. literalinclude:: examples/ruins-items.txt Generating a solution ===================== We can get a basic walkthrough of the game using:: ifm -t ruins.ifm and it looks like this: .. literalinclude:: examples/ruins-tasks.txt As you can see, IFM's solution is slightly different from the way we played it: it stashes the statue straight away. In the actual game, doing that this early wouldn't work---the packing case hasn't been dropped yet. Unless we're trying to make a recording that will play back in Frotz_ or similar, this doesn't really matter. If we *did* want to, we'd have to fix this and create a recording file using:: ifm -t -f rec ruins.ifm This produces: .. literalinclude:: examples/ruins-rec.txt Another way to view the solution is using a *task dependency graph*. This uses IFM's :ref:`dot ` output format, like this:: ifm -t -o ruins.dot -f dot ruins.ifm dot -Tps -o ruins-graph.ps ruins.dot Here's what *Ruins* looks like: .. image:: images/ruins-graph.png :align: center Yet another way to show this is by grouping tasks together according to the rooms they occur in, by setting the ``task_graph_rooms`` variable:: ifm -t -o ruins.dot -f dot -s task_graph_rooms=true ruins.ifm dot -Tps -o ruins-graph.ps ruins.dot This is what you get: .. image:: images/ruins-graph-byroom.png :align: center Tweaking the solution ===================== If we want to wait for the packing case to appear before trying to put the statue in it, we could do it like this:: task "Wait for packing case" in Dark_Forest need statue cmd "WAIT" 2; Also, The solution as it stands is not as short as it could be: the game solver takes a trip back up to the packing case to dump two treasures and only then goes to get the bangle. This is because the stashing-treasure tasks are marginally closer at that point. What we'd like is for the solver to grab all the underground treasure *before* returning to the surface. This can be done by extending the :ref:`length ` (i.e., movement cost) of the implicit link between above-ground and below-ground:: link Chamber length 10; After adding this line, the solver behaves the way we want. .. rubric:: Footnotes .. [1] Yeah, right. You can if you want. I'm off to Ebay.