home *** CD-ROM | disk | FTP | other *** search
/ Amiga MA Magazine 1998 #7 / amigamamagazinepolishissue1998.iso / rozrywka / rpg / amigamud / src / scenario / mail.m < prev    next >
Text File  |  1997-08-07  |  24KB  |  849 lines

  1. /*
  2.  * Amiga MUD
  3.  *
  4.  * Copyright (c) 1997 by Chris Gray
  5.  */
  6.  
  7. /*
  8.  * mail.m - code to handle the mail system and the postman.
  9.  *    NOTE: rooms referenced directly:
  10.  *        r_mailRoom - several things
  11.  *        r_garbageRoom - home for letters
  12.  *        r_neEnd, r_esEnd, r_swEnd, r_wnEnd - mailboxes
  13.  *        r_mallEntrance - so Postman erases the recorder
  14.  *    NOTE: other direct references: recorderErase, o_recorder,
  15.  *        p_oReadString, p_rRegisterAction (both in verbs.m)
  16.  *    NOTE: because the mailroom is actually setup here, this file needs
  17.  *        to be sourced by the same player who owns the mailroom, or
  18.  *        the mailroom needs to be public. Normally, this file is
  19.  *        sourced by SysAdmin.
  20.  *    NOTE: we assume that all mailboxes are in lighted rooms, and that
  21.  *        the mailroom is lighted.
  22.  *    NOTE: MAX_CARRY is ignored for letters. This includes writing them,
  23.  *        the initial REGISTER and picking up new mail.
  24.  */
  25.  
  26. /*****************************************************************************\
  27. *                                          *
  28. *    This stuff here sets up the mail facility                  *
  29. *                                          *
  30. \*****************************************************************************/
  31.  
  32. use t_streets
  33.  
  34. private tp_mail CreateTable()$
  35. use tp_mail
  36.  
  37. define tp_mail MAX_BULLETINS 20$
  38.  
  39. define tp_mail p_pMailRegistered CreateBoolProp()$
  40. define tp_mail p_pLetterTarget CreateThingProp()$   /* also put on letters */
  41. define tp_mail p_oLetterSender CreateThingProp()$   /* so can change name */
  42. define tp_mail p_oLettersHere CreateThingListProp()$/* on boxes & mailRoom */
  43. define tp_mail p_oPostManRoute CreateStringProp()$  /* codes for moves */
  44. define tp_mail p_oPostManIndex CreateIntProp()$     /* index into the string */
  45. define tp_mail p_oPostManClearing CreateBoolProp()$ /* used to idle him */
  46. define tp_mail p_oPostManCleared CreateBoolProp()$  /* ditto */
  47. define tp_mail p_rNewLetter CreateBoolProp()$        /* flag mailroom for new */
  48. define tp_mail p_oPostManDelay CreateIntProp()$     /* delay before move */
  49. define tp_mail p_oBulletinDate CreateStringProp()$
  50. define tp_mail p_oBulletinNumber CreateIntProp()$
  51.  
  52. define tp_mail o_letter CreateThing(nil)$
  53. o_letter@p_oHome := r_garbageRoom$
  54. o_letter@p_Image := "Town/letter"$
  55. SetThingStatus(o_letter, ts_readonly)$
  56.  
  57. define tp_mail o_bulletin CreateThing(nil)$
  58. o_bulletin@p_oHome := r_garbageRoom$
  59. o_bulletin@p_Image := "Town/bulletin"$
  60. SetThingStatus(o_bulletin, ts_readonly)$
  61.  
  62. r_mailRoom@p_oLettersHere := CreateThingList()$
  63. r_mailRoom@p_rNewLetter := false$
  64.  
  65. define tp_mail proc mailboxGet(thing th)status:
  66.  
  67.     Print("The mailbox is firmly bolted down.\n");
  68.     OPrint(Capitalize(CharacterNameG(Me())) +
  69.     " tries to rip up the mailbox.\n");
  70.     fail
  71. corp;
  72.  
  73. define tp_mail o_mailbox CreateThing(nil)$
  74. SetThingStatus(o_mailbox, ts_readonly)$
  75. o_mailbox@p_oName := "mailbox;official.box;mail,official"$
  76. o_mailbox@p_oDesc :=
  77.     "The mailbox is bright red, with a slot in the top used for posting "
  78.     "letters. It is locked up tight - only an official representative "
  79.     "of the postal service can get things out of it."$
  80. o_mailbox@p_oGetChecker := mailboxGet$
  81. o_mailbox@p_Image := "Town/mailbox"$
  82.  
  83. define tp_mail proc boardGet(thing th)status:
  84.  
  85.     Print("The bulletin board is firmly attached.\n");
  86.     OPrint(Capitalize(CharacterNameG(Me())) +
  87.     " tries to rip off the bulletin board.\n");
  88.     fail
  89. corp;
  90.  
  91. define tp_mail proc boardRead()void:
  92.     thing board, bulletin;
  93.     list thing lt;
  94.     string what, what2;
  95.     int count, i, n;
  96.  
  97.     board := It();
  98.     lt := board@p_oContents;
  99.     count := Count(lt);
  100.     what := GetWord();
  101.     what2 := GetWord();
  102.     if what = "" or what == "bulletins" or what == "contents" or
  103.     what == "notices" or what == "board" or
  104.     what == "bulletin" and what2 == "board"
  105.     then
  106.     if count = 0 then
  107.         Print("There are no bulletins posted yet.\n");
  108.     else
  109.         Print("Current bulletins (number, date posted, poster):\n");
  110.         for i from 0 upto count - 1 do
  111.         bulletin := lt[i];
  112.         Print("  " + IntToString(bulletin@p_oBulletinNumber) + "  " +
  113.             bulletin@p_oBulletinDate + "  " +
  114.             bulletin@p_oCreator@p_pName + "\n");
  115.         od;
  116.     fi;
  117.     else
  118.     if what == "bulletin" or what == "notice" then
  119.         what := what2;
  120.     fi;
  121.     if SubString(what, 0, 1) = "#" then
  122.         what := SubString(what, 1, Length(what) - 1);
  123.     fi;
  124.     if what = "" then
  125.         Print("You must say which bulletin you want to read.\n");
  126.     else
  127.         n := StringToInt(what);
  128.         if n < 0 then
  129.         Print("\"" + what + "\" is not a valid bulletin number.\n");
  130.         else
  131.         i := 0;
  132.         while i < count and lt[i]@p_oBulletinNumber ~= n do
  133.             i := i + 1;
  134.         od;
  135.         if i = count then
  136.             Print("There is no bulletin " + what + " on the board.\n");
  137.         else
  138.             Paginate(lt[i]@p_oReadString);
  139.         fi;
  140.         fi;
  141.     fi;
  142.     fi;
  143. corp;
  144.  
  145. define tp_mail proc actualPostBulletin(thing bulletin, board)void:
  146.     thing me, oldNote;
  147.     list thing lt;
  148.     int n;
  149.  
  150.     me := Me();
  151.     lt := board@p_oContents;
  152.     bulletin@p_oBulletinDate := Date();
  153.     n := board@p_oBulletinNumber;
  154.     board@p_oBulletinNumber := n + 1;
  155.     bulletin@p_oBulletinNumber := n;
  156.     bulletin@p_oName := IntToString(n) + ";bulletin";
  157.     if Count(lt) >= 20 then
  158.     oldNote := lt[0];
  159.     ClearThing(oldNote);
  160.     DelElement(lt, oldNote);
  161.     fi;
  162.     AddTail(lt, bulletin);
  163.     bulletin -- p_oCarryer;
  164.     bulletin@p_oWhere := board;
  165.     bulletin@p_oInvisible := true;
  166.     DelElement(me@p_pCarrying, bulletin);
  167.     Print("Bulletin posted.\n");
  168.     if not me@p_pHidden then
  169.     OPrint(Capitalize(me@p_pName) + " posts a bulletin.\n");
  170.     else
  171.     OPrint("A new bulletin has been posted.\n");
  172.     fi;
  173. corp;
  174.  
  175. define tp_mail proc boardPutIn(thing bulletin, board)status:
  176.  
  177.     if Parent(bulletin) = o_bulletin then
  178.     actualPostBulletin(bulletin, board);
  179.     succeed
  180.     else
  181.     Print("You can't post that on the bulletin board.\n");
  182.     fail
  183.     fi
  184. corp;
  185.  
  186. define tp_mail proc boardTakeFrom(thing bulletin, board)status:
  187.     thing me;
  188.  
  189.     me := Me();
  190.     if bulletin@p_oCreator = me or MeCharacter() = SysAdmin then
  191.     AddTail(me@p_pCarrying, bulletin);
  192.     DelElement(board@p_oContents, bulletin);
  193.     bulletin -- p_oWhere;
  194.     bulletin@p_oCarryer := me;
  195.     Print("You take " + FormatName(bulletin@p_oName) +
  196.         " from the bulletin board.\n");
  197.     if not me@p_pHidden then
  198.     OPrint(Capitalize(CharacterNameG(me)) +
  199.         " takes a bulletin from the bulletin board.\n");
  200.     else
  201.         OPrint("A bulletin has been removed from the bulletin board.\n");
  202.     fi;
  203.     bulletin@p_oName := "bulletin";
  204.     bulletin -- p_oInvisible;
  205.     succeed
  206.     else
  207.     Print("That's not your bulletin.\n");
  208.     fail
  209.     fi
  210. corp;
  211.  
  212. define tp_mail o_bulletinBoard CreateThing(nil)$
  213. SetThingStatus(o_bulletinBoard, ts_readonly)$
  214. o_bulletinBoard@p_oName := "board;bulletin"$
  215. o_bulletinBoard@p_oDesc :=
  216.     "The bulletin board is a framed corkboard which is used for the posting "
  217.     "of public notices. Anyone can post on it, and anyone can read what is "
  218.     "posted on it. Use 'read notices' to see what notices exist. Use "
  219.     "'read N', where N is the number of a bulletin, to read that bulletin. "
  220.     "Use 'take bulletin N from board' to take a bulletin from the board."$
  221. o_bulletinBoard@p_oGetChecker := boardGet$
  222. o_bulletinBoard@p_oActWord := "read"$
  223. o_bulletinBoard@p_oActAction := boardRead$
  224. o_bulletinBoard@p_oPutInMeChecker := boardPutIn$
  225. o_bulletinBoard@p_oTakeFromMeChecker := boardTakeFrom$
  226. o_bulletinBoard@p_Image := "Town/bboard"$
  227.  
  228. define tp_mail o_postalService CreateThing(nil)$
  229. o_postalService@p_pName := "the postal service"$
  230.  
  231. define tp_mail proc mailRoomRegister()bool:
  232.     thing me, th;
  233.     string name;
  234.     list thing lt;
  235.  
  236.     me := Me();
  237.     name := Capitalize(CharacterNameG(me));
  238.     if me@p_pMailRegistered then
  239.     Print("Only one registration per customer, sir!\n");
  240.     if not me@p_pHidden then
  241.         OPrint(name + " walks up to the counter, but is turned away.\n");
  242.     fi;
  243.     false
  244.     else
  245.     lt := me@p_pCarrying;
  246.     th := CreateThing(o_letter);
  247.     SetThingStatus(th, ts_public);
  248.     GiveThing(th, SysAdmin);
  249.     AddTail(lt, th);
  250.     th@p_oName := "service;letter,from,the,postal.letter";
  251.     th@p_oHome := r_garbageRoom;
  252.     th@p_oReadString := "Date: " + Date() +
  253. "\nFrom: the postal service\n\n    Welcome to the mail system. You can use "
  254. "any of the mailboxes scattered around to mail letters to people, but you "
  255. "must go to the mail room to pick up new letters from others to you.\n";
  256.     th@p_pLetterTarget := me;
  257.     th@p_oLetterSender := o_postalService;
  258.     th@p_oCarryer := me;
  259.     th@p_oCreator := me;
  260.     me@p_pMailRegistered := true;
  261.     Print(
  262. "You walk up to the counter to register. A clerk comes up to the wicket and "
  263. "helps you fill out all of the forms in triplicate. He then gives you a "
  264. "letter, says goodbye, and leaves.\n");
  265.     if not me@p_pHidden then
  266.         OPrint(name +
  267.         " walks up to the counter and is given something.\n");
  268.     else
  269.         OPrint("The clerk at the counter hands something to thin air.\n");
  270.     fi;
  271.     true
  272.     fi
  273. corp;
  274. r_mailRoom@p_rRegisterAction := mailRoomRegister$
  275.  
  276. define tp_mail r_postmanHidden CreateThing(nil)$
  277.  
  278. define tp_mail proc postmanStep()void:
  279.     list thing ltMan, ltHere;
  280.     thing here, me, mailbox, letter;
  281.     string route;
  282.     int index, count;
  283.     status st;
  284.     bool idling;
  285.  
  286.     me := Me();
  287.     here := Here();
  288.     idling := false;
  289.     if ClientsActive() then
  290.     /* someone is playing */
  291.     me@p_oPostManClearing := false;
  292.     me@p_oPostManCleared := false;
  293.     else
  294.     /* no active players, and we have collected all mail - go idle */
  295.     if me@p_oPostManCleared then
  296.         idling := true;
  297.     fi;
  298.     fi;
  299.     if idling then
  300.     After(60.0, postmanStep);
  301.     elif here = r_postmanHidden then
  302.     SetLocation(r_mailRoom);
  303.     OPrint("Postman comes out from the private areas of the mailroom.\n");
  304.     me@p_oPostManRoute := "";
  305.     me@p_oPostManIndex := 0;
  306.     if r_mailRoom@p_rNewLetter then
  307.         /* make sure we deliver that last letter */
  308.         r_mailRoom@p_rNewLetter := false;
  309.         me@p_oPostManClearing := false;
  310.         me@p_oPostManCleared := false;
  311.     fi;
  312.     SetLocation(r_mailRoom);
  313.     ForEachAgent(r_mailRoom, ShowIconOnce);
  314.     After(20.0, postmanStep);
  315.     else
  316.     route := me@p_oPostManRoute;
  317.     index := me@p_oPostManIndex;
  318.     if index = Length(route) then
  319.         st := FindName(here@p_rContents, p_oName, "mailbox");
  320.         if st = fail then
  321.         Say("", "AAAAAARRRRRRGGGGGHHHHH! I'm lost!!!!");
  322.         Log("Postman is lost! Route = '" + route + "', index = " +
  323.             IntToString(index) + ", " + here@p_rName + "\n");
  324.         else
  325.         /* collect the mail from this mailbox, and get new route */
  326.         mailbox := FindResult();
  327.         ltHere := mailbox@p_oLettersHere;
  328.         if ltHere = nil then
  329.             Say("", "AAAAARRRRGGGGGHHHH! Fake mailbox!");
  330.         else
  331.             ltMan := me@p_oLettersHere;
  332.             count := Count(ltHere);
  333.             if count = 0 then
  334.             OPrint("Postman looks, but there is no mail in the "
  335.                 "mailbox.\n");
  336.             else
  337.             OPrint(
  338.                 "Postman collects the mail from the mailbox.\n");
  339.             fi;
  340.             while count ~= 0 do
  341.             count := count - 1;
  342.             letter := ltHere[count];
  343.             AddTail(ltMan, letter);
  344.             DelElement(ltHere, letter);
  345.             od;
  346.             if here = r_mailRoom and route ~= "" then
  347.             /* deliver the mail (plunk it down right here) */
  348.             ltHere := here@p_oLettersHere;
  349.             count := Count(ltMan);
  350.             while count ~= 0 do
  351.                 count := count - 1;
  352.                 letter := ltMan[count];
  353.                 AddTail(ltHere, letter);
  354.                 DelElement(ltMan, letter);
  355.             od;
  356.             OPrint("Postman disappears into the private "
  357.                 "areas of the mailroom.\n");
  358.             ForEachAgent(r_mailRoom, UnShowIconOnce);
  359.             SetLocation(r_postmanHidden);
  360.             /* a two-step process to make sure that he has
  361.                collected and delivered all mail before he goes
  362.                idle */
  363.             if me@p_oPostManClearing then
  364.                 me@p_oPostManCleared := true;
  365.             else
  366.                 me@p_oPostManClearing := true;
  367.             fi;
  368.             After(300.0, postmanStep);
  369.             else
  370.             me@p_oPostManRoute := mailbox@p_oPostManRoute;
  371.             me@p_oPostManIndex := 0;
  372.             After(20.0, postmanStep);
  373.             fi;
  374.         fi;
  375.         fi;
  376.     else
  377.         ignore Parse(G, SubString(route, index, 1));
  378.         index := index + 1;
  379.         me@p_oPostManIndex := index;
  380.         /* Here() is AFTER the call to Parse! */
  381.         if Here() = r_mallEntrance then
  382.         ignore recorderErase();
  383.         fi;
  384.         After(20.0, postmanStep);
  385.     fi;
  386.     fi;
  387. corp;
  388.  
  389. define tp_mail proc postmanDesc()string:
  390.  
  391. "The postman, dressed in official postal service blue and carrying the "
  392. "standard satchel for letters, is not actually delivering mail. Rather, he is "
  393. "picking mail up at the various mailboxes and taking it in for delivery. " +
  394.     if Count(It()@p_oLettersHere) = 0 then
  395.     "The postman's satchel appears to be empty."
  396.     else
  397.     "The postman's satchel appears to contain some letters."
  398.     fi
  399. corp;
  400.  
  401. define tp_mail proc postmanHear(string what)void:
  402.     string word;
  403.  
  404.     word := SetSay(what);
  405.     if word ~= "" and word ~= "Packrat" then
  406.     if GetWord() == "Postman" then
  407.         OPrint("Postman mutters something about dogs and hailstones.\n");
  408.     fi;
  409.     fi;
  410. corp;
  411.  
  412. define tp_mail proc postmanPre()status:
  413.  
  414.     SPrint(TrueMe(), "Postman refuses the gift.\n");
  415.     fail
  416. corp;
  417.  
  418. define tp_mail proc postmanStart()void:
  419.     thing me;
  420.     int delay;
  421.  
  422.     me := Me();
  423.     delay := me@p_oPostManDelay;
  424.     me -- p_oPostManDelay;
  425.     After(IntToFixed(delay), postmanStep);
  426. corp;
  427.  
  428. define tp_mail proc postmanCreate(int delay)void:
  429.     thing postman;
  430.  
  431.     postman := CreateThing(nil);
  432.     SetupMachine(postman);
  433.     postman@p_pStandard := true;
  434.     postman@p_oLettersHere := CreateThingList();
  435.     postman@p_pDescAction := postmanDesc;
  436.     postman@p_oPostManClearing := false;
  437.     postman@p_oPostManCleared := false;
  438.     postman@p_oPostManDelay := delay;
  439.     postman@p_pGivePre := postmanPre;
  440.     postman@p_Image := "Characters/Postman";
  441.     CreateMachine("Postman,pos,post", postman, r_postmanHidden, postmanStart);
  442.     ignore SetMachineActive(postman, postmanStep);
  443.     ignore SetMachineSay(postman, postmanHear);
  444.     GNewIcon(postman, makePostmanIcon());
  445. corp;
  446.  
  447. postmanCreate(0)$
  448. /* postmanCreate(300)$ */
  449. /* postmanCreate(600)$ */
  450. ignore DeleteSymbol(tp_mail, "postmanCreate")$
  451.  
  452. define tp_mail proc mailMakeLetter(string s)void:
  453.     thing me, target, letter;
  454.     string myName;
  455.  
  456.     me := Me();
  457.     myName := me@p_pName;
  458.     target := me@p_pLetterTarget;
  459.     me -- p_pLetterTarget;
  460.     letter := CreateThing(o_letter);
  461.     AddTail(me@p_pCarrying, letter);
  462.     letter@p_oName := FormatName(target@p_pName) + ";letter,for.letter";
  463.     letter@p_oReadString :=
  464.     "Date: " + Date() + "\nFrom: " + myName + "\n\n" + s;
  465.     letter@p_pLetterTarget := target;
  466.     letter@p_oLetterSender := me;
  467.     letter@p_oCarryer := me;
  468.     letter@p_oCreator := me;
  469.     SetThingStatus(letter, ts_public);
  470.     GiveThing(letter, SysAdmin);
  471.     if not me@p_pHidden and CanSee(Here(), me) then
  472.     OPrint(Capitalize(myName) + " finishes writing.\n");
  473.     else
  474.     OPrint("The quiet scratching noise stops.\n");
  475.     fi;
  476.     Print("Letter finished. Now all you need to do is post it.\n");
  477. corp;
  478.  
  479. define tp_mail proc makeBulletin(string s)void:
  480.     thing me, bulletin;
  481.     string myName;
  482.  
  483.     me := Me();
  484.     myName := me@p_pName;
  485.     bulletin := CreateThing(o_bulletin);
  486.     AddTail(me@p_pCarrying, bulletin);
  487.     bulletin@p_oName := "bulletin,note";
  488.     bulletin@p_oReadString :=
  489.     "Date: " + Date() + "\nBy: " + myName + "\n\n" + s;
  490.     bulletin@p_oLetterSender := me;
  491.     bulletin@p_oCarryer := me;
  492.     bulletin@p_oCreator := me;
  493.     SetThingStatus(bulletin, ts_public);
  494.     GiveThing(bulletin, SysAdmin);
  495.     if not me@p_pHidden and CanSee(Here(), me) then
  496.     OPrint(Capitalize(myName) + " finishes writing.\n");
  497.     else
  498.     OPrint("The quiet scratching noise stops.\n");
  499.     fi;
  500.     Print("Bulletin finished. Now all you need to do is post it.\n");
  501. corp;
  502.  
  503. define tp_mail proc writeNote(thing targetThing)bool:
  504.     thing me;
  505.  
  506.     me := Me();
  507.     if FindName(me@p_pCarrying, p_oName, "pad;writing") = fail then
  508.     Print("You have no pad to write on.\n");
  509.     false
  510.     elif FindName(me@p_pCarrying, p_oName, "pen;ballpoint") = fail then
  511.     Print("You have no ballpoint pen to write with.\n");
  512.     false
  513.     elif not CanSee(Here(), me) then
  514.     Print("You can't write in the dark.\n");
  515.     false
  516.     else
  517.     if targetThing ~= nil then
  518.         me@p_pLetterTarget := targetThing;
  519.         if GetDocument("mail> ", "Enter body of letter",
  520.                "", mailMakeLetter, true)
  521.         then
  522.         if not me@p_pHidden and CanSee(Here(), me) then
  523.             OPrint(Capitalize(me@p_pName) + " starts writing.\n");
  524.         else
  525.             OPrint("You hear a quiet scratching noise start.\n");
  526.         fi;
  527.         true
  528.         else
  529.         false
  530.         fi
  531.     else
  532.         if GetDocument("bulletin> ", "Enter body of bulletin",
  533.                "", makeBulletin, true)
  534.         then
  535.         if not me@p_pHidden and CanSee(Here(), me) then
  536.             OPrint(Capitalize(me@p_pName) + " starts writing.\n");
  537.         else
  538.             OPrint("You hear a quiet scratching noise start.\n");
  539.         fi;
  540.         true
  541.         else
  542.         false
  543.         fi
  544.     fi
  545.     fi
  546. corp;
  547.  
  548. define tp_mail proc mailTo(string who)bool:
  549.     character targetPlayer;
  550.     thing targetThing, me;
  551.  
  552.     me := Me();
  553.     if who == "me" then
  554.     who := me@p_pName;
  555.     fi;
  556.     targetPlayer := Character(who);
  557.     if targetPlayer = nil then
  558.     targetPlayer := Character(Capitalize(who));
  559.     fi;
  560.     if targetPlayer = nil then
  561.     targetThing := FindAgent(who);
  562.     if targetThing = nil then
  563.         Print("Character \"" + FormatName(who) +
  564.         "\" does not exist. Make sure you have the spelling and "
  565.         "capitalization right.\n");
  566.     else
  567.         /* must have been a machine in the same location! */
  568.         Print("Sorry, " + who + " hasn't registered for mail yet.\n");
  569.     fi;
  570.     false
  571.     else
  572.     targetThing := CharacterThing(targetPlayer);
  573.     if not targetThing@p_pMailRegistered then
  574.         Print("Sorry, " + who + " hasn't registered for mail yet.\n");
  575.         false
  576.     else
  577.         writeNote(targetThing)
  578.     fi
  579.     fi
  580. corp;
  581.  
  582. define tp_mail proc v_write()bool:
  583.     string error, help, word;
  584.  
  585.     error := "You must specify who you want to write a letter to.\n";
  586.     help :=
  587.         "Use 'post' to post a letter or bulletin, "
  588.         "'mail <who>' or 'write <who>' to write a letter, "
  589.         "and 'write bulletin' to write a bulletin.\n";
  590.     word := GetWord();
  591.     if word == "a" then
  592.     word := GetWord();
  593.     fi;
  594.     if word == "to" then
  595.     word := GetWord();
  596.     if word = "" then
  597.         Print(error);
  598.         false
  599.     else
  600.         mailTo(word)
  601.     fi
  602.     elif word == "letter" then
  603.     word := GetWord();
  604.     if word = "" then
  605.         if FindName(Me()@p_pCarrying, p_oName, "letter") ~= fail then
  606.         Print(help);
  607.         else
  608.         Print(error);
  609.         fi;
  610.         false
  611.     elif word == "to" then
  612.         mailTo(GetWord())
  613.     else
  614.         mailTo(word)
  615.     fi
  616.     elif word == "bulletin" then
  617.     word := GetWord();
  618.     if word = "" then
  619.         writeNote(nil)
  620.     elif word == "to" then
  621.         Print("You can't write bulletins to individuals. You can write "
  622.           "letters to people, or you can write public bulletins.\n");
  623.         false
  624.     else
  625.         Print("I don't understand what you want to write. ");
  626.         Print(help);
  627.         false
  628.     fi
  629.     elif Character(word) ~= nil then
  630.     mailTo(word)
  631.     elif word = "" then
  632.     Print(error);
  633.     false
  634.     else
  635.     Print("I don't understand who you want to write to. "
  636.           "Make sure you have the spelling and "
  637.           "capitalization of the name right. If you are trying to "
  638.           "write a bulletin, use 'write bulletin'.\n");
  639.     false
  640.     fi
  641. corp;
  642.  
  643. VerbTail(G, "write", v_write)$
  644. Synonym(G, "write", "mail")$
  645.  
  646. define tp_mail o_mail CreateThing(nil)$
  647. SetupObject(o_mail, r_mailRoom, "mail,letters;my,new", "")$
  648. o_mail@p_oInvisible := true$
  649. o_mail@p_oReadString :=
  650.     "Use 'get mail' or something similar to pick up your new mail, and "
  651.     "then 'read' the individual letters."$
  652. define tp_mail proc mailGet(thing letter)status:
  653.     list thing letters, carrying;
  654.     thing me;
  655.     int count, n;
  656.     bool gotOne;
  657.  
  658.     me := Me();
  659.     carrying := me@p_pCarrying;
  660.     letters := r_mailRoom@p_oLettersHere;
  661.     count := Count(letters);
  662.     gotOne := false;
  663.     n := 0;
  664.     while n ~= count do
  665.     letter := letters[n];
  666.     if letter@p_pLetterTarget = me then
  667.         Print("You have a " + FormatName(letter@p_oName) + ".\n");
  668.         AddTail(carrying, letter);
  669.         DelElement(letters, letter);
  670.         count := count - 1;
  671.         letter@p_oCarryer := me;
  672.         letter@p_oCreator := me;
  673.         gotOne := true;
  674.     else
  675.         n := n + 1;
  676.     fi;
  677.     od;
  678.     if gotOne then
  679.     if not me@p_pHidden then
  680.         OPrint(Capitalize(me@p_pName) + " picks up some new mail.\n");
  681.     fi;
  682.     else
  683.     Print("You have no new mail.\n");
  684.     if not me@p_pHidden then
  685.         OPrint(Capitalize(CharacterNameG(me)) +
  686.         " looks, but has no new mail.\n");
  687.     fi;
  688.     fi;
  689.     succeed
  690. corp;
  691. o_mail@p_oGetChecker := mailGet$
  692.  
  693. define tp_mail proc doPostLetter(thing letter)bool:
  694.     thing me, sender, mailbox;
  695.     list thing lt;
  696.     status st;
  697.  
  698.     st := FindName(Here()@p_rContents, p_oName, "mailbox");
  699.     if st = fail then
  700.     Print("There is no mailbox here.\n");
  701.     false
  702.     else
  703.     mailbox := FindResult();
  704.     lt := mailbox@p_oLettersHere;
  705.     if Parent(mailbox) ~= o_mailbox or lt = nil then
  706.         Print("Sorry, the mailbox here isn't official.\n");
  707.         false
  708.     else
  709.         me := Me();
  710.         sender := letter@p_oLetterSender;
  711.         if sender ~= o_postalService then
  712.         letter@p_oName := sender@p_pName +
  713.             ";letter,from.letter";
  714.         fi;
  715.         AddTail(lt, letter);
  716.         letter -- p_oCarryer;
  717.         DelElement(me@p_pCarrying, letter);
  718.         /* force Postman to deliver it before idling */
  719.         r_mailRoom@p_rNewLetter := true;
  720.         Print("Letter posted.\n");
  721.         if not me@p_pHidden then
  722.         OPrint(Capitalize(CharacterNameG(me)) + " posts a letter.\n");
  723.         fi;
  724.         true
  725.     fi
  726.     fi
  727. corp;
  728.  
  729. define tp_mail proc doPostBulletin(thing bulletin)bool:
  730.     thing board, oldNote;
  731.     list thing lt;
  732.     status st;
  733.     int n;
  734.  
  735.     st := FindName(Here()@p_rContents, p_oName, "board;bulletin");
  736.     if st = fail then
  737.     Print("There is no bulletin board here.\n");
  738.     false
  739.     else
  740.     board := FindResult();
  741.     lt := board@p_oContents;
  742.     if Parent(board) ~= o_bulletinBoard or lt = nil then
  743.         Print("Sorry, the bulletin board here isn't official.\n");
  744.         false
  745.     else
  746.         actualPostBulletin(bulletin, board);
  747.         true
  748.     fi
  749.     fi
  750. corp;
  751.  
  752. define tp_mail proc v_post(string what)bool:
  753.     thing me, letter;
  754.     string name;
  755.     status st;
  756.  
  757.     if what = "" then
  758.     Print("You must specify what you want to post.\n");
  759.     false
  760.     else
  761.     me := Me();
  762.     name := FormatName(what);
  763.     st := FindName(me@p_pCarrying, p_oName, what);
  764.     if st = fail then
  765.         Print(AAn("You are not carrying", name) + ".\n");
  766.         false
  767.     elif st = continue then
  768.         Print(name + " is ambiguous here.\n");
  769.         false
  770.     else
  771.         letter := FindResult();
  772.         if Parent(letter) = o_letter then
  773.         if letter@p_oCreator ~= me and MeCharacter() ~= SysAdmin then
  774.             Print("That's not your letter.\n");
  775.             false
  776.         else
  777.             doPostLetter(letter)
  778.         fi
  779.         elif Parent(letter) = o_bulletin then
  780.         if letter@p_oCreator ~= me and MeCharacter() ~= SysAdmin then
  781.             Print("That's not your bulletin.\n");
  782.             false
  783.         else
  784.             doPostBulletin(letter)
  785.         fi
  786.         else
  787.         Print("The " + name + " is not something you can post.\n");
  788.         false
  789.         fi
  790.     fi
  791.     fi
  792. corp;
  793.  
  794. Verb1(G, "post", 0, v_post)$
  795.  
  796. define tp_mail proc mailRoomDrop(thing th)status:
  797.  
  798.     if Parent(th) = o_letter then
  799.     Print("The letter somehow wafts its way into the mailbox.\n");
  800.     if Me()@p_pHidden then
  801.         OPrint("A letter appears and wafts into the mailbox.\n");
  802.     else
  803.         OPrint(Capitalize(CharacterNameG(Me())) +
  804.         " drops a letter, which wafts into the mailbox.\n");
  805.     fi;
  806.     if doPostLetter(th) then
  807.         succeed
  808.     else
  809.         continue
  810.     fi
  811.     else
  812.     continue
  813.     fi
  814. corp;
  815. AddRoomDropChecker(r_mailRoom, mailRoomDrop, false)$
  816.  
  817. define tp_mail proc makeMailBox(thing room; string route)void:
  818.     thing mailbox;
  819.  
  820.     mailbox := CreateThing(o_mailbox);
  821.     AddTail(room@p_rContents, mailbox);
  822.     mailbox@p_oPostManRoute := route;
  823.     mailbox@p_oLettersHere := CreateThingList();
  824.     SetThingStatus(mailbox, ts_readonly);
  825. corp;
  826.  
  827. makeMailBox(r_mailRoom, "seene")$
  828. makeMailBox(r_ne3, "ssseees")$
  829. makeMailBox(r_es4, "wwwwssw")$
  830. makeMailBox(r_sw3, "nnnwwwn")$
  831. makeMailBox(r_wn3, "eeennwwn")$
  832.  
  833. define t_util proc MakeBulletinBoard(thing room)void:
  834.     thing board;
  835.  
  836.     board := CreateThing(o_bulletinBoard);
  837.     board@p_oBulletinNumber := 1;
  838.     board@p_oContents := CreateThingList();
  839.     SetThingStatus(board, ts_readonly);
  840.     AddTail(room@p_rContents, board);
  841. corp;
  842.  
  843. MakeBulletinBoard(r_wn2)$
  844.  
  845. CharacterThing(SysAdmin)@p_pMailRegistered := true$
  846.  
  847. unuse tp_mail
  848. unuse t_streets
  849.