home *** CD-ROM | disk | FTP | other *** search
/ Amiga MA Magazine 1998 #7 / amigamamagazinepolishissue1998.iso / rozrywka / rpg / amigamud / src / proving / trollmaze.m < prev   
Text File  |  1997-05-31  |  26KB  |  983 lines

  1. /*
  2.  * Amiga MUD
  3.  *
  4.  * Copyright (c) 1997 by Chris Gray
  5.  */
  6.  
  7. /*
  8.  * trollMaze.m - the 3D maze area
  9.  */
  10.  
  11. define tp_proving tp_trollMaze CreateTable()$
  12. use tp_trollMaze
  13.  
  14. define tp_trollMaze p_pHasShovel CreateBoolProp()$
  15. define tp_trollMaze p_pMazeX CreateIntProp()$
  16. define tp_trollMaze p_pMazeY CreateIntProp()$
  17. define tp_trollMaze p_pMazeZ CreateIntProp()$
  18. define tp_trollMaze MAZE_MAX_X 15$
  19. define tp_trollMaze MAZE_MAX_Y 9$
  20. define tp_trollMaze MAZE_MAX_Z 9$
  21. define tp_trollMaze MAZE_ENTER_X 8$
  22. define tp_trollMaze MAZE_ENTER_Y 9$
  23. define tp_trollMaze MAZE_ENTER_Z 5$
  24. define tp_trollMaze MAZE_GOAL_X  11$
  25. define tp_trollMaze MAZE_GOAL_Y  3$
  26. define tp_trollMaze MAZE_GOAL_Z  5$
  27. define tp_trollMaze p_rLayerList CreateThingListProp()$
  28. define tp_trollMaze p_rLayer CreateIntListProp()$
  29. define tp_trollMaze MAZE_OPEN     0b00$
  30. define tp_trollMaze MAZE_NORMAL  0b01$
  31. define tp_trollMaze MAZE_BLOCK     0b10$
  32. define tp_trollMaze p_oCurrentUser CreateThingProp()$
  33.  
  34. define tp_trollMaze r_shovelChamber CreateThing(r_provingCave)$
  35. SetupRoomDP(r_shovelChamber, "in a small chamber", "")$
  36. AutoGraphics(r_shovelChamber, AutoOpenRoom)$
  37. Connect(r_doorsExit, r_shovelChamber, D_NORTH)$
  38. r_shovelChamber@p_rNoGenerateMonsters := true$
  39. r_shovelChamber@p_Image := "Proving/shovelRoom"$
  40.  
  41. define tp_trollMaze o_trollShovel CreateThing(nil)$
  42. SetupObject(o_trollShovel, r_shovelChamber,
  43.     "Shovel;Troll,King's.shovel;troll's,troll,king's,king",
  44.     "The shovel is the same size and shape as a normal garden shovel, but it "
  45.     "seems to be made of silver or some other shiny, whitish metal. There is "
  46.     "a faint greenish glow surrounding it.")$
  47.  
  48. define tp_trollMaze r_trollMaze CreateThing(nil)$
  49. SetupRoomD(r_trollMaze, "", "")$
  50. HConnect(r_shovelChamber, r_trollMaze, D_NORTH)$
  51. Scenery(r_trollMaze, "chasm.rock.cavity")$
  52. r_trollMaze@p_rHintString := "Explore carefully - there is a route!"$
  53.  
  54. define tp_trollMaze proc mazeDropCheck(thing what)status:
  55.     Print("You can't drop things here.\n");
  56.     fail
  57. corp;
  58. AddRoomDropChecker(r_trollMaze, mazeDropCheck, false)$
  59.  
  60. define tp_trollMaze o_drawBridge CreateThing(nil)$
  61. FakeObject(o_drawBridge, r_trollMaze,
  62.     "bridge;wooden,draw.drawbridge;wooden.draw-bridge;wooden", "")$
  63. o_drawBridge@p_oState := 0$
  64. define tp_trollMaze proc drawBridgeDesc()string:
  65.     thing me;
  66.  
  67.     me := Me();
  68.     if me@p_pMazeZ = MAZE_GOAL_Z and me@p_pMazeY = MAZE_GOAL_Y + 3 and
  69.     me@p_pMazeX = MAZE_GOAL_X
  70.     then
  71.     "The drawbridge is quite old, but still in good condition. "
  72.     "It is currently " +
  73.     if o_drawBridge@p_oState = 0 then
  74.         "drawn up on the far side of the chasm."
  75.     else
  76.         "lowered into position across the chasm."
  77.     fi
  78.     else
  79.     "There is no drawbridge here."
  80.     fi
  81. corp;
  82. o_drawBridge@p_oDescAction := drawBridgeDesc$
  83.  
  84. define tp_trollMaze proc mazeNotify()void:
  85.  
  86.     Print("\n* You were in the troll maze when the database was last backed "
  87.     "up. You have been moved out of the maze. *\n\n");
  88.     DelElement(Me()@p_pEnterActions, mazeNotify);
  89. corp;
  90.  
  91. /* forward declaration */
  92. define tp_trollMaze proc mazeIdle()void: corp;
  93.  
  94. define tp_trollMaze proc mazeActive(thing shovel)void:
  95.     thing who;
  96.  
  97.     who := o_trollShovel@p_oCurrentUser;
  98.     if who ~= nil then
  99.     Log("mazeActive moving " + who@p_pName + " out of the troll maze.\n");
  100.     who -- p_pHasShovel;
  101.     AddTail(r_shovelChamber@p_rContents, o_trollShovel);
  102.     o_trollShovel -- p_oCurrentUser;
  103.     o_drawBridge@p_oState := 0;
  104.     SetCharacterLocation(ThingCharacter(who), r_shovelChamber);
  105.     AddTail(who@p_pEnterActions, mazeNotify);
  106.     DelElement(who@p_pExitActions, mazeIdle);
  107.     fi;
  108. corp;
  109.  
  110. replace mazeIdle()void:
  111.     thing me;
  112.  
  113.     me := Me();
  114.     me -- p_pHasShovel;
  115.     DelElement(me@p_pExitActions, mazeIdle);
  116.     SetLocation(r_shovelChamber);
  117.     ABPrint(r_shovelChamber, nil, nil, "Clunk!\n");
  118.     AddTail(r_shovelChamber@p_rContents, o_trollShovel);
  119.     o_trollShovel -- p_oCurrentUser;
  120.     o_drawBridge@p_oState := 0;
  121.     ignore RemoveActiveAction(o_trollShovel, mazeActive);
  122. corp;
  123.  
  124. define tp_trollMaze proc touchShovel()status:
  125.     thing me;
  126.     action a;
  127.  
  128.     me := Me();
  129.     if Character(me@p_pName) ~= nil then
  130.     Print(
  131.         "As you touch the shovel, you feel a sharp shock, as of "
  132.         "electricity. The shock momentarily clouds your mind, but even so "
  133.         "you look with bewilderment as the shovel seems to melt into your "
  134.         "hand. When you recover your senses, the shovel is gone, and you "
  135.         "feel a strong desire to dig. There is a nagging feeling of "
  136.         "something tugging at your mind, from somewhere to the northeast."
  137.         "\n");
  138.     OPrint("As " + me@p_pName +
  139.         " touches the shovel, it seems to cloud or "
  140.         "blur, and then it is gone.\n");
  141.     me@p_pHasShovel := true;
  142.     DelElement(r_shovelChamber@p_rContents, o_trollShovel);
  143.     AddTail(me@p_pExitActions, mazeIdle);
  144.     RegisterActiveAction(o_trollShovel, mazeActive);
  145.     o_trollShovel@p_oCurrentUser := me;
  146.     succeed
  147.     else
  148.     fail
  149.     fi
  150. corp;
  151. o_trollShovel@p_oTouchChecker := touchShovel$
  152. define tp_trollMaze proc getShovel(thing shovel)status:
  153.     touchShovel()
  154. corp;
  155. o_trollShovel@p_oGetChecker := getShovel$
  156. o_trollShovel@p_Image := "Proving/trollShovel"$
  157.  
  158. define tp_trollMaze proc leaveShovel()status:
  159.     thing me;
  160.  
  161.     me := Me();
  162.     if me@p_pHasShovel then
  163.     me -- p_pHasShovel;
  164.     Print("As you leave this chamber, you experience a momentary feeling "
  165.         "of loss.\n");
  166.     ABPrint(r_shovelChamber, nil, nil, "Clunk!\n");
  167.     AddTail(r_shovelChamber@p_rContents, o_trollShovel);
  168.     DelElement(me@p_pExitActions, mazeIdle);
  169.     o_trollShovel -- p_oCurrentUser;
  170.     o_drawBridge@p_oState := 0;
  171.     ignore RemoveActiveAction(o_trollShovel, mazeActive);
  172.     fi;
  173.     continue
  174. corp;
  175. AddSouthChecker(r_shovelChamber, leaveShovel, false)$
  176.  
  177. HUniConnect(r_shovelChamber, r_shovelChamber, D_NORTHWEST)$
  178. HUniConnect(r_shovelChamber, r_shovelChamber, D_WEST)$
  179. HUniConnect(r_shovelChamber, r_shovelChamber, D_SOUTHWEST)$
  180. HUniConnect(r_shovelChamber, r_shovelChamber, D_NORTHEAST)$
  181. HUniConnect(r_shovelChamber, r_shovelChamber, D_EAST)$
  182. HUniConnect(r_shovelChamber, r_shovelChamber, D_SOUTHEAST)$
  183. define tp_trollMaze proc shovelNoGo()status:
  184.     if Me()@p_pHasShovel then
  185.     Print("The stone is much too hard for you to walk through!\n");
  186.     else
  187.     Print("You can't go in that direction.\n");
  188.     fi;
  189.     fail
  190. corp;
  191. AddNorthWestChecker(r_shovelChamber, shovelNoGo, false)$
  192. AddWestChecker(r_shovelChamber, shovelNoGo, false)$
  193. AddSouthWestChecker(r_shovelChamber, shovelNoGo, false)$
  194. AddNorthEastChecker(r_shovelChamber, shovelNoGo, false)$
  195. AddEastChecker(r_shovelChamber, shovelNoGo, false)$
  196. AddSouthEastChecker(r_shovelChamber, shovelNoGo, false)$
  197.  
  198. HUniConnect(r_shovelChamber, r_shovelChamber, D_UP)$
  199. define tp_trollMaze proc shovelUp()status:
  200.     if Me()@p_pHasShovel then
  201.     Print("The ceiling is too high - you cannot go up that way.\n");
  202.     else
  203.     Print("You can't go in that direction.\n");
  204.     fi;
  205.     fail
  206. corp;
  207. AddUpChecker(r_shovelChamber, shovelUp, false)$
  208. HUniConnect(r_shovelChamber, r_shovelChamber, D_DOWN)$
  209. define tp_trollMaze proc shovelDown()status:
  210.     if Me()@p_pHasShovel then
  211.     Print("The stone of the floor is quite hard - you cannot go down that "
  212.         "way.\n");
  213.     else
  214.     Print("You can't go in that direction.\n");
  215.     fi;
  216.     fail
  217. corp;
  218. AddDownChecker(r_shovelChamber, shovelDown, false)$
  219.  
  220. define tp_trollMaze proc doShovelDig()void:
  221.     if Me()@p_pHasShovel then
  222.     Print("The stone of the floor is quite hard - you cannot go down that "
  223.         "way.\n");
  224.     else
  225.     Print("Digging through solid rock is quite difficult.\n");
  226.     fi;
  227. corp;
  228. AddSpecialCommand(r_shovelChamber, "dig,excavate,shovel", doShovelDig)$
  229.  
  230. define tp_trollMaze o_bridgeSign CreateThing(nil)$
  231. FakeObject(o_bridgeSign, r_trollMaze, "sign", "")$
  232. define tp_trollMaze proc bridgeSignDesc()string:
  233.     thing me;
  234.  
  235.     me := Me();
  236.     if me@p_pMazeZ = MAZE_GOAL_Z and me@p_pMazeY = MAZE_GOAL_Y + 3 and
  237.     me@p_pMazeX = MAZE_GOAL_X
  238.     then
  239.     "You see nothing special about the sign. It reads:\n\n"
  240.     "\tSPEAK THE BOTTOM WORD\n"
  241.     else
  242.     "There is no sign here."
  243.     fi
  244. corp;
  245. o_bridgeSign@p_oDescAction := bridgeSignDesc$
  246. define tp_trollMaze proc bridgeSignRead()string:
  247.     thing me;
  248.  
  249.     me := Me();
  250.     if me@p_pMazeZ = MAZE_GOAL_Z and me@p_pMazeY = MAZE_GOAL_Y + 3 and
  251.     me@p_pMazeX = MAZE_GOAL_X
  252.     then
  253.     "The sign reads:\n\n\tSPEAK THE BOTTOM WORD\n"
  254.     else
  255.     "There is no sign here."
  256.     fi
  257. corp;
  258. o_bridgeSign@p_oReadAction := bridgeSignRead$
  259.  
  260. define tp_trollMaze proc trollMazeListen(string s)status:
  261.     thing me;
  262.     int xScale, yScale;
  263.  
  264.     me := Me();
  265.     if me@p_pMazeZ = MAZE_GOAL_Z and me@p_pMazeY = MAZE_GOAL_Y + 3 and
  266.     me@p_pMazeX = MAZE_GOAL_X
  267.     then
  268.     SetTail(s);
  269.     while
  270.         s := GetWord();
  271.         s ~= ""
  272.     do
  273.         if s == "LURT" and o_drawBridge@p_oState = 0 then
  274.         o_drawBridge@p_oState := 1;
  275.         Print("With a rumble and a bang, the drawbridge lowers into "
  276.             "place across the chasm.\n");
  277.         xScale := GCols(nil) / (2 * (MAZE_MAX_X + 1));
  278.         yScale := GRows(nil) / (MAZE_MAX_Y + 1);
  279.         GSetPen(nil, C_BROWN);
  280.         GAMovePixels(nil, MAZE_GOAL_X * xScale + 1,
  281.             MAZE_GOAL_Y * yScale + 2 * yScale - 1);
  282.         GRectanglePixels(nil, xScale - 2, yScale + 2, true);
  283.         fi;
  284.     od;
  285.     fi;
  286.     continue
  287. corp;
  288. AddRoomSayChecker(r_trollMaze, trollMazeListen, false)$
  289.  
  290. define tp_trollMaze proc questHeartDesc()string:
  291.     "Find the heart of the trolls."
  292. corp;
  293. define tp_trollMaze proc questHeartCheck()void:
  294. corp;
  295. define tp_trollMaze proc questHeartHint()string:
  296.     "It lies deep in the rock."
  297. corp;
  298. QuestDirect("Heart", questHeartDesc, questHeartCheck, questHeartHint)$
  299.  
  300. define tp_trollMaze proc maze(int z, y, x)int:
  301.     if z < 0 or z > MAZE_MAX_Z or
  302.     y < 0 or y > MAZE_MAX_Y or
  303.     x < 0 or x > MAZE_MAX_X
  304.     then
  305.     MAZE_BLOCK
  306.     else
  307.     (r_trollMaze@p_rLayerList[z]@p_rLayer[y] >>
  308.         ((MAZE_MAX_X - x) * 2)) & 0b11
  309.     fi
  310. corp;
  311.  
  312. define tp_trollMaze p_rSpaceCount CreateIntProp()$
  313. define tp_trollMaze p_rSpaceVector CreateIntListProp()$
  314. r_trollMaze@p_rSpaceCount := 0$
  315. r_trollMaze@p_rSpaceVector := CreateIntArray(6)$
  316. define tp_trollMaze proc markSpace(int dir)void:
  317.     int count;
  318.  
  319.     count := r_trollMaze@p_rSpaceCount;
  320.     r_trollMaze@p_rSpaceVector[count] := dir;
  321.     r_trollMaze@p_rSpaceCount := count + 1;
  322. corp;
  323. define tp_trollMaze proc dumpSpaces()bool:
  324.     list int spaces;
  325.     int count, i;
  326.  
  327.     count := r_trollMaze@p_rSpaceCount;
  328.     spaces := r_trollMaze@p_rSpaceVector;
  329.     if count ~= 0 then
  330.     if count = 1 then
  331.         Print("There is open space ");
  332.     else
  333.         Print("There are open spaces ");
  334.     fi;
  335.     for i from 0 upto count - 1 do
  336.         if i ~= 0 then
  337.         if i = count - 1 then
  338.             Print(" and ");
  339.         else
  340.             Print(", ");
  341.         fi;
  342.         fi;
  343.         Print(
  344.         case spaces[i]
  345.         incase D_NORTH:
  346.             "to the north"
  347.         incase D_SOUTH:
  348.             "to the south"
  349.         incase D_EAST:
  350.             "to the east"
  351.         incase D_WEST:
  352.             "to the west"
  353.         incase D_UP:
  354.             "above you"
  355.         incase D_DOWN:
  356.             "below you"
  357.         default:
  358.             "?"
  359.         esac);
  360.     od;
  361.     Print(".");
  362.     r_trollMaze@p_rSpaceCount := 0;
  363.     true
  364.     else
  365.     false
  366.     fi
  367. corp;
  368.  
  369. define tp_trollMaze proc drawFloor(int x, y, z)void:
  370.     int kind, xScale, yScale;
  371.  
  372.     kind := maze(z - 1, y, x);
  373.     if kind = MAZE_NORMAL then
  374.     GSetPen(nil, C_GOLD);
  375.     elif kind = MAZE_BLOCK then
  376.     GSetPen(nil, C_LIGHT_GREY);
  377.     else
  378.     GSetPen(nil, C_DARK_GREY);
  379.     fi;
  380.     xScale := GCols(nil) / (2 * (MAZE_MAX_X + 1));
  381.     yScale := GRows(nil) / (MAZE_MAX_Y + 1);
  382.     GAMovePixels(nil, x * xScale, y * yScale);
  383.     GRectanglePixels(nil, xScale, yScale, true);
  384. corp;
  385.  
  386. define tp_trollMaze proc drawBlock(int x, y, kind)void:
  387.     int xScale, yScale;
  388.  
  389.     if kind = MAZE_NORMAL then
  390.     GSetPen(nil, C_ORANGE);
  391.     else
  392.     GSetPen(nil, C_MEDIUM_GREY);
  393.     fi;
  394.     xScale := GCols(nil) / (2 * (MAZE_MAX_X + 1));
  395.     yScale := GRows(nil) / (MAZE_MAX_Y + 1);
  396.     GAMovePixels(nil, x * xScale, y * yScale);
  397.     GRectanglePixels(nil, xScale, yScale, true);
  398. corp;
  399.  
  400. define tp_trollMaze proc showMaze()void:
  401.     thing me;
  402.     int x, y, z, dx, dy, dz, x0, y0, kind, xScale, yScale;
  403.     bool needNewLine;
  404.  
  405.     me := Me();
  406.     if me@p_oLight or FindFlagOnList(me@p_pCarrying, p_oLight) then
  407.     x := me@p_pMazeX;
  408.     y := me@p_pMazeY;
  409.     z := me@p_pMazeZ;
  410.     dx := x - MAZE_GOAL_X;
  411.     dy := y - MAZE_GOAL_Y;
  412.     dz := z - MAZE_GOAL_Z;
  413.     if dz = 0 and dy = 0 and dx = 0 then
  414.         Print("You are in the heart of the trolls.\n");
  415.     elif dz = 0 and dy = 2 and dx = 0 then
  416.         Print("You are on a drawbridge.\n");
  417.     elif maze(z, y, x) = MAZE_NORMAL then
  418.         Print("You are in solid rock.\n");
  419.     else
  420.         Print("You are in a cavity in the rock.\n");
  421.     fi;
  422.     if maze(z + 1, y, x) = MAZE_OPEN then
  423.         markSpace(D_UP);
  424.     fi;
  425.     if maze(z - 1, y, x) = MAZE_OPEN then
  426.         markSpace(D_DOWN);
  427.     fi;
  428.     if maze(z, y - 1, x) = MAZE_OPEN then
  429.         markSpace(D_NORTH);
  430.     fi;
  431.     if maze(z, y + 1, x) = MAZE_OPEN then
  432.         markSpace(D_SOUTH);
  433.     fi;
  434.     if maze(z, y, x - 1) = MAZE_OPEN then
  435.         markSpace(D_WEST);
  436.     fi;
  437.     if maze(z, y, x + 1) = MAZE_OPEN then
  438.         markSpace(D_EAST);
  439.     fi;
  440.     needNewLine := dumpSpaces();
  441.     if z = MAZE_GOAL_Z and y = MAZE_GOAL_Y + 3 and x = MAZE_GOAL_X then
  442.         if o_drawBridge@p_oState = 0 then
  443.         Print(" There is a drawbridge drawn up on the other side of "
  444.             "the chasm, and there is a small sign on this side.");
  445.         else
  446.         Print(" There is a drawbridge across the chasm, and there "
  447.             "is a small sign on this side.");
  448.         fi;
  449.     fi;
  450.     if needNewLine then
  451.         Print("\n");
  452.     fi;
  453.     if dx ~= 0 or dy ~= 0 or dz ~= 0 then
  454.         if dx > -2 and dx < 2 then
  455.         dx := 0;
  456.         fi;
  457.         if dy > -2 and dy < 2 then
  458.         dy := 0;
  459.         fi;
  460.         if dz > -2 and dz < 2 then
  461.         dz := 0;
  462.         fi;
  463.         if dx = 0 and dy = 0 and dz = 0 then
  464.         Print("Whatever has been leading you around is very close.\n");
  465.         else
  466.         Print("The tugging is coming from ");
  467.         if dz ~= 0 then
  468.             if dz < 0 then
  469.             Print("above");
  470.             elif dz > 0 then
  471.             Print("below");
  472.             fi;
  473.             if dx ~= 0 or dy ~= 0 then
  474.             Print(" and from ");
  475.             fi;
  476.         fi;
  477.         if dx ~= 0 or dy ~= 0 then
  478.             Print("the ");
  479.             if dx < 0 then
  480.             if dy < 0 then
  481.                 Print("southeast");
  482.             elif dy = 0 then
  483.                 Print("east");
  484.             else
  485.                 Print("northeast");
  486.             fi;
  487.             elif dx = 0 then
  488.             if dy < 0 then
  489.                 Print("south");
  490.             elif dy > 0 then
  491.                 Print("north");
  492.             fi;
  493.             else
  494.             if dy < 0 then
  495.                 Print("southwest");
  496.             elif dy = 0 then
  497.                 Print("west");
  498.             else
  499.                 Print("northwest");
  500.             fi;
  501.             fi;
  502.         fi;
  503.         Print(".\n");
  504.         fi;
  505.     fi;
  506.     if GOn(nil) then
  507.         GSetPen(nil, C_BLACK);
  508.         GAMove(nil, 0.0, 0.0);
  509.         GRectangle(nil, 0.5, 1.0, true);
  510.         kind := maze(z, y, x);
  511.         if kind = MAZE_OPEN then
  512.         drawFloor(x, y, z);
  513.         else
  514.         drawBlock(x, y, kind);
  515.         fi;
  516.         if y > 0 then
  517.         kind := maze(z, y - 1, x);
  518.         if kind = MAZE_OPEN then
  519.             drawFloor(x, y - 1, z);
  520.             if y > 1 then
  521.             kind := maze(z, y - 2, x);
  522.             if kind = MAZE_OPEN then
  523.                 drawFloor(x, y - 2, z);
  524.             else
  525.                 drawBlock(x, y - 2, kind);
  526.             fi;
  527.             fi;
  528.         else
  529.             drawBlock(x, y - 1, kind);
  530.         fi;
  531.         if x < MAZE_MAX_X then
  532.             kind := maze(z, y - 1, x + 1);
  533.             if kind = MAZE_OPEN then
  534.             drawFloor(x + 1, y - 1, z);
  535.             else
  536.             drawBlock(x + 1, y - 1, kind);
  537.             fi;
  538.         fi;
  539.         fi;
  540.         if x < MAZE_MAX_X then
  541.         kind := maze(z, y, x + 1);
  542.         if kind = MAZE_OPEN then
  543.             drawFloor(x + 1, y, z);
  544.             if x < MAZE_MAX_X - 1 then
  545.             kind := maze(z, y, x + 2);
  546.             if kind = MAZE_OPEN then
  547.                 drawFloor(x + 2, y, z);
  548.             else
  549.                 drawBlock(x + 2, y, kind);
  550.             fi;
  551.             fi;
  552.         else
  553.             drawBlock(x + 1, y, kind);
  554.         fi;
  555.         if y < MAZE_MAX_Y then
  556.             kind := maze(z, y + 1, x + 1);
  557.             if kind = MAZE_OPEN then
  558.             drawFloor(x + 1, y + 1, z);
  559.             else
  560.             drawBlock(x + 1, y + 1, kind);
  561.             fi;
  562.         fi;
  563.         fi;
  564.         if y < MAZE_MAX_Y then
  565.         kind := maze(z, y + 1, x);
  566.         if kind = MAZE_OPEN then
  567.             drawFloor(x, y + 1, z);
  568.             if y < MAZE_MAX_Y - 1 then
  569.             kind := maze(z, y + 2, x);
  570.             if kind = MAZE_OPEN then
  571.                 drawFloor(x, y + 2, z);
  572.             else
  573.                 drawBlock(x, y + 2, kind);
  574.             fi;
  575.             fi;
  576.         else
  577.             drawBlock(x, y + 1, kind);
  578.         fi;
  579.         if x > 0 then
  580.             kind := maze(z, y + 1, x - 1);
  581.             if kind = MAZE_OPEN then
  582.             drawFloor(x - 1, y + 1, z)
  583.             else
  584.             drawBlock(x - 1, y + 1, kind);
  585.             fi;
  586.         fi;
  587.         fi;
  588.         if x > 0 then
  589.         kind := maze(z, y, x - 1);
  590.         if kind = MAZE_OPEN then
  591.             drawFloor(x - 1, y, z);
  592.             if x > 1 then
  593.             kind := maze(z, y, x - 2);
  594.             if kind = MAZE_OPEN then
  595.                 drawFloor(x - 2, y, z);
  596.             else
  597.                 drawBlock(x - 2, y, kind);
  598.             fi;
  599.             fi;
  600.         else
  601.             drawBlock(x - 1, y, kind);
  602.         fi;
  603.         if y > 0 then
  604.             kind := maze(z, y - 1, x - 1);
  605.             if kind = MAZE_OPEN then
  606.             drawFloor(x - 1, y - 1, z);
  607.             else
  608.             drawBlock(x - 1, y - 1, kind);
  609.             fi;
  610.         fi;
  611.         fi;
  612.         xScale := GCols(nil) / (2 * (MAZE_MAX_X + 1));
  613.         yScale := GRows(nil) / (MAZE_MAX_Y + 1);
  614.         if z = MAZE_GOAL_Z and
  615.         x >= MAZE_GOAL_X - 1 and x <= MAZE_GOAL_X + 1 and
  616.         y >= MAZE_GOAL_Y and y <= MAZE_GOAL_Y + 3
  617.         then
  618.         x0 := MAZE_GOAL_X * xScale;
  619.         y0 := MAZE_GOAL_Y * yScale;
  620.         /* Draw the sign */
  621.         GSetPen(nil, C_RED_ORANGE);
  622.         GAMovePixels(nil, x0 + xScale + 1, y0 + yScale * 3 + 1);
  623.         GRectanglePixels(nil, xScale / 10, yScale / 10, true);
  624.         /* Draw the drawbridge */
  625.         GSetPen(nil, C_BROWN);
  626.         GAMovePixels(nil, x0 + 1, y0 + yScale * 2 - 1);
  627.         if o_drawBridge@p_oState = 0 then
  628.             GRectanglePixels(nil, xScale - 2, yScale / 5, true);
  629.         else
  630.             GRectanglePixels(nil, xScale - 2, yScale + yScale / 5,
  631.             true);
  632.         fi;
  633.         fi;
  634.         PlaceCursorPixels(x * xScale + (xScale - 7) / 2,
  635.                   y * yScale + (yScale - 7) / 2);
  636.     fi;
  637.     else
  638.     Print("It is dark.\n");
  639.     fi;
  640. corp;
  641.  
  642. define tp_trollMaze proc mazeLookChecker()status:
  643.     showMaze();
  644.     succeed
  645. corp;
  646. AddRoomLookChecker(r_trollMaze, mazeLookChecker, false)$
  647.  
  648. define tp_trollMaze proc enterMaze()status:
  649.     thing me;
  650.  
  651.     me := Me();
  652.     if me@p_pHasShovel then
  653.     me@p_pMazeX := MAZE_ENTER_X;
  654.     me@p_pMazeY := MAZE_ENTER_Y;
  655.     me@p_pMazeZ := MAZE_ENTER_Z;
  656.     o_drawBridge@p_oState := 0;
  657.     Print("Amazingly enough, you are able to walk right into the wall. "
  658.         "The stone seems to be soft, and it opens in front of you and "
  659.         "closes behind you.\n");
  660.     SetLocation(r_trollMaze);
  661.     if LightAt(r_shovelChamber) then
  662.         if not me@p_pHidden then
  663.         OPrint(me@p_pName + " walks into the rock and disappears!\n");
  664.         ForEachAgent(r_shovelChamber, UnShowIconOnce);
  665.         fi;
  666.     else
  667.         ForEachAgent(r_shovelChamber, UnShowRoomFromAgent);
  668.     fi;
  669.     SetLocation(r_trollMaze);
  670.     if GOn(nil) then
  671.         RemoveCursor();
  672.         GUndrawIcons(nil);
  673.         GResetIcons(nil);
  674.         DrawRoomName("Solid Rock", "");
  675.     else
  676.         Print("Warning! This puzzle area is MUCH easier if you have "
  677.         "a graphics display!\n\n");
  678.     fi;
  679.     succeed
  680.     else
  681.     Print("You can't go in that direction.\n");
  682.     fail
  683.     fi
  684. corp;
  685. AddNorthChecker(r_shovelChamber, enterMaze, false)$
  686.  
  687. define tp_trollMaze proc mazeMove(int xDelta, yDelta, zDelta)status:
  688.     thing me;
  689.     int x, y, z, oldKind, kind;
  690.  
  691.     me := Me();
  692.     x := me@p_pMazeX;
  693.     y := me@p_pMazeY;
  694.     z := me@p_pMazeZ;
  695.     oldKind := maze(z, y, x);
  696.     if oldKind = MAZE_OPEN and zDelta = 1 then
  697.     Print("The ceiling is too high - you cannot go up that way.\n");
  698.     else
  699.     x := x + xDelta;
  700.     y := y + yDelta;
  701.     z := z + zDelta;
  702.     kind := maze(z, y, x);
  703.     if kind = MAZE_BLOCK then
  704.         Print("That rock is too hard for you to dig into.\n");
  705.     else
  706.         if oldKind ~= MAZE_OPEN or kind ~= MAZE_OPEN then
  707.         Print("You dig ");
  708.         if zDelta = -1 then
  709.             Print("downwards ");
  710.         elif zDelta = 1 then
  711.             Print("upwards ");
  712.         fi;
  713.         if kind = MAZE_OPEN then
  714.             Print("into a cavity in the rock.\n");
  715.         else
  716.             Print("through the rock.\n");
  717.         fi;
  718.         fi;
  719.         if kind = MAZE_OPEN then
  720.         while maze(z - 1, y, x) = MAZE_OPEN do
  721.             Print("There is a cavity beneath you - you fall.\n");
  722.             z := z - 1;
  723.         od;
  724.         fi;
  725.         me@p_pMazeX := x;
  726.         me@p_pMazeY := y;
  727.         me@p_pMazeZ := z;
  728.         if GOn(nil) then
  729.         RemoveCursor();
  730.         fi;
  731.         showMaze();
  732.     fi;
  733.     fi;
  734.     fail
  735. corp;
  736.  
  737. define tp_trollMaze proc mazeMoveNorth()status:
  738.     thing me;
  739.  
  740.     me := Me();
  741.     if me@p_pMazeZ = MAZE_GOAL_Z and me@p_pMazeY = MAZE_GOAL_Y + 3 and
  742.     me@p_pMazeX = MAZE_GOAL_X and o_drawBridge@p_oState = 1
  743.     then
  744.     if GOn(nil) then
  745.         RemoveCursor();
  746.     fi;
  747.     me@p_pMazeY := MAZE_GOAL_Y + 2;
  748.     showMaze();
  749.     fail
  750.     else
  751.     if me@p_pMazeZ = MAZE_GOAL_Z and me@p_pMazeY = MAZE_GOAL_Y + 1 and
  752.         me@p_pMazeX = MAZE_GOAL_X
  753.     then
  754.         Print("You enter the heart of the trolls - their most sacred "
  755.         "place. Congratulations on finding it!\n");
  756.         DoQuest(questHeartCheck);
  757.     fi;
  758.     mazeMove(0, -1, 0)
  759.     fi
  760. corp;
  761. define tp_trollMaze proc mazeMoveEast()status:
  762.     mazeMove(1, 0, 0)
  763. corp;
  764. define tp_trollMaze proc mazeMoveSouth()status:
  765.     thing me;
  766.  
  767.     me := Me();
  768.     if me@p_pMazeX = MAZE_ENTER_X and
  769.     me@p_pMazeY = MAZE_ENTER_Y and
  770.     me@p_pMazeZ = MAZE_ENTER_Z
  771.     then
  772.     continue
  773.     elif me@p_pMazeZ = MAZE_GOAL_Z and me@p_pMazeY = MAZE_GOAL_Y + 1 and
  774.     me@p_pMazeX = MAZE_GOAL_X
  775.     then
  776.     if GOn(nil) then
  777.         RemoveCursor();
  778.     fi;
  779.     me@p_pMazeY := MAZE_GOAL_Y + 2;
  780.     showMaze();
  781.     fail
  782.     else
  783.     mazeMove(0, 1, 0)
  784.     fi
  785. corp;
  786. define tp_trollMaze proc mazeMoveWest()status:
  787.     mazeMove(-1, 0, 0)
  788. corp;
  789. define tp_trollMaze proc mazeMoveUp()status:
  790.     mazeMove(0, 0, 1)
  791. corp;
  792. define tp_trollMaze proc mazeMoveDown()status:
  793.     mazeMove(0, 0, -1)
  794. corp;
  795.  
  796. HUniConnect(r_trollMaze, r_trollMaze, D_NORTH)$
  797. HUniConnect(r_trollMaze, r_trollMaze, D_EAST)$
  798. HUniConnect(r_trollMaze, r_shovelChamber, D_SOUTH)$
  799. HUniConnect(r_trollMaze, r_trollMaze, D_WEST)$
  800. HUniConnect(r_trollMaze, r_trollMaze, D_DOWN)$
  801. HUniConnect(r_trollMaze, r_trollMaze, D_UP)$
  802. AddNorthChecker(r_trollMaze, mazeMoveNorth, false)$
  803. AddEastChecker(r_trollMaze, mazeMoveEast, false)$
  804. AddSouthChecker(r_trollMaze, mazeMoveSouth, false)$
  805. AddWestChecker(r_trollMaze, mazeMoveWest, false)$
  806. AddUpChecker(r_trollMaze, mazeMoveUp, false)$
  807. AddDownChecker(r_trollMaze, mazeMoveDown, false)$
  808.  
  809. define tp_trollMaze proc shovelDig()void:
  810.     ignore mazeMove(0, 0, -1);
  811. corp;
  812. AddSpecialCommand(r_trollMaze, "dig,excavate,shovel", shovelDig)$
  813.  
  814. r_trollMaze@p_rLayerList := CreateThingList()$
  815.  
  816. define tp_trollMaze proc makeRow(string r)int:
  817.     int row, i;
  818.     string ch;
  819.  
  820.     row := 0;
  821.     for i from 0 upto MAZE_MAX_X do
  822.     row := row << 2;
  823.     ch := SubString(r, i, 1);
  824.     if ch = "B" then
  825.         row := row | MAZE_BLOCK;
  826.     elif ch = "N" then
  827.         row := row | MAZE_NORMAL;
  828.     elif ch = "." then
  829.         row := row | MAZE_OPEN;
  830.     else
  831.         Print("Illegal character in maze row: '" + ch + "'.\n");
  832.     fi;
  833.     od;
  834.     row
  835. corp;
  836.  
  837. define tp_trollMaze proc makeLayer(string y0,y1,y2,y3,y4,y5,y6,y7,y8,y9)void:
  838.     thing th;
  839.     list int li;
  840.  
  841.     li := CreateIntArray(10);
  842.     li[0] := makeRow(y0);
  843.     li[1] := makeRow(y1);
  844.     li[2] := makeRow(y2);
  845.     li[3] := makeRow(y3);
  846.     li[4] := makeRow(y4);
  847.     li[5] := makeRow(y5);
  848.     li[6] := makeRow(y6);
  849.     li[7] := makeRow(y7);
  850.     li[8] := makeRow(y8);
  851.     li[9] := makeRow(y9);
  852.     th := CreateThing(nil);
  853.     th@p_rLayer := li;
  854.     AddTail(r_trollMaze@p_rLayerList, th);
  855. corp;
  856.  
  857. /* must be given from the bottom up */
  858.  
  859. makeLayer(    /* 0 */
  860.     "NNNNNNNNNNNNNNNN",
  861.     "NNNNNNNNNNNNNNNN",
  862.     "BNNNBNBNBBNNBBBN",
  863.     "BNNNBNBNBNBNNBNN",
  864.     "BNNNBNBNBBNNNBNN",
  865.     "BNNNBNBNBNBNNBNN",
  866.     "BBBNNBBNBNBNNBNN",
  867.     "NNNNNNNNNNNNNNNN",
  868.     "NNNNNNNNNNNNNNNN",
  869.     "BBBNBBBNBBBNBBBN")$
  870.  
  871. makeLayer(    /* 1 */
  872.     "BBBBBBBBBBBBBBBB",
  873.     "BBBBBBBBBBBBBBBB",
  874.     "BBBBBBBBBBBBBBBB",
  875.     "BBBBBNBBBNBBBBBB",
  876.     "BBBBBBBBBBBBBBBB",
  877.     "BBBBBBBBBBBBBBBB",
  878.     "BBBBBBBBBBBBBBBB",
  879.     "BBBBBBBBBBBBBBBB",
  880.     "BBBBBBBBBBNBBBBB",
  881.     "BBBBBBBBBBBBBBBB")$
  882.  
  883. makeLayer(    /* 2 */
  884.     "BBBBNN..B..NN..N",
  885.     "...B....B...BBBN",
  886.     ".B.BBB..B...BBBN",
  887.     ".....NN.B...BBBN",
  888.     ".B.BBBBBBBBBBBBB",
  889.     "...BNNNBBBBBBBBB",
  890.     ".B.BNBNBBBBBBBBN",
  891.     "...BNBNBBB.....N",
  892.     ".B.BNBNB.B.BBBBB",
  893.     "...BNBN..BBBNNNB")$
  894.  
  895. makeLayer(    /* 3 */
  896.     "BBBB.NN...NN....",
  897.     "BBBB........BBB.",
  898.     "BBBBBB......B...",
  899.     "BBBBBBN.B...B.BB",
  900.     "BBBBBBBBBBBBB.BB",
  901.     "BBBB.B.B.B....BN",
  902.     "BBBB.B.B.BBBBBBN",
  903.     "BBBB...B.B......",
  904.     "BBBB...B.B......",
  905.     "BBBB..NNNNNNNNBB")$
  906.  
  907. makeLayer(    /* 4 */
  908.     ".NBB..NNNNN...BB",
  909.     "..NN........BBBB",
  910.     "BBBBB.....BBBBBB",
  911.     "BBB.NNN...BBBBBB",
  912.     "BBBBBBBBBBBBBBBN",
  913.     "N....BBB.B...BBN",
  914.     "BBBB.BBBBBBBBBB.",
  915.     "......BB.BBBBBB.",
  916.     ".NNNNNNBBB..BBBB",
  917.     "......NNN..NBBBB")$
  918.  
  919. makeLayer(    /* 5 */
  920.     ".NNB............",
  921.     "...B............",
  922.     ".........BBBB.B.",
  923.     "NBBN....BBB.B.NN",
  924.     "NBBBBBBBBBB.BBNN",
  925.     "NBBB..B..B...BBB",
  926.     "BBBB..B......BBB",
  927.     "......BB.BBBBB.B",
  928.     "......NBBB.....B",
  929.     "......NNNN.NNNNN")$
  930.  
  931. makeLayer(    /* 6 */
  932.     "..BB.......B.BBB",
  933.     "..BB.......B..BB",
  934.     "BBBB...B.NBBB.BB",
  935.     "BBBN...BBNBBB.BB",
  936.     "BBBBBBBBBNBBBBNB",
  937.     "BBBB..B.BBBBBBNB",
  938.     "BBBB..BBBBBBBBNB",
  939.     "BBBBBBBBBBBBBBBB",
  940.     "BBBB...BBB......",
  941.     "BBBB........BBBB")$
  942.  
  943. makeLayer(    /* 7 */
  944.     "BBB..BBBBBBB....",
  945.     "BBB....BBBB...B.",
  946.     "BBNN...NNNN...B.",
  947.     "...N...NBBBB..B.",
  948.     "BBBBBBBBBNB..BN.",
  949.     "NNNN..B..NB.BBN.",
  950.     "N.....BBBBB.....",
  951.     "N.......B...BBB.",
  952.     "N...............",
  953.     "NNNN........BBBB")$
  954.  
  955. makeLayer(    /* 8 */
  956.     "BB.....NNNNNN.BB",
  957.     "BBN....NBBBBB.B.",
  958.     ".......NNNNBB.B.",
  959.     "BBBBBB.NBBBBB.BB",
  960.     "BBBBBBBBBBBBBBB.",
  961.     "BBBB..BBBBBBBBB.",
  962.     "BBBB..BBBBBBBBB.",
  963.     "BBBB...BBBBBBBBB",
  964.     "BBBB...BBBB.BBBB",
  965.     "BBBB...BBBB.BBBB")$
  966.  
  967. makeLayer(    /* 9 */
  968.     "B......NBBBB.B..",
  969.     "....BBBBBBBB....",
  970.     "........NBBB.B..",
  971.     "BBBBBB..B....B..",
  972.     "........BB.B.B..",
  973.     "NNNN..B.BB.B.B..",
  974.     "N..........B.B..",
  975.     "N.NN...BB.BB.B..",
  976.     "N..N....B.B..BB.",
  977.     "NNNN............")$
  978.  
  979. ignore DeleteSymbol(tp_trollMaze, "makeLayer")$
  980. ignore DeleteSymbol(tp_trollMaze, "makeRow")$
  981.  
  982. unuse tp_trollMaze
  983.