home *** CD-ROM | disk | FTP | other *** search
/ Amiga MA Magazine 1998 #7 / amigamamagazinepolishissue1998.iso / rozrywka / rpg / amigamud / src / scenario / mall.m < prev    next >
Text File  |  1997-08-03  |  43KB  |  1,248 lines

  1. /*
  2.  * Amiga MUD
  3.  *
  4.  * Copyright (c) 1997 by Chris Gray
  5.  */
  6.  
  7. /*
  8.  * mall.m - define the minimall in the starter dungeon.
  9.  */
  10.  
  11. private tp_mall CreateTable()$
  12. use tp_mall
  13.  
  14. /*
  15.  * NOTE: two rooms, r_arrivals and r_lostAndFound, are actually created
  16.  *    in 'util1.m' and 'util2.m'. Since the structure and connections of
  17.  *    those rooms are set up in this file, this file must be sourced by
  18.  *    the same player who sources those files (normally SysAdmin), or
  19.  *    those two rooms must be public, at least long enough to allow the
  20.  *    building here. We are also dependent on some properties relevant
  21.  *    to specific verbs, p_rRegisterAction and p_rBuyAction, so we need
  22.  *    to have 'verbs.m' sourced first.
  23.  */
  24.  
  25. /* Most are private since we don't want anybody changing the stuff in the
  26.    minimall area. */
  27.  
  28. /* All rooms in this area use this routine as their graphics drawing routine.
  29.    It works with the code in 'graphics.m'. */
  30.  
  31. define tp_mall MINI_MALL_ID NextEffectId()$
  32.  
  33. define tp_mall proc drawMiniMall()void:
  34.  
  35.     if not KnowsEffect(nil, MINI_MALL_ID) then
  36.     DefineEffect(nil, MINI_MALL_ID);
  37.  
  38.     GSetImage(nil, "Town/mall");
  39.     IfFound(nil);
  40.         ShowCurrentImage();
  41.     Else(nil);
  42.         GSetPen(nil, C_TAN);
  43.         GAMove(nil, 0.051, 0.165);
  44.         GRectangle(nil, 0.4047, 0.685, false);
  45.  
  46.         GAMove(nil, 0.186, 0.325);
  47.         GADraw(nil, 0.32, 0.325);
  48.         GADraw(nil, 0.345, 0.405);
  49.         GAMove(nil, 0.345, 0.605);
  50.         GADraw(nil, 0.32, 0.685);
  51.         GADraw(nil, 0.186, 0.685);
  52.         GADraw(nil, 0.161, 0.605);
  53.         GADraw(nil, 0.161, 0.405);
  54.         GADraw(nil, 0.186, 0.325);
  55.         GADraw(nil, 0.186, 0.165);
  56.         GAMove(nil, 0.32, 0.165);
  57.         GADraw(nil, 0.32, 0.325);
  58.         GAMove(nil, 0.346, 0.41);
  59.         GADraw(nil, 0.453, 0.41);
  60.         GAMove(nil, 0.345, 0.605);
  61.         GADraw(nil, 0.453, 0.605);
  62.         GAMove(nil, 0.32, 0.685);
  63.         GADraw(nil, 0.32, 0.837);
  64.         GAMove(nil, 0.186, 0.685);
  65.         GADraw(nil, 0.186, 0.837);
  66.         GAMove(nil, 0.052, 0.605);
  67.         GADraw(nil, 0.161, 0.605);
  68.         GAMove(nil, 0.052, 0.405);
  69.         GADraw(nil, 0.161, 0.405);
  70.  
  71.         GSetPen(nil, C_BLACK);
  72.         GAMove(nil, 0.454, 0.415);
  73.         GADraw(nil, 0.454, 0.6);
  74.  
  75.         GSetPen(nil, C_BROWN);
  76.         GAMove(nil, 0.239, 0.325);
  77.         HorizontalDoor();
  78.         GAMove(nil, 0.239, 0.685);
  79.         HorizontalDoor();
  80.         GAMove(nil, 0.162, 0.47);
  81.         VerticalDoor();
  82.         GAMove(nil, 0.18, 0.345);
  83.         NorthWestDoor();
  84.         GAMove(nil, 0.168, 0.623);
  85.         NorthEastDoor();
  86.         GAMove(nil, 0.326, 0.345);
  87.         NorthEastDoor();
  88.         GAMove(nil, 0.338, 0.623);
  89.         NorthWestDoor();
  90.  
  91.         GSetPen(nil, C_GOLD);
  92.         GAMove(nil, 0.12, 0.285);
  93.         GRMovePixels(nil, -8, 3);
  94.         GText(nil, "GR");
  95.         GAMove(nil, 0.111, 0.505);
  96.         GRMovePixels(nil, -8, 3);
  97.         GText(nil, "LF");
  98.         GAMove(nil, 0.12, 0.725);
  99.         GRMovePixels(nil, -8, 3);
  100.         GText(nil, "BS");
  101.         GAMove(nil, 0.257, 0.243);
  102.         GRMovePixels(nil, -8, 3);
  103.         GText(nil, "MR");
  104.         GAMove(nil, 0.257, 0.505);
  105.         GRMovePixels(nil, -8, 3);
  106.         GText(nil, "MM");
  107.         GAMove(nil, 0.257, 0.765);
  108.         GRMovePixels(nil, -8, 3);
  109.         GText(nil, "ST");
  110.         GAMove(nil, 0.389, 0.285);
  111.         GRMovePixels(nil, -8, 3);
  112.         GText(nil, "AR");
  113.         GAMove(nil, 0.389, 0.725);
  114.         GRMovePixels(nil, -8, 3);
  115.         GText(nil, "BK");
  116.     Fi(nil);
  117.     
  118.     EndEffect();
  119.     fi;
  120.     CallEffect(nil, MINI_MALL_ID);
  121. corp;
  122.  
  123. define tp_mall MALL_MAP_GROUP NextMapGroup()$
  124.  
  125. /*
  126.  * The mall entrance room has a bunch of direction specific descriptions and
  127.  * messages. It also contains the 'enter-exit machine', a bench to sit on,
  128.  * and a hidden exit under the plate in the floor.
  129.  */
  130.  
  131. define tp_mall r_underPlate CreateThing(r_indoors)$    /* needed here */
  132.  
  133. /* r_mallEntrance is in tp_misc, since is used in other files */
  134. define tp_misc r_mallEntrance CreateThing(r_indoors)$
  135. SetupRoom(r_mallEntrance, "in a small public passageway", "")$
  136. r_mallEntrance@p_rWestDesc := "You can see back into the mini mall."$
  137. r_mallEntrance@p_rEnterDesc := "You can see back into the mini mall."$
  138. r_mallEntrance@p_rWestMessage := "You walk into the mini mall."$
  139. r_mallEntrance@p_rEnterMessage := "You walk into the mini mall."$
  140. r_mallEntrance@p_rWestOMessage := "walks into the mini mall."$
  141. r_mallEntrance@p_rEnterOMessage := "walks into the mini mall."$
  142. r_mallEntrance@p_rWestEMessage := "comes from the mini mall."$
  143. r_mallEntrance@p_rEnterEMessage := "comes from the mini mall."$
  144. r_mallEntrance@p_rEastDesc := "You can see out towards the street."$
  145. r_mallEntrance@p_rExitDesc := "You can see out towards the street."$
  146. r_mallEntrance@p_rEastMessage := "You walk out onto the sunny street."$
  147. r_mallEntrance@p_rExitMessage := "You walk out onto the sunny street."$
  148. r_mallEntrance@p_rEastOMessage := "walks out onto the street."$
  149. r_mallEntrance@p_rExitOMessage := "walks out onto the street."$
  150. r_mallEntrance@p_rEastEMessage := "comes in from the street."$
  151. r_mallEntrance@p_rExitEMessage := "comes in from the street."$
  152. r_mallEntrance@p_rNoGoString := "You cannot walk through concrete."$
  153. RoomGraphics(r_mallEntrance, "Mall", "Entrance", MALL_MAP_GROUP,
  154.          0.4, 0.505, drawMiniMall)$
  155. define tp_mall o_bench CreateThing(nil)$
  156. SetupObject(o_bench, r_mallEntrance, "bench;wooden",
  157.     "The bench is a bit faded, but quite usable. There is room for 3 people "
  158.     "to sit on it.")$
  159. o_bench@p_oCanSitOn := 4$    /* one greater than actual capacity */
  160. o_bench@p_oNotGettable := true$
  161. r_mallEntrance@p_rDownDesc :=
  162.     "There is a 3 foot square metal plate set into the floor. It looks like "
  163.     "it can be raised on its hinges."$
  164. FakeObject(CreateThing(nil), r_mallEntrance, "floor",
  165.        r_mallEntrance@p_rDownDesc)$
  166. define tp_mall CLANG_ID NextSoundEffectId()$
  167. define tp_mall proc clangOnce(thing client)void:
  168.     if SOn(client) then
  169.     SPlaySound(client, "clang", 1, CLANG_ID);
  170.     IfFound(client);
  171.     Else(client);
  172.         FailText(client, "Clang!");
  173.     Fi(client);
  174.     else
  175.     SPrint(client, "Clang!\n");
  176.     fi;
  177. corp;
  178. define tp_mall proc walkOnPlate()status:
  179.     ForEachAgent(r_mallEntrance, clangOnce);
  180.     /* walking on the plate can also be heard in the room under the plate */
  181.     ForEachAgent(r_underPlate, clangOnce);
  182.     clangOnce(Me());
  183.     continue
  184. corp;
  185. AddAnyEnterChecker(r_mallEntrance, walkOnPlate, false)$
  186. /* We can operate on the plate from either above it or below it. So, we
  187.    define a generic one, and inherit from it for the ones that are in the
  188.    two rooms. */
  189. define tp_mall o_entrancePlate CreateThing(nil)$
  190. FakeModel(o_entrancePlate,
  191.     "plate;metal.plate;dirty,metal,metallic,3,foot,square,hinged",
  192.     "The plate is quite battered, and sags slightly in the middle. There are "
  193.     "hinges on one side, and a small, recessed handle on the opposite side.")$
  194. o_entrancePlate@p_oSmellString := "It smells like very dirty metal."$
  195. o_entrancePlate@p_oTouchString := "It feels like very dirty metal."$
  196. o_entrancePlate@p_oLowerString := "The plate cannot be lowered any further."$
  197. o_entrancePlate@p_oCloseString := "The plate is already closed."$
  198. o_entrancePlate@p_oNotLockable := true$
  199. define tp_mall o_entrancePlate1 CreateThing(o_entrancePlate)$    /* inherit */
  200. SetThingStatus(o_entrancePlate1, ts_wizard)$
  201. AddTail(r_mallEntrance@p_rContents, o_entrancePlate1)$
  202. Scenery(r_mallEntrance, "hinge.handle;small,recessed")$
  203. define tp_mall proc plateLift1()status:
  204.     thing me;
  205.  
  206.     me := Me();
  207.     if me@p_pPosition ~= POS_NONE then
  208.     Print("You are still " + ShowPosition(me) + "\n");
  209.     fail
  210.     else
  211.     Print("The plate lifts easily on its hinges. You see a metal ladder "
  212.         "leading down into a small space under the passageway. You climb "
  213.         "down the ladder, and the plate closes over you.\n");
  214.     if me@p_pHidden then
  215.         OPrint("The metal plate lifts for a moment, then closes.\n");
  216.     else
  217.         OPrint(Capitalize(CharacterNameG(me)) +
  218.          " lifts the metal plate in the floor and descends beneath it.\n");
  219.     fi;
  220.     LeaveRoomStuff(r_underPlate, D_DOWN, MOVE_SPECIAL);
  221.     EnterRoomStuff(r_underPlate, D_UP, MOVE_NORMAL);
  222.     succeed
  223.     fi
  224. corp;
  225. o_entrancePlate1@p_oLiftChecker := plateLift1$
  226. o_entrancePlate1@p_oOpenChecker := plateLift1$
  227. o_entrancePlate1@p_Image := "Town/plateTop"$
  228.  
  229. /* Exercise for the reader: make the plate have an open/closed state, so that
  230.    the player must open the plate, then go down. You should use functions
  231.    dependent on its state for all relevant descriptions, actions, etc. Don't
  232.    forget all the stuff later on for the other side of the plate! */
  233.  
  234. /* For the central area of the minimall, there is not much, but we continue
  235.    with the direction messages for the mall entrance. */
  236.  
  237. define tp_mall r_miniMall CreateThing(r_indoors)$
  238. SetupRoom(r_miniMall, "in the mini mall",
  239.     "This is a small shopping area which collects together a number of useful "
  240.     "services. The seven individual areas are distributed around the sides "
  241.     "of the mall, and a passageway to the street is to the east.")$
  242. Connect(r_mallEntrance, r_miniMall, D_WEST)$
  243. Connect(r_mallEntrance, r_miniMall, D_ENTER)$
  244. r_miniMall@p_rEastDesc :=
  245.     "A large, gloomy passageway heads to the east. You can see something on "
  246.     "the floor half-way through, and daylight at the far end."$
  247. r_miniMall@p_rEastImage := "Town/mall-E"$
  248. r_miniMall@p_rEastMessage := "You head into the passageway."$
  249. r_miniMall@p_rEastOMessage := "heads into the passageway."$
  250. r_miniMall@p_rEastEMessage := "arrives from the passageway."$
  251. r_miniMall@p_rExitDesc :=
  252.     "A large, gloomy passageway heads to the east. You can see something on "
  253.     "the floor half-way through, and daylight at the far end."$
  254. r_miniMall@p_rExitMessage := "You head into the passageway."$
  255. r_miniMall@p_rExitOMessage := "heads into the passageway."$
  256. r_miniMall@p_rExitImage :="Town/mall-E"$
  257. RoomGraphics(r_miniMall, "Mini", "Mall", MALL_MAP_GROUP,
  258.          0.256, 0.505, drawMiniMall)$
  259.  
  260. /* SysAdmin's study is a hidden room, and it's graphic is a random set of
  261.    coloured rectangles (likely different each time). */
  262.  
  263. define tp_mall r_SysAdminsStudy CreateThing(r_indoors)$
  264. SetupRoom(r_SysAdminsStudy, "in SysAdmin's study",
  265.     "The mini mall is magically below you.")$
  266. define tp_mall proc drawStudy()void:
  267.     int i, rows, cols, colours, x1, x2, y1, y2, t;
  268.  
  269.     rows := GRows(nil);
  270.     cols := GCols(nil) / 2;
  271.     colours := GColours(nil);
  272.     for i from 1 upto Random(20) + 10 do
  273.     GSetPen(nil, Random(colours - 1) + 1);
  274.     x1 := Random(cols);
  275.     y1 := Random(rows);
  276.     x2 := Random(cols);
  277.     y2 := Random(rows);
  278.     if x2 < x1 then
  279.         t := x1;
  280.         x1 := x2;
  281.         x2 := t;
  282.     fi;
  283.     if y2 < y1 then
  284.         t := y1;
  285.         y1 := y2;
  286.         y2 := t;
  287.     fi;
  288.     GAMovePixels(nil, x1, y1);
  289.     GRectanglePixels(nil, x2 - x1, y2 - y1, true);
  290.     od;
  291.     /* force a re-draw on look */
  292.     Me()@p_MapGroup := UNKNOWN_MAP_GROUP;
  293. corp;
  294. RoomGraphics(r_SysAdminsStudy, "SysAdmin's", "Study", NextMapGroup(),
  295.          0.0, 0.0, drawStudy)$
  296. HConnect(r_miniMall, r_SysAdminsStudy, D_UP)$
  297. HConnect(r_SysAdminsStudy, r_miniMall, D_DOWN)$
  298. define tp_mall m_watcher CreateThing(nil)$
  299. CreateMachine("", m_watcher, r_miniMall, nil)$
  300. define tp_mall proc watchHandler(string message)void:
  301.     SetPrefix("MM: ");
  302.     /* this is dangerous! */
  303.     ABPrint(r_SysAdminsStudy, nil, nil, message);
  304.     SetPrefix("");
  305. corp;
  306. ignore SetMachineOther(m_watcher, watchHandler)$
  307.  
  308. /* arrivals room is created in util1.m */
  309. Connect(r_miniMall, r_arrivals, D_NORTHEAST)$
  310. UniConnect(r_arrivals, r_miniMall, D_EXIT)$
  311. r_arrivals@p_rNoGoString := "You must go through the doors."$
  312. RoomGraphics(r_arrivals, "Arrivals", "Room", MALL_MAP_GROUP,
  313.          0.387, 0.285, drawMiniMall)$
  314.  
  315. /* The actual mail service is defined later, in 'mail.m' */
  316.  
  317. /* r_mailRoom is in tp_misc, since it is needed in other files */
  318. define tp_misc r_mailRoom CreateThing(r_indoors)$
  319. SetupRoom(r_mailRoom, "in the mail room",
  320.     "This room looks much like all mail rooms. A bank of little "
  321.     "lockable boxes fills one wall. Another is filled by a long counter, "
  322.     "which has a couple of service positions screened with metal bars. "
  323.     "You can REGISTER at the wickets to send and receive mail, and you can "
  324.     "come here to pick up any mail that people have sent you.")$
  325. Connect(r_miniMall, r_mailRoom, D_NORTH)$
  326. UniConnect(r_mailRoom, r_miniMall, D_EXIT)$
  327. r_mailRoom@p_rNoGoString := "You must go through the doors."$
  328. RoomGraphics(r_mailRoom, "Mail", "Room", MALL_MAP_GROUP,
  329.          0.256, 0.245, drawMiniMall)$
  330. Scenery(r_mailRoom,
  331.     "bank.boxes,box;bank,of,little,lockable.lock."
  332.     "counter;long."
  333.     "position,wicket;service."
  334.     "bar;metal")$
  335.  
  336. /*
  337.  * The garbage room. If you drop something you own here, it is destroyed.
  338.  * There is also a slightly persistent bad smell - shows the use of attaching
  339.  * verb-specific stuff to the the player.
  340.  */
  341.  
  342. /* r_garbageRoom is in tp_misc since it is needed in other files */
  343. define tp_misc r_garbageRoom CreateThing(r_indoors)$
  344. SetupRoom(r_garbageRoom, "in the garbage room",
  345.     "Drop things here to dispose of them.")$
  346. Connect(r_miniMall, r_garbageRoom, D_NORTHWEST)$
  347. UniConnect(r_garbageRoom, r_miniMall, D_EXIT)$
  348. /* NOTE: not 'utility' - we want to be able to ClearThing the stuff */
  349. define tp_mall proc garbageDrop(thing th)status:
  350.     thing carryer;
  351.     string name;
  352.  
  353.     if Owner(th) = SysAdmin or Mine(th) then
  354.     carryer := th@p_oCarryer;
  355.     if carryer ~= nil then
  356.         if th@p_oCreator = Me() or th@p_oCreator = CharacterThing(SysAdmin)
  357.         then
  358.         name := FormatName(th@p_oName);
  359.         ZapObject(th);
  360.         if not carryer@p_pHidden then
  361.             ABPrint(r_garbageRoom, carryer, carryer,
  362.             Capitalize(CharacterNameG(carryer)) +
  363.             AAn(" drops", name) + " which vanishes!\n");
  364.         else
  365.             ABPrint(r_garbageRoom, carryer, carryer,
  366.             Capitalize(AAn("", name)) +
  367.             " appears, drops, and vanishes!\n");
  368.         fi;
  369.         SPrint(carryer, "You drop the " + name + " which vanishes!\n");
  370.         DelElement(carryer@p_pCarrying, th);
  371.         /* we do NOT want to continue with the normal drop actions */
  372.         succeed
  373.         else
  374.         continue
  375.         fi
  376.     else
  377.         continue
  378.     fi
  379.     else
  380.     continue
  381.     fi
  382. corp;
  383. AddRoomDropChecker(r_garbageRoom, garbageDrop, false)$
  384. define tp_mall proc garbageSmell()status: continue corp;  /* replaced later */
  385. define tp_mall proc garbageSmellDisable()status:
  386.     if Here() ~= r_garbageRoom then
  387.     Print("Your nose is still disabled!\n");
  388.     Me() -- p_pSmellChecker;
  389.     succeed
  390.     else
  391.     garbageSmell()
  392.     fi
  393. corp;
  394. replace garbageSmell()status:
  395.     if It() = nil then
  396.     Print("This room smells distinctly like a garbage room!\n");
  397.     else
  398.     Print("You can't smell the ");
  399.     Print(FormatName(It()@p_oName));
  400.     Print(" over the smell of this room!\n");
  401.     fi;
  402.     Me()@p_pSmellChecker := garbageSmellDisable;
  403.     succeed
  404. corp;
  405. r_garbageRoom@p_oSmellChecker := garbageSmell$
  406. r_garbageRoom@p_rNoGoString := "You must go through the doors."$
  407. RoomGraphics(r_garbageRoom, "Garbage", "Room", MALL_MAP_GROUP,
  408.          0.119, 0.285, drawMiniMall)$
  409.  
  410. /* lost and found room is created in util2.m */
  411. Connect(r_miniMall, r_lostAndFound, D_WEST)$
  412. UniConnect(r_lostAndFound, r_miniMall, D_EXIT)$
  413. r_lostAndFound@p_rNoGoString := "You must go through the doors."$
  414. RoomGraphics(r_lostAndFound, "Lost & Found", "Room", MALL_MAP_GROUP,
  415.          0.109, 0.505, drawMiniMall)$
  416.  
  417. /*
  418.  * The beauty shop allows a number of additional activities. Non-graphics
  419.  * players can REGISTER to change their description. Graphics players are given
  420.  * a couple of extra on-screen buttons, which call up the icon editor in
  421.  * 'icons.m' to edit their icon or cursor. A third button allows editing
  422.  * their description via the remote client. There is also use of the voice
  423.  * synthesis when you enter the room.
  424.  */
  425.  
  426. define tp_mall ICON_BUTTON    100$
  427. define tp_mall CURSOR_BUTTON    101$
  428. define tp_mall DESC_BUTTON    102$
  429. define tp_mall BEAUTY_SPEECH_ID NextSoundEffectId()$
  430. define tp_mall proc addBeautyButtons()void:
  431.     int xBase, yBase;
  432.  
  433.     xBase := GCols(nil) * 3 / 4;
  434.     yBase := GRows(nil) / 2;
  435.     AddButtonPixels(xBase - 74, yBase + 33,   ICON_BUTTON, "Icon"  );
  436.     AddButtonPixels(xBase - 28, yBase + 33, CURSOR_BUTTON, "Cursor");
  437.     AddButtonPixels(xBase + 33, yBase + 33,   DESC_BUTTON, "Desc"  );
  438.     Me()@p_pStandardButtonsNow := false;
  439. corp;
  440. define tp_mall proc eraseBeautyButtons()void:
  441.     EraseButton(ICON_BUTTON);
  442.     EraseButton(CURSOR_BUTTON);
  443.     EraseButton(DESC_BUTTON);
  444.     Me()@p_pStandardButtonsNow := true;
  445.     AbortEffect(nil, EFFECT_SPEECH, BEAUTY_SPEECH_ID);
  446. corp;
  447. define tp_mall proc beautySpeak()void:
  448.     /* if voice is not on, will not do this */
  449.     VParams(nil, 160, 250, 0, 1, 64);
  450.     VNarrate(nil,
  451.     "GUH4D DEY3. REHJIHSTER TUW CHEY1NCH YOHR DIYSKRIH1PSHUN.",
  452.     BEAUTY_SPEECH_ID);
  453.     VReset(nil);
  454. corp;
  455. define tp_mall r_beautyShop CreateThing(r_indoors)$
  456. SetupRoom(r_beautyShop, "in the beauty shop",
  457.     "You can REGISTER here to have your appearance changed.")$
  458. define tp_mall proc utility beautyEnd(string s)void:
  459.     string name;
  460.     thing me;
  461.  
  462.     if s = "" then
  463.     Print("Description not changed.\n");
  464.     else
  465.     me := Me();
  466.     name := Capitalize(me@p_pName);
  467.     OPrint(name + " has just been made over.\n");
  468.     s := name + " " + s;
  469.     me@p_pDesc := s;
  470.     /* note the uses of NPrint! */
  471.     NPrint("Nip! Tuck! Snip-snip! All done. "
  472.         "When people look at you now, they will see:\n"
  473.     );
  474.     NPrint(s + "\n");
  475.     fi;
  476.     if Here() = r_beautyShop then
  477.     /* Were removed when DESC button hit. No-op if no graphics. */
  478.     addBeautyButtons();
  479.     fi;
  480. corp;
  481. /* this is not 'utility' so that we don't get '@'s on the output */
  482. define tp_mall proc beautyRegister()bool:
  483.     thing me;
  484.     string name;
  485.     int len;
  486.     bool res;
  487.  
  488.     me := Me();
  489.     name := me@p_pName;
  490.     OPrint(Capitalize(name) + " decides to get a makeover.\n");
  491.     len := Length(name) + 1;
  492.     name := me@p_pDesc;
  493.     name := SubString(name, len, Length(name) - len);
  494.     res := GetDocument("beauty> ", "Enter your new description", name,
  495.                beautyEnd, false);
  496.     if not res then
  497.     /* Buttons were removed when DESC button hit. No-op if no graphics. */
  498.     addBeautyButtons();
  499.     fi;
  500.     res
  501. corp;
  502. r_beautyShop@p_rRegisterAction := beautyRegister$
  503. Connect(r_miniMall, r_beautyShop, D_SOUTHWEST)$
  504. UniConnect(r_beautyShop, r_miniMall, D_EXIT)$
  505. r_beautyShop@p_rNoGoString := "You must go through the doors."$
  506. RoomGraphics(r_beautyShop, "Beauty", "Shop", MALL_MAP_GROUP,
  507.          0.119, 0.725, drawMiniMall)$
  508. define tp_mall p_pBeautyHandlerSave CreateActionProp()$
  509. define tp_mall p_pInIconEdit CreateBoolProp()$
  510. define tp_mall proc beautyReset()void: corp;    /* replaced later */
  511. define tp_mall proc beautyRestore()void:
  512.     thing me;
  513.  
  514.     me := Me();
  515.     me -- p_pInIconEdit;
  516.     me@p_MapGroup := NO_MAP_GROUP;
  517.     EnterRoomDraw();
  518.     if Here() ~= r_beautyShop then
  519.     beautyReset();
  520.     elif me@p_pBeautyHandlerSave ~= nil then
  521.     addBeautyButtons();
  522.     /* otherwise, called from EndIconEdit called from beautyReset */
  523.     fi;
  524. corp;
  525. define tp_mall proc beautyButtonHandler(int whichButton)void:
  526.  
  527.     if whichButton = ICON_BUTTON then
  528.     eraseBeautyButtons();
  529.     Me()@p_pInIconEdit := true;
  530.     StartIconEdit(beautyRestore);
  531.     elif whichButton = CURSOR_BUTTON then
  532.     eraseBeautyButtons();
  533.     Me()@p_pInIconEdit := true;
  534.     StartCursorEdit(beautyRestore);
  535.     elif whichButton = DESC_BUTTON then
  536.     eraseBeautyButtons();
  537.     ignore beautyRegister();
  538.     else
  539.     call(Me()@p_pBeautyHandlerSave, void)(whichButton);
  540.     fi;
  541. corp;
  542. define tp_mall proc beautyActiveHandler()void:
  543.     action a;
  544.  
  545.     /* if graphics is not on, will not do the buttons */
  546.     addBeautyButtons();
  547.     a := SetCharacterButtonAction(beautyButtonHandler);
  548.     /* The handler could already have been set if the character was in
  549.        the Beauty Shop when a backup was made, and the server later runs
  550.        from that backup. */
  551.     if a ~= beautyButtonHandler then
  552.     Me()@p_pBeautyHandlerSave := a;
  553.     fi;
  554.     Me() -- p_pInIconEdit;
  555.     beautySpeak();
  556. corp;
  557. define tp_mall proc beautyEnter()status:
  558.     thing me;
  559.  
  560.     me := Me();
  561.     if me@p_pStandardButtonsNow and not me@p_pInIconEdit then
  562.     if not Editing() then
  563.         addBeautyButtons();
  564.     fi;
  565.     me@p_pBeautyHandlerSave :=
  566.         SetCharacterButtonAction(beautyButtonHandler);
  567.     AddHead(me@p_pEnterActions, beautyActiveHandler);
  568.     fi;
  569.     beautySpeak();
  570.     continue
  571. corp;
  572. define tp_mall proc beautyExit()status:
  573.     beautyReset();
  574.     AbortEffect(nil, EFFECT_SPEECH, BEAUTY_SPEECH_ID);
  575.     continue
  576. corp;
  577. replace beautyReset()void:
  578.     thing me;
  579.     action a;
  580.  
  581.     me := Me();
  582.     a := me@p_pBeautyHandlerSave;
  583.     if a ~= nil then
  584.     /* delete this property *before* calling EndIconEdit */
  585.     me -- p_pBeautyHandlerSave;
  586.     if me@p_pInIconEdit then
  587.         EndIconEdit();
  588.     else
  589.         eraseBeautyButtons();
  590.     fi;
  591.     ignore SetCharacterButtonAction(a);
  592.     DelElement(me@p_pEnterActions, beautyActiveHandler);
  593.     fi;
  594. corp;
  595. AddAnyEnterChecker(r_beautyShop, beautyEnter, false)$
  596. AddAnyLeaveChecker(r_beautyShop, beautyExit, false)$
  597.  
  598. /*
  599.  * The store in the mall has a number of items for sale. The fanciest is
  600.  * the camera. Also note the universal carryall, which is a container with
  601.  * no restrictions on what you can put into it.
  602.  */
  603.  
  604. define tp_mall r_mallStore CreateThing(r_indoors)$
  605. SetupRoom(r_mallStore, "in a small store",
  606.     "You can SHOP for supplies here.")$
  607. AddForSale(r_mallStore, "pen;ballpoint.pen;ball,point",
  608.     "There is nothing special about the ballpoint pen. It will "
  609.     "provide a lifetime of trouble-free writing.",
  610.     1, nil)@p_Image := "Town/pen"$
  611. AddForSale(r_mallStore, "pad,paper;writing.paper;pad,of",
  612.     "The writing pad is quite ordinary. It provides an "
  613.     "endless supply of sheets to write on.",
  614.     1, nil)@p_Image := "Town/pad"$
  615. define tp_mall o_carryall AddForSale(r_mallStore, "carryall;universal",
  616.     "The universal carryall is a somewhat magical item. You can put as much "
  617.     "stuff, of any size and shape, as you want into it.",
  618.     1000, nil)$
  619. o_carryall@p_oContents := CreateThingList()$
  620. o_carryall@p_oCapacity := 1000000$
  621. o_carryall@p_Image := "Town/carryall"$
  622.  
  623. define tp_mall o_lamp AddForSale(r_mallStore,
  624.     "lamp;everlight.switch;push-button,push,button,on-off,on,off",
  625.     "The everlight lamp is a small ovoid made of some indeterminate material. "
  626.     "It has an opening on the front through which soft white light is "
  627.     "emitted. There seems to be no identifiable power source. There is a "
  628.     "push-button on-off switch in the middle of it.",
  629.     5000, nil)$
  630. o_lamp@p_oActivateChecker := ActiveLightObject$
  631. o_lamp@p_oLightChecker := ActiveLightObject$
  632. o_lamp@p_oDeActivateChecker := ActiveUnLightObject$
  633. o_lamp@p_oExtinguishChecker := ActiveUnLightObject$
  634. o_lamp@p_Image := "Town/lamp"$
  635. define tp_mall proc lampPutIn(thing lamp, container)status:
  636.     if lamp@p_oLight then
  637.     lamp@p_oLight := false;
  638.     RemoveLight();
  639.     lamp@p_oLight := true;
  640.     fi;
  641.     continue
  642. corp;
  643. o_lamp@p_oPutMeInChecker := lampPutIn$
  644. define tp_mall proc lampTakeFrom(thing lamp, container)status:
  645.     if lamp@p_oLight then
  646.     AddLight();
  647.     fi;
  648.     continue
  649. corp;
  650. o_lamp@p_oTakeMeFromChecker := lampTakeFrom$
  651.  
  652. define tp_mall p_oShotsLeft CreateIntProp()$
  653. define tp_mall proc cameraDesc()string:
  654.     int n;
  655.  
  656.     n := It()@p_oShotsLeft;
  657.     "The instant camera is an ugly box-like contraption with a small lens on "
  658.     "one side and a big slot for the pictures at the bottom. There is a "
  659.     "flash attachment on top. It appears to be quite functional. "
  660.     "You can use it with the 'photograph' or 'snap' commands. "
  661.     "You can take pictures of the current location, of objects, or of "
  662.     "people/animals. The little indicator shows that the camera has " +
  663.     if n = 1 then
  664.         "one shot"
  665.     elif n = 0 then
  666.         "no shots"
  667.     else
  668.         IntToString(n) + " shots"
  669.     fi +
  670.     " left."
  671. corp;
  672. define tp_mall o_camera AddForSale(r_mallStore, "camera;instant", "", 50, nil)$
  673. o_camera@p_oDescAction := cameraDesc$
  674. o_camera@p_Image := "Town/camera"$
  675. o_camera@p_oShotsLeft := 12$
  676. MakeStore(r_mallStore)$
  677. Connect(r_miniMall, r_mallStore, D_SOUTH)$
  678. UniConnect(r_mallStore, r_miniMall, D_EXIT)$
  679. r_mallStore@p_rNoGoString := "You must go through the doors."$
  680. RoomGraphics(r_mallStore, "Small", "Store", MALL_MAP_GROUP,
  681.          0.256, 0.764, drawMiniMall)$
  682.  
  683. /*
  684.  * Code to implement photographs and photography. This code should really
  685.  * go elsewhere, but I'm not sure where.
  686.  */
  687.  
  688. /* o_photograph is in tp_misc since it is used in bguild.m */
  689. define tp_misc o_photograph CreateThing(nil)$
  690. o_photograph@p_oHome := r_garbageRoom$
  691. o_photograph@p_Image := "Town/photo"$
  692. define tp_mall proc createPhotograph(string name, desc)thing:
  693.     string noun, adj;
  694.     thing photo, me;
  695.     int i;
  696.  
  697.     if name = "" then
  698.     name := "photograph.photo.picture.snapshot";
  699.     else
  700.     name := FormatName(name);
  701.     name := GetNounPhrase(G, name, 0);
  702.     i := Index(name, ";");
  703.     if i = -1 then
  704.         name := name + ";photograph,of." + name + ";photo,of." +
  705.             name + ";picture,of." + name + ";snapshot,of." +
  706.             "photograph.photo.picture.snapshot";
  707.     else
  708.         noun := SubString(name, 0, i);
  709.         adj := SubString(name, i + 1, Length(name) - i - 1);
  710.         name := noun + ";photograph,of," + adj + "." +
  711.             noun + ";picture,of," + adj + "." +
  712.             noun + ";photo,of," + adj + "." +
  713.             noun + ";snapshot,of," + adj +
  714.             ".photograph.photo.picture.snapshot";
  715.     fi;
  716.     fi;
  717.     me := Me();
  718.     Print("Click - FLASH!!\n");
  719.     OPrint("FLASH! - " + CharacterNameG(me) + " takes a photograph.\n");
  720.     photo := CreateThing(o_photograph);
  721.     photo@p_oCarryer := me;
  722.     photo@p_oCreator := me;
  723.     photo@p_oName := name;
  724.     photo@p_oDesc := desc;
  725.     SetThingStatus(photo, ts_public);
  726.     GiveThing(photo, SysAdmin);
  727.     AddTail(me@p_pCarrying, photo);
  728.     photo
  729. corp;
  730.  
  731. define tp_mall proc v_photograph(string what)bool:
  732.     thing here, camera, object;
  733.     action a;
  734.     string name, desc, ambig, read;
  735.     int count, dir;
  736.     status st;
  737.     bool wasScenery;
  738.  
  739.     here := Here();
  740.     if FindChildOnList(Me()@p_pCarrying, o_camera) then
  741.     camera := FindResult();
  742.     count := camera@p_oShotsLeft;
  743.     if count = 0 then
  744.         Print("The camera has no shots left.\n");
  745.         false
  746.     elif what = "" then
  747.         /* taking a picture of the current location */
  748.         a := here@p_rNameAction;
  749.         if a ~= nil then
  750.         name := call(a, string)();
  751.         else
  752.         name := here@p_rName;
  753.         fi;
  754.         name := name + ".";
  755.         a := here@p_rDescAction;
  756.         if a ~= nil then
  757.         name := name + "\n";
  758.         desc := call(a, string)();
  759.         elif here@p_rDesc ~= "" then
  760.         name := name + "\n";
  761.         desc := here@p_rDesc;
  762.         else
  763.         desc := "";
  764.         fi;
  765.         camera@p_oShotsLeft := count - 1;
  766.         ignore createPhotograph("",
  767.         "This photograph was taken " + name + desc);
  768.         true
  769.     else
  770.         object := FindAgent(what);
  771.         if object ~= nil then
  772.         a := object@p_pDescAction;
  773.         if a ~= nil then
  774.             SetIt(object);
  775.             desc := call(a, string)();
  776.         elif object@p_pDesc ~= "" then
  777.             desc := object@p_pDesc;
  778.         else
  779.             desc := name + "is a nondescript adventurer.";
  780.         fi;
  781.         camera@p_oShotsLeft := count - 1;
  782.         ignore createPhotograph(CharacterNameG(object), desc);
  783.         true
  784.         else
  785.         dir := DirMatch(what);
  786.         if dir ~= -1 then
  787.             desc := here@(DirDesc(dir));
  788.             if desc = "" then
  789.             desc := "The photograph shows nothing special.";
  790.             else
  791.             desc := desc;
  792.             fi;
  793.             camera@p_oShotsLeft := count - 1;
  794.             ignore createPhotograph("", desc);
  795.             true
  796.         else
  797.             /* player is photographing an object */
  798.             name := FormatName(what);
  799.             object := nil;
  800.             wasScenery := false;
  801.             ambig := " is ambiguous here.\n";
  802.             st := FindName(Me()@p_pCarrying, p_oName, what);
  803.             if st = fail then
  804.             st := FindName(here@p_rContents, p_oName, what);
  805.             if st = fail then
  806.                 if MatchName(here@p_rScenery, what) ~= -1 then
  807.                 wasScenery := true;
  808.                 else
  809.                 Print(IsAre("There", "no", name, "here.\n"));
  810.                 fi;
  811.             elif st = continue then
  812.                 Print(name);
  813.                 Print(ambig);
  814.             else
  815.                 object := FindResult();
  816.             fi;
  817.             elif st = continue then
  818.             Print(name);
  819.             Print(ambig);
  820.             else
  821.             object := FindResult();
  822.             fi;
  823.             if object = nil then
  824.             if wasScenery then
  825.                 camera@p_oShotsLeft := count - 1;
  826.                 ignore createPhotograph(what,
  827.                 "The photograph shows nothing special.");
  828.                 true
  829.             else
  830.                 false
  831.             fi
  832.             elif object = camera then
  833.             Print("No matter how you twist or turn it, you "
  834.                 "cannot get the camera to take a picture of "
  835.                 "itself.\n");
  836.             false
  837.             else
  838.             a := object@p_oDescAction;
  839.             if a ~= nil then
  840.                 SetIt(object);
  841.                 desc := call(a, string)();
  842.             elif object@p_oDesc ~= "" then
  843.                 desc := object@p_oDesc;
  844.             else
  845.                 desc := "The photograph shows nothing special.";
  846.             fi;
  847.             a := object@p_oReadAction;
  848.             if a ~= nil then
  849.                 read := call(a, string)();
  850.             elif object@p_oReadString ~= "" then
  851.                 read := object@p_oReadString;
  852.             else
  853.                 read := "";
  854.             fi;
  855.             camera@p_oShotsLeft := count - 1;
  856.             object := createPhotograph(what, desc);
  857.             if read ~= "" then
  858.                 object@p_oReadString := read;
  859.             fi;
  860.             true
  861.             fi
  862.         fi
  863.         fi
  864.     fi
  865.     else
  866.     Print("You don't have a camera!\n");
  867.     false
  868.     fi
  869. corp;
  870.  
  871. Verb1(G, "photograph", 0, v_photograph)$
  872. Synonym(G, "photograph", "photo")$
  873. Synonym(G, "photograph", "snap")$
  874.  
  875. /*
  876.  * The bank in the minimall uses the bank code from 'util2.m', and uses
  877.  * speech when you enter it.
  878.  */
  879.  
  880. define tp_mall BANK_SPEECH_ID NextSoundEffectId()$
  881. define tp_mall r_mallBank CreateThing(r_indoors)$
  882. SetupRoom(r_mallBank, "in a small local bank",
  883.     "You can use the commands 'deposit <amount>', 'withdraw <amount>' and "
  884.     "'balance' here.")$
  885. Connect(r_miniMall, r_mallBank, D_SOUTHEAST)$
  886. UniConnect(r_mallBank, r_miniMall, D_EXIT)$
  887. MakeBank(r_mallBank)$
  888. r_mallBank@p_rNoGoString := "You must go through the doors."$
  889. RoomGraphics(r_mallBank, "Bank", "", MALL_MAP_GROUP,
  890.          0.388, 0.725, drawMiniMall)$
  891. define tp_mall proc bankSay()status:
  892.     if VOn(nil) then
  893.     VParams(nil, 150, 120, 0, 0, 64);
  894.     VNarrate(nil,
  895.         "WEH5LKAHM KAH4STAHMER. DIH4PAAZIHT MAH4NIY TUWDEY1.",
  896.         BANK_SPEECH_ID);
  897.     VReset(nil);
  898.     fi;
  899.     continue
  900. corp;
  901. AddAnyEnterChecker(r_mallBank, bankSay, false)$
  902. define tp_mall proc bankExit()status:
  903.     if VOn(nil) then
  904.     AbortEffect(nil, EFFECT_SPEECH, BANK_SPEECH_ID);
  905.     fi;
  906.     continue
  907. corp;
  908. AddAnyLeaveChecker(r_mallBank, bankExit, false)$
  909.  
  910. /*
  911.  * The service tunnels under the plate in the mall entrance are mostly
  912.  * description and scenery, although there is a door to open, and you get
  913.  * 100 blutos at the far end.
  914.  */
  915.  
  916. /* actual room thing created earlier */
  917.  
  918. SetupRoom(r_underPlate, "in a small, cramped space under the passageway",
  919.     "Immediately over your head is a metal plate which can be lifted to "
  920.     "allow you to exit. The walls of this chamber are of stained concrete "
  921.     "blocks. The floor is of cracked, dirty concrete. A round shaft heads "
  922.     "down into darkness. There are rusty metal rungs embedded in one side "
  923.     "of the shaft.")$
  924. Scenery(r_underPlate,
  925.     "floor,concrete;cracked,dirty,concrete,of."
  926.     "wall,block;stained,concrete,block."
  927.     "shaft;round."
  928.     "rung;rusty,metal."
  929.     "hinge."
  930.     "handle;small,recessed")$
  931. AutoGraphics(r_underPlate, AutoTunnels)$
  932. AutoPens(r_underPlate, C_DARK_BROWN, C_LIGHT_GREY, 0, 0)$
  933. define tp_mall o_entrancePlate2 CreateThing(o_entrancePlate)$    /* inherit */
  934. SetThingStatus(o_entrancePlate2, ts_wizard)$
  935. AddTail(r_underPlate@p_rContents, o_entrancePlate2)$
  936. r_underPlate@p_rUpDesc :=
  937.     "There is a 3 foot square metal plate in the ceiling. It looks like "
  938.     "it can be raised on its hinges."$
  939. define tp_mall proc plateLift3()status:
  940.     Print("You lift the plate, climb up to the passageway, and lower the "
  941.     "plate back into place.\n");
  942.     LeaveRoomStuff(r_mallEntrance, D_UP, MOVE_NORMAL);
  943.     EnterRoomStuff(r_mallEntrance, D_DOWN, MOVE_SPECIAL);
  944.     if Me()@p_pHidden then
  945.     OPrint("The metal plate in the floor lifts up,"
  946.         " then lowers back into place.\n");
  947.     else
  948.     OPrint("The metal plate in the floor lifts up and " +
  949.         Capitalize(CharacterNameG(Me())) +
  950.         " emerges and lowers the plate back into place.\n");
  951.     fi;
  952.     succeed
  953. corp;
  954. o_entrancePlate2@p_oLiftChecker := plateLift3$
  955. o_entrancePlate2@p_oOpenChecker := plateLift3$
  956. o_entrancePlate2@p_Image := "Town/plateBottom"$
  957.  
  958. define tp_mall r_underMall CreateThing(r_indoors)$
  959. SetThingStatus(r_underMall, ts_readonly)$
  960. AutoGraphics(r_underMall, AutoTunnels)$
  961. AutoPens(r_underMall, C_DARK_BROWN, C_LIGHT_GREY, 0, 0)$
  962.  
  963. define tp_mall r_underMall1 CreateThing(r_underMall)$
  964. SetupRoomD(r_underMall1, "at the end of a passageway",
  965.     "A low, narrow passageway from the northwest ends here. A round shaft "
  966.     "with metal wrungs on one side leads upward.")$
  967. Connect(r_underPlate, r_underMall1, D_DOWN)$
  968. Scenery(r_underMall1, "shaft;round.wrung;rusty,metal")$
  969.  
  970. define tp_mall r_underMall2 CreateThing(r_underMall)$
  971. SetupRoomD(r_underMall2, "at a corner in a passageway", "")$
  972. Connect(r_underMall1, r_underMall2, D_NORTHWEST)$
  973.  
  974. define tp_mall r_underMall3 CreateThing(r_underMall)$
  975. SetupRoomD(r_underMall3, "at the end of a passageway",
  976.     "The passage extends to the east, and a steep staircase leads downwards.")$
  977. Connect(r_underMall2, r_underMall3, D_WEST)$
  978. Scenery(r_underMall3, "stair,staircase;steep")$
  979.  
  980. define tp_mall r_serviceTunnel CreateThing(r_indoors)$
  981. r_serviceTunnel@p_oListenString :=
  982.     "The noise of machinery and active pipes is fairly loud here."$
  983. r_serviceTunnel@p_oSmellString :=
  984.     "You can smell a faint smell of machine oil and ozone. It is also "
  985.     "quite warm in here."$
  986. Scenery(r_serviceTunnel, "pipe;large,active.machinery,machine")$
  987. SetThingStatus(r_serviceTunnel, ts_readonly)$
  988. define tp_mall r_underMall5 CreateThing(r_serviceTunnel)$
  989. define tp_mall UTILITY_TUNNEL_ID NextEffectId()$
  990. define tp_mall proc drawUtilityTunnel()void:
  991.  
  992.     if not KnowsEffect(nil, UTILITY_TUNNEL_ID) then
  993.     DefineEffect(nil, UTILITY_TUNNEL_ID);
  994.     GSetImage(nil, "Town/utilityTunnel");
  995.     IfFound(nil);
  996.         ShowCurrentImage();
  997.     Else(nil);
  998.         GSetPen(nil, C_DARK_BROWN);
  999.         GAMove(nil, 0.0, 0.0);
  1000.         GRectangle(nil, 0.5, 1.0, true);
  1001.         GSetPen(nil, C_LIGHT_GREY);
  1002.         GAMove(nil, 0.20313, 0.0);
  1003.         GRectangle(nil, 0.09375, 1.0, true);
  1004.         GSetPen(nil, C_RED_ORANGE);
  1005.         GAMove(nil, 0.30312, 0.0);
  1006.         GRectangle(nil, 0.00312, 1.0, true);
  1007.         GSetPen(nil, C_DARK_GREEN);
  1008.         GAMove(nil, 0.19375, 0.0);
  1009.         GRectangle(nil, 0.00312, 1.0, true);
  1010.         GSetPen(nil, C_BLUE);
  1011.         GAMove(nil, 0.1875, 0.0);
  1012.         GRectangle(nil, 0.00312, 1.0, true);
  1013.         GSetPen(nil, C_CADMIUM_YELLOW);
  1014.         GAMove(nil, 0.3125, 0.0);
  1015.         GRDraw(nil, 0.0, 1.0);
  1016.         GAMove(nil, 0.31875, 0.0);
  1017.         GRDraw(nil, 0.0, 1.0);
  1018.     Fi(nil);
  1019.     EndEffect();
  1020.     fi;
  1021.     CallEffect(nil, UTILITY_TUNNEL_ID);
  1022. corp;
  1023.  
  1024. define tp_mall r_underMall4 CreateThing(r_indoors)$
  1025. SetupRoomD(r_underMall4, "at the bottom of some steep stairs",
  1026.     "The stairs head up to the east, but the west is blocked by a heavy "
  1027.     "metal door. The door has a sign reading \"Authorized Personnel Only\", "
  1028.     "but it does not appear to be locked.")$
  1029. Connect(r_underMall3, r_underMall4, D_DOWN)$
  1030. Connect(r_underMall3, r_underMall4, D_WEST)$
  1031. Sign(r_underMall4, "sign;security,door",
  1032.     "The sign is red with white lettering, and is firmly attached to the "
  1033.     "door.",
  1034.     "\"Authorized Personnel Only\"")$
  1035. define tp_mall o_securityDoor CreateThing(nil)$
  1036. FakeModel(o_securityDoor, "door;heavy,metal,security",
  1037.     "The door is painted grey, but many scratches and dents show the metal "
  1038.     "underneath.")$
  1039. o_securityDoor@p_oCloseString := "The door is already closed."$
  1040. o_securityDoor@p_oNotLockable := true$
  1041. define tp_mall o_securityDoor1 CreateThing(o_securityDoor)$
  1042. AddTail(r_underMall4@p_rContents, o_securityDoor1)$
  1043. Scenery(r_underMall4, "lettering,letter;white.scratch.scratches.dent.metal")$
  1044. o_securityDoor1@p_oListenString :=
  1045.     "You hear machine-like noises coming through the door."$
  1046. o_securityDoor1@p_Image := "Town/SecurityDoor1"$
  1047. define tp_mall proc openSecurityDoor1()status:
  1048.     Print("You open the door and pass through. As you do, you are hit with a "
  1049.     "blast of warm air, light and noise.\n");
  1050.     ignore EnterRoom(r_underMall5, D_WEST, MOVE_NORMAL);
  1051.     succeed
  1052. corp;
  1053. o_securityDoor1@p_oOpenChecker := openSecurityDoor1$
  1054. define tp_mall SECURITY_DOOR_ID NextEffectId()$
  1055. define tp_mall proc drawOutsideDoor()void:
  1056.  
  1057.     if not KnowsEffect(nil, SECURITY_DOOR_ID) then
  1058.     DefineEffect(nil, SECURITY_DOOR_ID);
  1059.     GSetImage(nil, "Town/securityDoor");
  1060.     IfFound(nil);
  1061.         ShowCurrentImage();
  1062.     Else(nil);
  1063.         GSetPen(nil, C_DARK_BROWN);
  1064.         GAMove(nil, 0.0, 0.0);
  1065.         GRectangle(nil, 0.5, 1.0, true);
  1066.         GSetPen(nil, C_LIGHT_GREY);
  1067.         GAMove(nil, 0.207, 0.425);
  1068.         GRectangle(nil, 0.294, 0.155, true);
  1069.         GSetPen(nil, C_DARK_GREY);
  1070.         GAMove(nil, 0.205, 0.46);
  1071.         VerticalDoor();
  1072.     Fi(nil);
  1073.     EndEffect();
  1074.     fi;
  1075.     CallEffect(nil, SECURITY_DOOR_ID);
  1076. corp;
  1077. AutoGraphics(r_underMall4, drawOutsideDoor)$
  1078.  
  1079. SetupRoom(r_underMall5, "in a pit in the tunnel floor",
  1080.     "Above you is the metal floor of the utility tunnel. Steep metal stairs "
  1081.     "lead up to a trapdoor in the floor. To your east is a metal security "
  1082.     "door.")$
  1083. define tp_mall o_securityDoor2 CreateThing(o_securityDoor)$
  1084. AddTail(r_underMall5@p_rContents, o_securityDoor2)$
  1085. define tp_mall proc openSecurityDoor2()status:
  1086.     Print("You open the door and pass through.\n");
  1087.     ignore EnterRoom(r_underMall4, D_EAST, MOVE_NORMAL);
  1088.     succeed
  1089. corp;
  1090. o_securityDoor2@p_oOpenChecker := openSecurityDoor2$
  1091. o_securityDoor2@p_Image := "Town/SecurityDoor2"$
  1092. Scenery(r_underMall5, "stair,floor,grill,grillwork;steep,metal."
  1093.     "dent.scratch.scratches.metal.pipe.machinery,machine")$
  1094. define tp_mall o_trapDoor CreateThing(nil)$
  1095. FakeObject(o_trapDoor, r_underMall5, "door;trap.trapdoor", "")$
  1096. o_trapDoor@p_oOpenString := "The trapdoor is already open."$
  1097. o_trapDoor@p_oCloseString := "The trapdoor cannot be closed."$
  1098. o_trapDoor@p_oNotLockable := true$
  1099. o_trapDoor@p_Image := "Town/trapdoor"$
  1100. define tp_mall UTILITY_PIT_ID NextEffectId()$
  1101. define tp_mall proc drawInsideDoor()void:
  1102.  
  1103.     if not KnowsEffect(nil, UTILITY_PIT_ID) then
  1104.     DefineEffect(nil, UTILITY_PIT_ID);
  1105.     GSetImage(nil, "Town/utilityPit");
  1106.     IfFound(nil);
  1107.         ShowCurrentImage();
  1108.     Else(nil);
  1109.         GSetPen(nil, C_DARK_BROWN);
  1110.         GAMove(nil, 0.0, 0.0);
  1111.         GRectangle(nil, 0.5, 1.0, true);
  1112.         GSetPen(nil, C_LIGHT_GREY);
  1113.         GAMove(nil, 0.20313, 0.41);
  1114.         GRectangle(nil, 0.09375, 0.18, true);
  1115.         GSetPen(nil, C_DARK_GREY);
  1116.         GAMove(nil, 0.29688, 0.46);
  1117.         VerticalDoor();
  1118.         DrawUpArrow(C_GOLD);
  1119.     Fi(nil);
  1120.     EndEffect();
  1121.     fi;
  1122.     CallEffect(nil, UTILITY_PIT_ID);
  1123. corp;
  1124. AutoGraphics(r_underMall5, drawInsideDoor)$
  1125. RoomName(r_underMall5, "Pit", "")$
  1126.  
  1127. define tp_mall r_underMall6 CreateThing(r_serviceTunnel)$
  1128. SetupRoom(r_underMall6, "in a north-south utility tunnel",
  1129.     "Large pipes and cable trays line both walls of the tunnel. It is quite "
  1130.     "warm and fairly noisy in here. The floor here is a metal grillwork over "
  1131.     "a small pit. There is a trapdoor in the grillwork and you can make out "
  1132.     "a staircase going down beneath it.")$
  1133. Connect(r_underMall5, r_underMall6, D_UP)$
  1134. Scenery(r_underMall6,
  1135.     "grill;metal.grillwork;metal."
  1136.     "tray;cable,large."
  1137.     "floor,grill,grillwork,stair,staircase;steep,metal,grill,grillwork."
  1138.     "wall;both."
  1139.     "pit;small")$
  1140. AddTail(r_underMall6@p_rContents, o_trapDoor)$
  1141. define tp_mall UTILITY_START_ID NextEffectId()$
  1142. define tp_mall proc drawAbovePit()void:
  1143.     int i;
  1144.  
  1145.     if not KnowsEffect(nil, UTILITY_START_ID) then
  1146.     DefineEffect(nil, UTILITY_START_ID);
  1147.     GSetImage(nil, "Town/utilityStart");
  1148.     IfFound(nil);
  1149.         ShowCurrentImage();
  1150.     Else(nil);
  1151.         drawUtilityTunnel();
  1152.         GSetPen(nil, C_MEDIUM_GREY);
  1153.         GAMove(nil, 0.20313, 0.42);
  1154.         GRectangle(nil, 0.09375, 0.18, false);
  1155.         GAMove(nil, 0.2125, 0.422);
  1156.         for i from 0 upto 8 do
  1157.         GRDraw(nil, 0.0, 0.165);
  1158.         GRMove(nil, 0.01, -0.165);
  1159.         od;
  1160.     Fi(nil);
  1161.     EndEffect();
  1162.     fi;
  1163.     CallEffect(nil, UTILITY_START_ID);
  1164. corp;
  1165. AutoGraphics(r_underMall6, drawAbovePit)$
  1166. RoomName(r_underMall6, "Utility", "Tunnel")$
  1167.  
  1168. define t_mall r_underMall7 CreateThing(r_serviceTunnel)$
  1169. SetupRoomP(r_underMall7, "in a north-south utility tunnel",
  1170.     "You can go north, but the way south is blocked by a metal grill across "
  1171.     "the tunnel. The grill apparently divides the tunnel into separate "
  1172.     "sections.")$
  1173. Connect(r_underMall6, r_underMall7, D_SOUTH)$
  1174. Scenery(r_underMall7, "grill,grillwork;metal.tray;large,cable")$
  1175. define tp_mall UTILITY_SOUTH_ID NextEffectId()$
  1176. define tp_mall proc drawSouthEnd()void:
  1177.  
  1178.     if not KnowsEffect(nil, UTILITY_SOUTH_ID) then
  1179.     DefineEffect(nil, UTILITY_SOUTH_ID);
  1180.     GSetImage(nil, "Town/utilitySouth");
  1181.     IfFound(nil);
  1182.         ShowCurrentImage();
  1183.     Else(nil);
  1184.         drawUtilityTunnel();
  1185.         GSetPen(nil, C_MEDIUM_GREY);
  1186.         GAMove(nil, 0.20313, 0.59);
  1187.         GRDraw(nil, 0.09375, 0.0);
  1188.     Fi(nil);
  1189.     EndEffect();
  1190.     fi;
  1191.     CallEffect(nil, UTILITY_SOUTH_ID);
  1192. corp;
  1193. AutoGraphics(r_underMall7, drawSouthEnd)$
  1194. RoomName(r_underMall7, "Utility", "Tunnel")$
  1195.  
  1196. define t_mall r_underMall8 CreateThing(r_serviceTunnel)$
  1197. SetupRoomP(r_underMall8, "in a north-south utility tunnel",
  1198.     "This large concrete tunnel is used to carry utility services such as "
  1199.     "steam, hot and cold water, electricity, communications, etc.")$
  1200. Connect(r_underMall6, r_underMall8, D_NORTH)$
  1201. Scenery(r_underMall8, "tray;large,cable")$
  1202. AutoGraphics(r_underMall8, drawUtilityTunnel)$
  1203. RoomName(r_underMall8, "Utility", "Tunnel")$
  1204.  
  1205. define t_mall r_underMall9 CreateThing(r_serviceTunnel)$
  1206. SetupRoomP(r_underMall9, "in a north-south utility tunnel",
  1207.     "You can go south, but the way north is blocked by a metal grill across "
  1208.     "the tunnel. The grill apparently divides the tunnel into separate "
  1209.     "sections.")$
  1210. Connect(r_underMall8, r_underMall9, D_NORTH)$
  1211. Scenery(r_underMall9, "grill,grillwork;metal.tray;large,cable")$
  1212. define tp_mall giftGivenList CreateThingListProp()$
  1213. r_underMall9@giftGivenList := CreateThingList()$
  1214. define tp_mall proc checkForGift()status:
  1215.     thing me;
  1216.  
  1217.     me := Me();
  1218.     if FindElement(r_underMall9@giftGivenList, me) = -1 then
  1219.     AddTail(r_underMall9@giftGivenList, me);
  1220.     Print("You find 100 blutos!\n");
  1221.     me@p_pMoney := me@p_pMoney + 100;
  1222.     fi;
  1223.     continue
  1224. corp;
  1225. AddAnyEnterChecker(r_underMall9, checkForGift, false)$
  1226. define tp_mall UTILITY_NORTH_ID NextEffectId()$
  1227. define tp_mall proc drawNorthEnd()void:
  1228.  
  1229.     if not KnowsEffect(nil, UTILITY_NORTH_ID) then
  1230.     DefineEffect(nil, UTILITY_NORTH_ID);
  1231.     GSetImage(nil, "Town/utilityNorth");
  1232.     IfFound(nil);
  1233.         ShowCurrentImage();
  1234.     Else(nil);
  1235.         drawUtilityTunnel();
  1236.         GSetPen(nil, C_MEDIUM_GREY);
  1237.         GAMove(nil, 0.20313, 0.41);
  1238.         GRDraw(nil, 0.09375, 0.0);
  1239.     Fi(nil);
  1240.     EndEffect();
  1241.     fi;
  1242.     CallEffect(nil, UTILITY_NORTH_ID);
  1243. corp;
  1244. AutoGraphics(r_underMall9, drawNorthEnd)$
  1245. RoomName(r_underMall9, "Utility", "Tunnel")$
  1246.  
  1247. unuse tp_mall
  1248.