home *** CD-ROM | disk | FTP | other *** search
/ CD PowerPlay 6 / TheCompleteAdventureCollection1995 / CDPP6.ISO / utility / agtsrc / describe.pa4 < prev    next >
Encoding:
Text File  |  1991-06-10  |  18.5 KB  |  475 lines

  1.  
  2.   {DESCRIBE.PA2}
  3.  
  4.  
  5.   { Proc List_Contents }
  6.   { *recursive* }
  7.   {Given a location (integer) and the recursion }
  8.   {level, prints out the items which are inside }
  9.   {the location specified. If any of the items are}
  10.   {themselves open, calls itself again to list }
  11.   {the contents of that item, passing level+1 to }
  12.   {insure proper indentation. }
  13.   {Routine only executes if something}
  14.   {is at location that should be listed}
  15.  
  16.   PROCEDURE List_Contents(loc : Integer;
  17.                           level : Integer);
  18.   LABEL Done;
  19.   VAR i : Integer;
  20.     FWord : words;
  21.  
  22.     FUNCTION ds : names;          {handles spacing}
  23.     VAR k : Integer;              {level is global to this}
  24.       st : names;
  25.     BEGIN
  26.       k := 0;
  27.       st := ' ';
  28.       REPEAT
  29.         st := st+' ';
  30.         k := k+1;
  31.       UNTIL k >= ((2*level)-1);
  32.       ds := st;
  33.     END;                          {ds}
  34.  
  35.   BEGIN                           {List_Contents}
  36.     IF Things_Here(loc) < 1 THEN GOTO Done;
  37.     FOR i := First_noun TO MaxNoun DO
  38.       IF N[i]^.location = loc THEN
  39.         BEGIN
  40.           IF (morecount >= MoreLimit)
  41.           THEN BEGIN
  42.             morecount := 0;
  43.             Pause;
  44.           END;
  45.           FWord := first_word(N[i]^.short); {get first world of short description}
  46.           {$V-} Capitalize(FWord); {$V+} {Capitalize it}
  47.           IF FWord <> 'INVISIBLE' THEN
  48.             BEGIN
  49.               Write(IO, ds, N[i]^.short);
  50.               IF ((level = 1) AND (N[i]^.position <> 'none'))
  51.               THEN Write(IO, ' (', N[i]^.position, ')');
  52.               IF (level > 1) THEN Write(IO, ' (in the ', name(loc), ')');
  53.               WriteLn(IO, ' ');
  54.               morecount := morecount+1;
  55.               IF N[i]^.open THEN List_Contents(i, level+1);
  56.             END;
  57.         END;
  58. Done:
  59.   END;                            {list_contents}
  60.  
  61.   { Procedure List_Creatures }
  62.   {Similar in function to List_Contents. Lists }
  63.   {all creatures whose location is specified. This}
  64.   {is not a recursive procedure, since creatures }
  65.   {can only be in rooms, not other creatures or }
  66.   {nouns. }
  67.  
  68.   PROCEDURE List_Creatures(loc : Integer);
  69.  
  70.   VAR i : Integer;
  71.     FWord : words;
  72.   BEGIN
  73.     FOR i := First_creature TO MaxCreature DO
  74.       IF M[i]^.location = loc THEN
  75.         BEGIN
  76.           IF (morecount >= MoreLimit)
  77.           THEN BEGIN
  78.             morecount := 0;
  79.             Pause;
  80.           END;
  81.           FWord := M[i]^.short;   {get first world of short description}
  82.           {$V-} Capitalize(FWord); {$V+} {Capitalize it}
  83.           IF FWord <> 'INVISIBLE' THEN
  84.             BEGIN
  85.               WriteLn(IO, '  ', M[i]^.short);
  86.               morecount := morecount+1;
  87.             END;
  88.         END;
  89.   END;                            {list_Creatures}
  90.  
  91.  
  92.   { SwapWords }
  93.   {Swaps two words in a sentence}
  94.  
  95.   PROCEDURE SwapWords(FromWord, ToWord : words; VAR sentence : s; LowerCase : Boolean);
  96.  
  97.   VAR
  98.     Spot, FromLength : Integer;
  99.   BEGIN
  100.     IF LowerCase THEN Normalize(ToWord); {make lower case}
  101.     IF (FromWord[1] = '$') THEN
  102.       BEGIN
  103.         Normalize(ToWord);        { make lower case }
  104.         IF (FromWord[2] <= 'Z') THEN { if first letter capital... }
  105.           ToWord[1] := Upcase(ToWord[1]);
  106.         IF (FromWord[3] <= 'Z') THEN { if second letter capital... }
  107.           FOR Spot := 2 TO Length(ToWord) DO ToWord[Spot] := Upcase(ToWord[Spot]);
  108.       END;
  109.     FromLength := Length(FromWord);
  110.     WHILE POS(FromWord, sentence) <> 0 DO
  111.       BEGIN
  112.         Spot := POS(FromWord, sentence);
  113.         Delete(sentence, Spot, FromLength); {delete FromWord}
  114.         Insert(ToWord, sentence, Spot); {insert ToWord}
  115.       END;
  116.     IF (FromWord[1] = '$') AND (FromWord[3] <= 'Z') THEN
  117.       BEGIN
  118.         Normalize(FromWord);
  119.         SwapWords(FromWord, ToWord, sentence, LowerCase);
  120.         FromWord[2] := Upcase(FromWord[2]);
  121.         SwapWords(FromWord, ToWord, sentence, LowerCase);
  122.       END;
  123.   END;                            {SwapWords}
  124.  
  125.  
  126.  
  127.   { Handle Word Combinations }
  128.   {Remove the specific word combination from the}
  129.   {sentence and replace them with other words.}
  130.   PROCEDURE Handle_Word_Combinations(VAR sentence : s);
  131.   BEGIN
  132.     SwapWords(',', ' AND ', sentence, False); {convert ,s to 'and'}
  133.     SwapWords(';', ' AND ', sentence, False); {convert ;s to 'and'}
  134.     SwapWords('  ', ' ', sentence, False); {remove any double spaces}
  135.     SwapWords(' AND AND ', ' AND ', sentence, False);
  136.     SwapWords(' AND THEN ', ' AND ', sentence, False);
  137.     SwapWords(' IN TO ', ' INTO ', sentence, False);
  138.     SwapWords(' NEAR BY ', ' BY ', sentence, False);
  139.     SwapWords(' NEXT TO ', ' NEAR ', sentence, False);
  140.   END;
  141.  
  142.  
  143.   { Check For Name }
  144.   {Checks to see if the command is being addressed to a creature}
  145.   {If it is then routine sets Global NameStr to name of creature and}
  146.   {  the Global NameNum to the creature's number.}
  147.   {If it is NOT then routine sets Global NameStr to '' and}
  148.   {  the Global NameNum to 0.}
  149.   {After returning from this routine, sentence has the name (if any) stripped off}
  150.   PROCEDURE CheckForName(VAR sentence : s);
  151.   VAR FWord : words;
  152.     num : Integer;
  153.   BEGIN
  154.     FWord := first_word(sentence);
  155.     num := Creature_Number(FWord);
  156.     IF ((FWord = 'ANYONE') OR (FWord = 'ANYBODY'))
  157.     THEN num := Num_Verbs+1;
  158.     IF ((FWord = 'EVERYONE') OR (FWord = 'EVERYBODY'))
  159.     THEN num := Num_Verbs+2;
  160.     IF num = 0 THEN               {Command is NOT being addressed to a creature}
  161.       BEGIN
  162.         NameStr := '';
  163.         NameNum := 0;
  164.       END
  165.     ELSE BEGIN                    {Command is NOT being addressed to a creature}
  166.       NameNum := num;
  167.       Normalize(FWord);           {make lower case except for first letter}
  168.       IF (FWord[1] IN ['a'..'z'])
  169.       THEN FWord[1] := Char(Integer(FWord[1])-32);
  170.       NameStr := FWord;
  171.       sentence := But_First(sentence); {strip off name}
  172.       FWord := first_word(sentence); {second word of command}
  173.       IF FWord = 'AND' THEN sentence := But_First(sentence); {strip off AND}
  174.     END;
  175.   END;
  176.  
  177.   {Move any group member in FromLoc to ToLoc}
  178.   PROCEDURE MoveGroup(FromLoc, ToLoc : Integer);
  179.   VAR i : Integer;
  180.   BEGIN
  181.     IF MaxCreature > 0 THEN
  182.       FOR i := First_creature TO MaxCreature DO
  183.         IF ((M[i]^.location = FromLoc) AND (M[i]^.groupmember))
  184.         THEN M[i]^.location := ToLoc;
  185.   END;
  186.  
  187.  
  188.   { Procedure Describe_It }
  189.   {Given a number, it searches the data file and }
  190.   {provides a description. }
  191.   { 1. Allow Verb, Noun or Object to be "played back" in output.}
  192.   { 2. Give short description (if available), if long description is missing.}
  193.   { 3. Show short description of any nouns inside noun being described.}
  194.  
  195.   PROCEDURE Describe_It(keyword : words; num : Integer);
  196.  
  197.   VAR st : s;
  198.     i, k, adjnum, Tries : Integer;
  199.     VarStr, adj, SubWord, CapSubWord : words;
  200.     start, len, Spot, VarLn, VarNum, ErrorNum, FirstDollar, NextDollar : Integer;
  201.  
  202.   BEGIN
  203.     start := 0;
  204.     IF keyword = 'NOUN_DESCR' THEN start := Noun_Ptr[num].start
  205.     ELSE IF keyword = 'PLAY_DESCR' THEN start := Play_Ptr[num].start
  206.     ELSE IF keyword = 'PUSH_DESCR' THEN start := Push_Ptr[num].start
  207.     ELSE IF keyword = 'PULL_DESCR' THEN start := Pull_Ptr[num].start
  208.     ELSE IF keyword = 'TURN_DESCR' THEN start := Turn_Ptr[num].start
  209.     ELSE IF keyword = 'TEXT' THEN start := Text_Ptr[num].start
  210.     ELSE IF keyword = 'ROOM_DESCR' THEN start := Room_Ptr[num].start
  211.     ELSE IF keyword = 'SPECIAL' THEN start := Special_Ptr[num].start
  212.     ELSE IF keyword = 'MESSAGE' THEN start := Message_Ptr[num].start
  213.     ELSE IF keyword = 'HELP' THEN start := Help_Ptr[num].start
  214.     ELSE IF keyword = 'INTRO' THEN start := Intro_Ptr.start
  215.     ELSE IF keyword = 'CREATURE_DESCR' THEN start := Creature_Ptr[num].start;
  216.     IF start > 0 THEN
  217.       IF keyword = 'NOUN_DESCR' THEN len := Noun_Ptr[num].len
  218.       ELSE IF keyword = 'PLAY_DESCR' THEN len := Play_Ptr[num].len
  219.       ELSE IF keyword = 'PUSH_DESCR' THEN len := Push_Ptr[num].len
  220.       ELSE IF keyword = 'PULL_DESCR' THEN len := Pull_Ptr[num].len
  221.       ELSE IF keyword = 'TURN_DESCR' THEN len := Turn_Ptr[num].len
  222.       ELSE IF keyword = 'TEXT' THEN len := Text_Ptr[num].len
  223.       ELSE IF keyword = 'ROOM_DESCR' THEN len := Room_Ptr[num].len
  224.       ELSE IF keyword = 'SPECIAL' THEN len := Special_Ptr[num].len
  225.       ELSE IF keyword = 'MESSAGE' THEN len := Message_Ptr[num].len
  226.       ELSE IF keyword = 'HELP' THEN len := Help_Ptr[num].len
  227.       ELSE IF keyword = 'INTRO' THEN len := Intro_Ptr.len
  228.       ELSE IF keyword = 'CREATURE_DESCR' THEN len := Creature_Ptr[num].len;
  229.     IF start <= 0 THEN
  230.       IF keyword = 'MESSAGE'
  231.       THEN WriteLn(IO, 'MESSAGE ',num, ' is missing from .MSG file!')
  232.       ELSE IF (num >= First_noun) AND (num <= MaxNoun)
  233.       THEN WriteLn(IO, N[num]^.short) {give short description of no long one}
  234.       ELSE IF (num >= First_creature) AND (num <= MaxCreature)
  235.       THEN WriteLn(IO, M[num]^.short) {give short description of no long one}
  236.       ELSE WriteLn(IO, 'Sorry, I can''t describe that.')
  237.     ELSE                          {seek(datafile,start)}
  238.       BEGIN
  239.         Seek(descr_file, start);
  240.         FOR i := 1 TO len DO
  241.           BEGIN
  242.             IF (morecount >= MoreLimit)
  243.             THEN BEGIN
  244.               morecount := 0;
  245.               Pause;
  246.             END;
  247.             Read(descr_file, st);
  248.             st := Decode(st);
  249.             WHILE POS('#VAR', st) <> 0 DO
  250.               BEGIN               {Sub Variable N (0 .. 9) for #VARN#}
  251.                 Spot := POS('#VAR', st);
  252.                 VarStr := Copy(st, Spot+4, 2);
  253.                 IF VarStr[2] = '#'
  254.                 THEN BEGIN
  255.                   VarLn := 1;
  256.                   VarStr := VarStr[1];
  257.                 END ELSE VarLn := 2;
  258.                 Delete(st, Spot+4, VarLn); {get ride of Var digit}
  259.                 Val(VarStr, VarNum, ErrorNum);
  260.                 IF ErrorNum = 0 THEN
  261.                   BEGIN
  262.                     VarNum := Variable[VarNum];
  263.                     Str(VarNum, VarStr);
  264.                     SwapWords('#VAR#', VarStr, st, True); {substitute Variable value}
  265.                   END;
  266.               END;                {WHILE}
  267.             WHILE POS('#CTR', st) <> 0 DO
  268.               BEGIN               {Sub Counter N (0 .. 9) for #CTRN#}
  269.                 Spot := POS('#CTR', st);
  270.                 VarStr := Copy(st, Spot+4, 2);
  271.                 IF VarStr[2] = '#'
  272.                 THEN BEGIN
  273.                   VarLn := 1;
  274.                   VarStr := VarStr[1];
  275.                 END ELSE VarLn := 2;
  276.                 Delete(st, Spot+4, VarLn); {get ride of Ctr digit(s)}
  277.                 Val(VarStr, VarNum, ErrorNum);
  278.                 IF ErrorNum = 0 THEN
  279.                   BEGIN
  280.                     VarNum := counter[VarNum];
  281.                     Str(VarNum, VarStr);
  282.                     SwapWords('#CTR#', VarStr, st, True); {substitute Counter value}
  283.                   END;
  284.               END;                {WHILE}
  285.             adjnum := Noun_Number(noun);
  286.             adj := Things_Adjective(adjnum);
  287.             Tries := 0;
  288.             WHILE ((POS('$', st) <> 0) AND (Tries < 10)) DO
  289.               BEGIN
  290.                 Tries := Tries + 1;
  291.                 FirstDollar := POS('$', st);
  292.                 st[FirstDollar] := 'X';
  293.                 NextDollar := POS('$', st);
  294.                 st[FirstDollar] := '$'; {restore first '$' sign}
  295.                 IF NextDollar > FirstDollar THEN
  296.                   BEGIN
  297.                     {FromWord to substitute -- no necessarily capitalized}
  298.                     SubWord := Copy(st, FirstDollar, NextDollar-FirstDollar+1);
  299.                     CapSubWord := SubWord;
  300.                     FOR k := 1 TO Length(CapSubWord) DO
  301.                       CapSubWord[k] := Upcase(CapSubWord[k]); {capitalized word}
  302.                     IF CapSubWord = '$ADJECTIVE$'
  303.                     THEN SwapWords(SubWord, adj, st, True);
  304.                     {substitute Adj wherever $ADJECTIVE$ appears}
  305.                     IF CapSubWord = '$PREPOSITION$'
  306.                     THEN SwapWords(SubWord, prep, st, True);
  307.                     {substitute Prep wherever it appears}
  308.                     IF CapSubWord = '$NOUN$'
  309.                     THEN SwapWords(SubWord, noun, st, True);
  310.                     {substitute Noun wherever $NOUN$ appears}
  311.                     IF CapSubWord = '$VERB$'
  312.                     THEN SwapWords(SubWord, Original_Verb, st, True);
  313.                     {substitute verb for $VERB$}
  314.                     IF CapSubWord = '$OBJECT$'
  315.                     THEN SwapWords(SubWord, object_word, st, True);
  316.                     {substitute Object for $OBJECT$}
  317.                     IF CapSubWord = '$NAME$'
  318.                     THEN SwapWords(SubWord, NameStr, st, False);
  319.                     {substitute NameStr for $NAME$}
  320.                   END;            {NextDollar > FirstDollar}
  321.               END;                {WHILE}
  322.  
  323.             WriteLn(IO, st);
  324.             morecount := morecount+1;
  325.           END;
  326.       END;
  327.     IF (keyword = 'NOUN_DESCR') AND (num >= First_noun) AND (num <= MaxNoun)
  328.     THEN IF N[num]^.open THEN List_Contents(num, 2); {show items inside - if any}
  329.   END;
  330.  
  331.   { Function LightIsHere }
  332.   {Returns true if possible to see in Current_Room}
  333.  
  334.   FUNCTION LightIsHere : Boolean;
  335.  
  336.   VAR i, l : Integer;
  337.     can_see : Boolean;
  338.   BEGIN
  339.     can_see := False;
  340.     {determine if need and have specific light}
  341.     IF (Room[Current_room]^.light <= 0)
  342.     THEN can_see := True          {do not need light}
  343.     ELSE
  344.       IF Room[Current_room]^.light > 1 {room needs specific light if > 1}
  345.       THEN
  346.         BEGIN
  347.           l := location(Room[Current_room]^.light);
  348.           can_see := ((l = Player) OR (l = Current_room));
  349.         END
  350.       ELSE
  351.         FOR i := First_noun TO MaxNoun DO
  352.           BEGIN
  353.             l := location(i);
  354.             IF (N[i]^.on) AND (N[i]^.is_light)
  355.             AND ((l = Player) OR (l = Current_room))
  356.             THEN can_see := True;
  357.           END;
  358.     LightIsHere := can_see;
  359.   END;                            {LightIsHere}
  360.  
  361.   { Proc Describe_Scene }
  362.   { (Describe Room, Situation) }
  363.   {Assumes that everything is global but doesn't }
  364.   {modify any variables. It checks the boolean }
  365.   {variable 'verbose' to see if full descriptions }
  366.   {are normally desired. Calls all three of the }
  367.   {above procedures. }
  368.  
  369.   PROCEDURE Describe_scene;
  370.  
  371.   VAR
  372.     can_see : Boolean;
  373.   BEGIN
  374.     IF (Current_room <> Previous_room) {just moved into room}
  375.     THEN IF (NOT Room[Current_room]^.has_seen)
  376.       THEN FirstVisitFlag := True {Player has been here before}
  377.       ELSE FirstVisitFlag := False; {Player has not been here before}
  378.     can_see := LightIsHere;
  379.     {determine if need and have specific light}
  380.     IF NOT can_see
  381.     THEN
  382.       IF (Room[Current_room]^.light = 1)
  383.       THEN                        {player isn't carrying any light at all}
  384.         WriteLn(IO, 'It is pitch black. You can see nothing, not even your hands.')
  385.       ELSE                        {player may be carrying a light but still can't see}
  386.         WriteLn(IO, 'For some reason, you can''t see anything here.')
  387.     ELSE
  388.       BEGIN                       {Show room description only if first turn in room}
  389.         IF ((verb <> 'LOOK') AND (verb <> 'L')
  390.             AND (Current_room = Previous_room) AND (NOT Is_Direction(verb)))
  391.         THEN BEGIN                {No Description}
  392.         END                       {No description}
  393.         ELSE IF ((verb = 'LOOK') OR (verb = 'L') OR (FirstVisitFlag)
  394.                  OR ((verbose) AND (Current_room <> Previous_room)))
  395.         THEN BEGIN                {Verbose Description}
  396.           IF Scripting THEN WriteLn(IO, '<< ', Room[Current_room]^.name, ' >>');
  397.           morecount := morecount+2;
  398.           Describe_It('ROOM_DESCR', Current_room);
  399.           List_Contents(Current_room, 1);
  400.           List_Creatures(Current_room);
  401.         END                       {full verbose description}
  402.         ELSE IF (NOT verbose) AND ((Current_room <> Previous_room)
  403.                                    OR (Room[Current_room]^.has_seen))
  404.         THEN BEGIN                {Brief Description}
  405.           WriteLn(IO, '<< ', Room[Current_room]^.name, ' >>');
  406.           morecount := morecount+2;
  407.           List_Contents(Current_room, 1);
  408.           List_Creatures(Current_room);
  409.         END;                      {Brief description}
  410.       END;                        {normal room description if light on or not needed}
  411.     Previous_room := Current_room;
  412.     Room[Current_room]^.has_seen := True;
  413.   END;                            {describe_scene}
  414.  
  415.   {Describe(something)}
  416.  
  417.   PROCEDURE Describe(w : words);
  418.  
  419.   VAR l, num : Integer;
  420.   BEGIN
  421.     {$V-} Capitalize(w); {$V+}
  422.     IF noun = 'ALL'
  423.     THEN WriteLn(IO, 'Not everything at once! Pick one thing at a time!')
  424.     ELSE
  425.       IF (noun = 'DOOR') AND (location(NounNumber) <> Current_room)
  426.       THEN IF Room[Current_room]^.locked_door
  427.         THEN WriteLn(IO, 'It looks like a solid, locked door.')
  428.         ELSE WriteLn(IO, 'The doors here all look pretty much like doors.')
  429.       ELSE
  430.         IF ((NounNumber >= First_noun) AND (NounNumber <= MaxNoun)) OR
  431.         (NounNumber = 0)
  432.         THEN
  433.           BEGIN
  434.             Normalize(w);
  435.             IF (NOT Is_Visible(NounNumber)) AND (NOT(location(NounNumber) = Player))
  436.             THEN WriteLn(IO, 'I see no ', w, ' here.')
  437.             ELSE Describe_It('NOUN_DESCR', NounNumber);
  438.           END
  439.         ELSE                      {it must be a creature}
  440.           BEGIN
  441.             num := Creature_Number(w);
  442.             Normalize(w);
  443.             l := M[num]^.location;
  444.             IF NOT(l = Current_room)
  445.             THEN WriteLn(IO, 'The ', w, ' isn''t here.')
  446.             ELSE Describe_It('CREATURE_DESCR', num);
  447.           END;
  448.   END;                            {describe}
  449.  
  450.   { Drop (noun ) }
  451.   {Also take off or remove worn nouns}
  452.   {e.g., drop axe or take off hat }
  453.   { 1. Allows player to drop a worn item.}
  454.   { 2. Keeps track of number of items being carried and in room.}
  455.  
  456.   PROCEDURE Drop(noun : words);
  457.  
  458.   VAR num : Integer;
  459.     adj : words;
  460.   BEGIN
  461.     num := Noun_Number(noun);
  462.     Normalize(noun);
  463.     adj := Things_Adjective(num);
  464.     IF (N[num]^.location <> Player) AND (N[num]^.location <> Wearing)
  465.     THEN WriteLn(IO, 'You don''t seem to have the ', adj, ' ', noun, '.')
  466.     ELSE
  467.       BEGIN
  468.         Adjust_Count(N[num]^.location, -1);
  469.         Adjust_Count(Current_room, 1);
  470.         N[num]^.location := Current_room;
  471.         WriteLn(IO, 'You ', Original_Verb, ' the ', adj, ' ', noun, '.');
  472.       END;
  473.   END;                            {drop}
  474.  
  475.