| !---------------------------------------------------------------------------! | |
| ! ! | |
| ! This file is intended as an illustration of the rather cryptic line in ! | |
| ! the Designer's Manual about using the "number" property of the compass ! | |
| ! directions to code a maze. This maze copies the "Alike_Maze" from ! | |
| ! Adventure (specifically, from Graham Nelson's Inform port thereof) and ! | |
| ! implements it with two rooms: Maze_Room and Maze_Dump, and three ! | |
| ! routines: LoadMaze, SetMaze and MoveInMaze. ! | |
| ! ! | |
| ! This method uses the "number" property to keep track of the location of ! | |
| ! objects in the maze, which has two major implications: 1. every object ! | |
| ! which the player can drop in the maze MUST have the number property ! | |
| ! defined; and 2. the number property cannot be used for anything else. ! | |
| ! The latter is avoidable by defining another property, say "maze_number," ! | |
| ! and using it instead. ! | |
| ! ! | |
| ! Although this method works fairly well, there are three caveats: ! | |
| ! 1. "Places" will list the entire maze as one room (in this case, ! | |
| ! "Standard Maze"). This may or may not be desirable. ! | |
| ! 2. "Objects" will list objects dropped in the last room visited properly, ! | |
| ! but anything in Maze_Dump will be listed as "lost." This is probably ! | |
| ! correctable. ! | |
| ! 3. This method is NOT recommended if you have any NPCs who can wander ! | |
| ! around in the maze. While you COULD keep track of each NPC's location ! | |
| ! with his or her "number" property, you'd have to code the movement rules ! | |
| ! completely differently. ! | |
| ! ! | |
| ! I don't have a great deal of experience with Inform (and in real life I ! | |
| ! use COBOL), so there may be better and easier alternatives to some of ! | |
| ! this. I welcome any and all comments, which you can e-mail to me at: ! | |
| ! blore@ibm.net. ! | |
| ! -- Steven Howard, 6/4/1996 ! | |
| !---------------------------------------------------------------------------! | |
| Switches dxs; | |
| Constant DEBUG; | |
| Constant Story "The Famous One-Room Maze"; | |
| Constant Headline "^An Interactive Labyrinth ^\ | |
| Copyright 1996 by Steven Howard, but freely usable. ^"; | |
| Include "Parser"; | |
| Include "Verblib"; | |
| !---------------------------------------------------------------------------! | |
| ! First, the routines: LoadMaze, SetMaze and MoveInMaze ! | |
| !---------------------------------------------------------------------------! | |
| [ LoadMaze i obj; | |
| for (obj = selfobj + 1: obj <= top_object: obj++) | |
| {if (obj in Maze_Room) | |
| {if (obj.&number == 0) | |
| print "*** ERROR: Can't move ", (the) obj, ". ***"; | |
| else | |
| {obj.number = Maze_Room.number; | |
| move obj to Maze_Dump;}; | |
| }; | |
| if (obj in Maze_Dump && obj.number == i) | |
| move obj to Maze_Room; | |
| }; | |
| Maze_Room.number = i; | |
| ]; | |
| !---------------------------------------------------------------------------! | |
| ! LoadMaze is called before the player moves into a new room in the ! | |
| ! maze. It moves items currently on the floor to the holding area ! | |
| ! Maze_Dump, using each object's "number" property to store its ! | |
| ! "real location". Meanwhile, it moves any objects in Maze_Dump whose ! | |
| ! number property is equal to the new room number into Maze_Room. ! | |
| ! Finally, it sets the number property of Maze_Room to the new value. ! | |
| !---------------------------------------------------------------------------! | |
| [ SetMaze ; | |
| n_obj.number=0; | |
| ne_obj.number=0; | |
| e_obj.number=0; | |
| se_obj.number=0; | |
| s_obj.number=0; | |
| sw_obj.number=0; | |
| w_obj.number=0; | |
| nw_obj.number=0; | |
| u_obj.number=0; | |
| d_obj.number=0; | |
| out_obj.number=0; | |
| switch (Maze_Room.number) { | |
| 1: {n_obj.number = 1; | |
| e_obj.number = 2; | |
| s_obj.number = 4; | |
| w_obj.number = 11; | |
| u_obj.number = 100;}; | |
| 2: {e_obj.number = 4; | |
| s_obj.number = 3; | |
| w_obj.number = 1;}; | |
| 3: {n_obj.number = 22; | |
| e_obj.number = 2; | |
| s_obj.number = 6; | |
| d_obj.number = 17;}; | |
| 4: {n_obj.number = 2; | |
| e_obj.number = 15; | |
| s_obj.number = 16; | |
| w_obj.number = 1; | |
| u_obj.number = 14; | |
| d_obj.number = 14;}; | |
| 5: {e_obj.number = 6; | |
| w_obj.number = 7;}; | |
| 6: {e_obj.number = 3; | |
| s_obj.number = 8; | |
| w_obj.number = 5; | |
| d_obj.number = 7;}; | |
| 7: {e_obj.number = 8; | |
| s_obj.number = 9; | |
| w_obj.number = 5; | |
| u_obj.number = 6;}; | |
| 8: {n_obj.number = 10; | |
| e_obj.number = 7; | |
| s_obj.number = 8; | |
| w_obj.number = 6; | |
| u_obj.number = 9; | |
| d_obj.number = 24;}; | |
| 9: {n_obj.number = 8; | |
| s_obj.number = 18; | |
| w_obj.number = 7;}; | |
| 10: {n_obj.number = 10; | |
| e_obj.number = 101; | |
| w_obj.number = 8; | |
| d_obj.number = 19;}; | |
| 11: {n_obj.number = 1; | |
| e_obj.number = 21; | |
| s_obj.number = 11; | |
| w_obj.number = 11;}; | |
| 12: {e_obj.number = 13; | |
| s_obj.number = 101; | |
| w_obj.number = 23;}; | |
| 13: {n_obj.number = 101; | |
| w_obj.number = 12; | |
| nw_obj.number = 25;}; | |
| 14: {u_obj.number = 4; | |
| d_obj.number = 4;}; | |
| 15: {w_obj.number = 4; | |
| out_obj.number = 4;}; | |
| 16: {w_obj.number = 4; | |
| out_obj.number = 4;}; | |
| 17: {u_obj.number = 3; | |
| out_obj.number = 3;}; | |
| 18: {w_obj.number = 9; | |
| out_obj.number = 9;}; | |
| 19: {u_obj.number = 10; | |
| out_obj.number = 10;}; | |
| 20: {e_obj.number = 101; | |
| out_obj.number = 101;}; | |
| 21: {w_obj.number = 11; | |
| out_obj.number = 11;}; | |
| 22: {s_obj.number = 3; | |
| out_obj.number = 3;}; | |
| 23: {e_obj.number = 12; | |
| out_obj.number = 12;}; | |
| 24: {u_obj.number = 8; | |
| out_obj.number = 8;}; | |
| 25: {se_obj.number = 13; | |
| out_obj.number = 13;}; | |
| }; | |
| ]; | |
| !---------------------------------------------------------------------------! | |
| ! SetMaze is called whenever the player enters a new room in the maze. ! | |
| ! The number property for the compass directions follow a simple code: ! | |
| ! 0 means movement in this direction is not allowed; 1 - 99 means ! | |
| ! movement in this direction leads into room 1 - 99 of the maze, as ! | |
| ! appropriate; 100 or more means movement in this direction leads out ! | |
| ! of the maze. Obviously, a gigantic maze of more than 99 rooms would ! | |
| ! require changing this scheme somewhat. ! | |
| !---------------------------------------------------------------------------! | |
| [ MoveInMaze ; | |
| if (noun.number == 0) return 0; | |
| if (noun.number == 100) return Starting_Room; | |
| if (noun.number == 101) return At_Brink_Of_Pit; | |
| return Maze_Room; | |
| ]; | |
| !---------------------------------------------------------------------------! | |
| ! MoveInMaze "translates" the numbers assigned by SetMaze. Making it ! | |
| ! a separate routine like this saves typing. ! | |
| !---------------------------------------------------------------------------! | |
| Object Starting_Room "Starting Room" | |
| with name "starting" "room" "cavern" "stone" "suspiciously" | |
| "twisty" "passage" "south", | |
| description "You are standing in a stone cavern. A \ | |
| suspiciously twisty passage leads south.", | |
| s_to Maze_Room, | |
| in_to Maze_Room, | |
| before [ ; | |
| Go: if (noun == s_obj or in_obj | |
| && Maze_Room.number ~= 1) | |
| {LoadMaze(1); | |
| rfalse;}; | |
| ]; | |
| !---------------------------------------------------------------------------! | |
| ! An "ordinary" room just outside the maze. The before rule makes sure the ! | |
| ! player enters the right room in the maze. It's not strictly necessary ! | |
| ! here, since the maze is defined with number = 1 and the only way to get ! | |
| ! here is from Room 1, but this situation is unusual. At_Brink_of_Pit, ! | |
| ! below, is an example of why this type of rule is needed. ! | |
| !---------------------------------------------------------------------------! | |
| !---------------------------------------------------------------------------! | |
| ! To help map the maze, we give the player a bunch of "things" to drop: ! | |
| !---------------------------------------------------------------------------! | |
| Nearby red_thing "red thing" | |
| with name "red" "thing", | |
| description "It's a red thing. You wouldn't understand.", | |
| number 0; | |
| Nearby blue_thing "blue thing" | |
| with name "blue" "thing", | |
| description "It's a blue thing. You wouldn't understand.", | |
| number 0; | |
| Nearby yellow_thing "yellow thing" | |
| with name "yellow" "thing", | |
| description "It's a yellow thing. You wouldn't understand.", | |
| number 0; | |
| Nearby green_thing "green thing" | |
| with name "green" "thing", | |
| description "It's a green thing. You wouldn't understand.", | |
| number 0; | |
| Nearby purple_thing "purple thing" | |
| with name "purple" "thing", | |
| description "It's a purple thing. You wouldn't understand.", | |
| number 0; | |
| Nearby orange_thing "orange thing" | |
| with name "orange" "thing", article "an", | |
| description "It's an orange thing. You wouldn't understand.", | |
| number 0; | |
| !---------------------------------------------------------------------------! | |
| ! And now, the maze itself: ! | |
| !---------------------------------------------------------------------------! | |
| Object Maze_Room "Standard Maze" | |
| with name "maze" "passage" "passages" "little" "twisty" | |
| "standard" "dead" "end", | |
| description | |
| [; | |
| if (self.number < 15) | |
| "You are in the standard maze of twisty little \ | |
| passages."; | |
| if (self.number == 25) | |
| "This is the pirate's dead end."; | |
| "You have reached a dead end.";], | |
| short_name [ ; | |
| if (action == ##Places or ##Objects) rfalse; | |
| if (self.number < 15) {print "Standard Maze"; | |
| #IFDEF DEBUG; print " (", self.number, ")";#ENDIF; | |
| rtrue}; | |
| print "Dead End"; | |
| #IFDEF DEBUG; print " (", self.number, ")";#ENDIF; | |
| rtrue; | |
| ], | |
| number 1, | |
| n_to MoveInMaze, | |
| ne_to MoveInMaze, | |
| e_to MoveInMaze, | |
| se_to MoveInMaze, | |
| s_to MoveInMaze, | |
| sw_to MoveInMaze, | |
| w_to MoveInMaze, | |
| nw_to MoveInMaze, | |
| u_to MoveInMaze, | |
| d_to MoveInMaze, | |
| out_to MoveInMaze, | |
| cant_go [; if (noun==out_obj && self.number < 15) | |
| "Easier said than done."; | |
| if (self.number > 14) | |
| "You'll have to go back the way you came."; | |
| "You can't go that way.";], | |
| before [ ; | |
| Go: if (noun.number == 0 || noun.number > 99) rfalse; | |
| if (self.number ~= noun.number) | |
| LoadMaze (noun.number); | |
| ], | |
| after [ ; | |
| Go: SetMaze(); | |
| if (self has general) <<Look>>; | |
| give self general; | |
| ]; | |
| !---------------------------------------------------------------------------! | |
| ! number holds the current room number in the maze. Rooms 1 through 14 ! | |
| ! represent the maze proper (i.e. those rooms whose description in the ! | |
| ! original is "You are in a maze of twisty little passages, all alike"). ! | |
| ! Rooms 15 through 24 are the ordinary dead ends (i.e. those rooms whose ! | |
| ! description is "You have reached a dead end" and where "out" takes you ! | |
| ! to the previous room). Room 25 is the pirate's dead end. ! | |
| ! ! | |
| ! The before rule on "Go" calls "LoadMaze" if the player is moving ! | |
| ! within the maze. ! | |
| ! ! | |
| ! Somewhat deceptively, moving within the maze also causes a "Look" ! | |
| ! action, making every room appear to have never been visited before. ! | |
| ! This could be improved by keeping track of which rooms have already ! | |
| ! been visited and only doing a <<Look>> in those which have not. ! | |
| !---------------------------------------------------------------------------! | |
| Object Maze_Dump "Maze Dump"; | |
| Nearby plaid_thing "plaid thing" | |
| with name "plaid" "thing", | |
| description "It's a plaid thing. You wouldn't understand.", | |
| number 2; | |
| Nearby treasure_chest "treasure chest" | |
| with name "strangely" "familiar" "treasure" "chest", | |
| initial "You have found the treasure chest!", | |
| description "It's strangely familiar . . .", | |
| number 25; | |
| !---------------------------------------------------------------------------! | |
| ! Maze_Dump isn't connected to any other rooms in the game. It's just a ! | |
| ! holding place for items dropped in the maze which aren't in the current ! | |
| ! room. ! | |
| ! There are two things left lying around in the maze. A "plaid thing" ! | |
| ! has been dropped in the second room, and the pirate's chest is in its ! | |
| ! expected location. ! | |
| !---------------------------------------------------------------------------! | |
| Object At_Brink_of_Pit "At Brink of Pit" | |
| with name "twisty" "passages" "passage" "maze" "guard" "rail", | |
| description "You are at the brink of a thirty-foot pit. \ | |
| A newly-installed guard rail prevents climbing down. \ | |
| Those twisty passages continue off in all directions.", | |
| d_to "The guard rail prevents it.", | |
| w_to Maze_Room, | |
| n_to Maze_Room, | |
| e_to Maze_Room, | |
| s_to Maze_Room, | |
| before [ ; | |
| Go: if (noun == s_obj && Maze_Room.number ~= 20) | |
| {LoadMaze(20); | |
| rfalse;}; | |
| if (noun == n_obj && Maze_Room.number ~= 12) | |
| {LoadMaze (12); | |
| rfalse;}; | |
| if (noun == e_obj && Maze_Room.number ~= 13) | |
| {LoadMaze (13); | |
| rfalse;}; | |
| if (noun == w_obj && Maze_Room.number ~= 10) | |
| {LoadMaze (10); | |
| rfalse;}; | |
| ]; | |
| !---------------------------------------------------------------------------! | |
| ! This illustrates the use of the before rule on "Go" to handle the case ! | |
| ! where the player leaves the maze and later enters a different room. ! | |
| !---------------------------------------------------------------------------! | |
| Nearby pit "pit" | |
| with name "brink" "of" "pit", | |
| description "It's a long way down. Luckily, the sturdy \ | |
| guard rail prevents anyone from trying to climb down.", | |
| before [ ; | |
| Climb: "The guard rail prevents it."; | |
| ], | |
| has scenery; | |
| !---------------------------------------------------------------------------! | |
| ! In Adventure the pit is an exit. Here, it's just window dressing. ! | |
| !---------------------------------------------------------------------------! | |
| Object glow_stick "glow stick" | |
| with name "glow" "stick" "luminous" "tube" "green" "fluid" | |
| "plastic" "of", | |
| description "A plastic tube of luminous green fluid.", | |
| number 0, | |
| has light; | |
| !---------------------------------------------------------------------------! | |
| ! Of course, the player needs to see. This also illustrates why it's ! | |
| ! necessary to actually move the player from Maze_Room to Maze_Room. At ! | |
| ! first thought, it seems we could accomplish the same thing by calling ! | |
| ! LoadMaze, calling SetMaze, performing a Look action and returning true ! | |
| ! in the before routine for Maze_Room. But that wouldn't handle the player ! | |
| ! dropping the only light source in the maze. ! | |
| !---------------------------------------------------------------------------! | |
| Include "Grammar"; | |
| [ Initialise; | |
| location = Starting_Room; | |
| move glow_stick to player; | |
| "^^^^^^^You've seen this maze before. Now, go find that \ | |
| pirate chest.^"; | |
| ]; | |
| end; | |
Xet Storage Details
- Size:
- 19.8 kB
- Xet hash:
- 159c0088cab703eb35e4f8e04bc77cdba6d8a200dc17c295bcf83bb4ff1a58cb
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.