home *** CD-ROM | disk | FTP | other *** search
/ CD PowerPlay 6 / TheCompleteAdventureCollection1995 / CDPP6.ISO / utility / agtsrc / spctools.pa3 < prev    next >
Encoding:
Text File  |  1989-06-16  |  17.8 KB  |  486 lines

  1.  
  2.   {SPCTOOLS.PA2 -- special GAGS tools}
  3.  
  4.   { Is_verb }
  5.   {Searches verb list via ascii name. }
  6.   {Returns TRUE if found and FALSE otherwise}
  7.   {NOTE: Synonyms have already been taken care of in PARSE}
  8.   FUNCTION Is_Verb(w : words) : Boolean;
  9.   VAR i : Integer;                {index to verbs array}
  10.     match : Boolean;
  11.   BEGIN
  12.     i := 0;                       {start with 'ANY'}
  13.     match := False;
  14.     REPEAT
  15.       match := (V[i] = w);
  16.       i := i+1;
  17.     UNTIL ((i > MaxVerb) OR (match)); {exits if match found}
  18.     IF NOT match THEN IF w = 'VERB' THEN match := True;
  19.     Is_Verb := match;
  20.   END;                            {Is_Verb}
  21.  
  22.   { Is_direction }
  23.   {Searches direction list via ascii name. }
  24.   {Returns TRUE if found and FALSE otherwise}
  25.   FUNCTION Is_Direction(w : words) : Boolean;
  26.   VAR i : Integer;
  27.     match : Boolean;
  28.   BEGIN
  29.     i := 1;
  30.     match := False;
  31.     REPEAT
  32.       match := (V[i] = w);
  33.       i := i+1;
  34.     UNTIL ((i > Num_Dirs) OR (match)); {exits if match found}
  35.     Is_Direction := match;
  36.   END;                            {Is_Verb}
  37.  
  38.   { Is_noun }
  39.   {Searches noun.name list via ascii name. }
  40.   {Also matches for valid synonyms to valid nouns.}
  41.   {Returns TRUE if found and FALSE otherwise. }
  42.   {Also Returns TRUE if word is number. }
  43.   FUNCTION Is_Noun(w : words) : Boolean;
  44.   VAR i, code : Integer;
  45.     match : Boolean;
  46.   BEGIN
  47.     Capitalize(w);
  48.     match := False;
  49.     Val(w, i, code);
  50.     IF code = 0 THEN match := True {If noun is a number, then OK noun}
  51.     ELSE BEGIN                    {not number -- so search list of nouns}
  52.       i := First_noun;
  53.       IF w <> '' THEN
  54.         WHILE (i <= MaxNoun) AND
  55.         (NOT match) DO
  56.           BEGIN
  57.             IF N[i]^.Has_Synonyms
  58.             THEN match := (POS(' '+w+' ', N[i]^.synonyms) <> 0)
  59.               {noun name also in synonym list}
  60.             ELSE match := (N[i]^.name = w);
  61.             i := i+1;
  62.           END;                    {exits if match found}
  63.       IF NOT match THEN
  64.         IF w = 'ALL' THEN match := True ELSE
  65.           IF w = 'EXITS' THEN match := True ELSE
  66.             IF w = 'DOORS' THEN match := True ELSE
  67.               IF w = 'GAME' THEN match := True ELSE
  68.                 IF w = 'IT' THEN match := True ELSE
  69.                   IF w = 'THEM' THEN match := True ELSE
  70.                     IF w = 'HIM' THEN match := True ELSE
  71.                       IF w = 'HER' THEN match := True ELSE
  72.                         IF w = 'VERB' THEN match := True ELSE
  73.                           IF w = 'NAME' THEN match := True ELSE
  74.                             IF w = 'NOUN' THEN match := True ELSE
  75.                               IF w = 'OBJECT' THEN match := True ELSE
  76.                                 IF w = 'ANY' THEN match := True ELSE
  77.                                   IF w = 'DOOR' THEN match := True;
  78.     END;                          {not number}
  79.     Is_Noun := match;
  80.   END;                            {Is_Noun}
  81.  
  82.   { Is_creature }
  83.   {Searches creature.name list via ascii name}
  84.   {Returns TRUE if found and FALSE otherwise.}
  85.   FUNCTION Is_Creature(w : words) : Boolean;
  86.   VAR i : Integer;                {index to creature array}
  87.     match : Boolean;
  88.   BEGIN
  89.     i := First_creature;
  90.     match := False;
  91.     IF w <> '' THEN
  92.       WHILE (i <= MaxCreature) AND
  93.       (NOT match) DO
  94.         BEGIN
  95.           IF M[i]^.Has_Synonyms
  96.           THEN match := (POS(' '+w+' ', M[i]^.synonyms) <> 0)
  97.             {creature name also in synonym list}
  98.           ELSE match := (M[i]^.name = w);
  99.           i := i+1;
  100.         END;                      {exits if match found}
  101.     Is_Creature := match;
  102.   END;                            {Is_Creature}
  103.  
  104.   { Is_prep }
  105.   {Checks word against hard-coded list of preps.}
  106.   {Returns TRUE if found and FALSE otherwise. }
  107.   FUNCTION Is_Prep(w : words) : Boolean;
  108.   BEGIN
  109.     Is_Prep := ((w = 'IN')
  110.                 OR (w = 'ON')
  111.                 OR (w = 'OFF')
  112.                 OR (w = 'UP')
  113.                 OR (w = 'DOWN')
  114.                 OR (w = 'THRU')
  115.                 OR (w = 'THROUGH')
  116.                 OR (w = 'INSIDE')
  117.                 OR (w = 'NEAR')
  118.                 OR (w = 'BESIDE')
  119.                 OR (w = 'BY')
  120.                 OR (w = 'UNDER')
  121.                 OR (w = 'OVER')
  122.                 OR (w = 'ACROSS')
  123.                 OR (w = 'BEHIND')
  124.                 OR (w = 'ANY')
  125.                 OR (w = 'ABOUT')
  126.                 OR (w = 'AT')
  127.                 OR (w = 'FROM')
  128.                 OR (w = 'FOR')
  129.                 OR (w = 'WITH')
  130.                 OR (w = 'INTO')
  131.                 OR (w = 'TO'));
  132.   END;                            {Is_Prep}
  133.  
  134.   PROCEDURE Parse(VAR sentence : s;
  135.                   VAR verb, noun, prep, object_word : words;
  136.   VAR syntax_error : Boolean); FORWARD;
  137.  
  138.   { Function Verb_Number }
  139.   {Searches verb list via ascii name. }
  140.   {Returns number if found and 0 otherwise}
  141.   FUNCTION Verb_Number(w : words) : Integer;
  142.   VAR i : Integer;                {index to verbs array}
  143.     match : Boolean;
  144.   BEGIN
  145.     i := 0;
  146.     match := False;
  147.     REPEAT
  148.       match := (V[i] = w);
  149.       i := i+1;
  150.     UNTIL ((i > MaxVerb) OR (match)); {exits if match found}
  151.     IF match
  152.     THEN Verb_Number := i-1
  153.     ELSE Verb_Number := 0;
  154.   END;                            {Verb_Number}
  155.  
  156.   FUNCTION Is_Visible(num : Integer) : Boolean; FORWARD;
  157.  
  158.  
  159.   { Function Noun_Number }
  160.   {Given a string (of type words), checks to see }
  161.   {if it's a noun or a creature. If it is, returns}
  162.   {the integer value of that noun or creature; }
  163.   {else it returns the value 0. }
  164.  
  165.   {This function will work with nouns that have }
  166.   {the same names. It does this by matching on }
  167.   {the adjective (if one has been entered) as well}
  168.   {as the noun. This function also looks at where}
  169.   {the noun is, i.e., if only one of the nouns }
  170.   {(with the same name) is in the room, being }
  171.   {carried or being worn -- that is assumed to be }
  172.   {the correct noun. If there is more than one }
  173.   {noun (with the same name) present, then an }
  174.   {error message asks the player to repeat his }
  175.   {command and be more specific about which noun }
  176.   {is meant. }
  177.   {Also matches for valid synonyms to valid nouns.}
  178.  
  179.   FUNCTION Noun_Number(w : words) : Integer;
  180.  
  181.   VAR i, j, k, Answer, RightOne, LastOne : Integer;
  182.     NumWithRightAdj, NounWithAdj : Integer;
  183.     match, FoundIt, FoundRightOne : Boolean;
  184.     TempAdj : words;
  185.   BEGIN
  186.     {$V-} Capitalize(w); {$V+}
  187.     Duplicate := False;
  188.     FoundIt := False;
  189.     NumWithRightAdj := 0;
  190.     NounWithAdj := 0;
  191.     IF MaxCreature > MaxNoun
  192.     THEN LastOne := MaxCreature
  193.     ELSE LastOne := MaxNoun;
  194.     IF (w = noun) AND (NounNumber <> 0)
  195.     THEN Answer := NounNumber ELSE
  196.       IF w = '' THEN
  197.         Answer := 0
  198.       ELSE
  199.         IF (w = object_word) AND (ObjectNumber <> 0)
  200.         THEN Answer := ObjectNumber
  201.         ELSE BEGIN
  202.           {main routine}
  203.           i := First_noun-1;
  204.           FoundRightOne := False;
  205.           j := 0;                 {number of matches}
  206.           k := 0;                 {number of first match}
  207.           WHILE (i <= MaxNoun) AND
  208.           (NOT FoundRightOne) DO
  209.             BEGIN
  210.               i := i+1;
  211.               IF N[i]^.Has_Synonyms
  212.               THEN match := (POS(' '+w+' ', N[i]^.synonyms) <> 0) {noun name also in list}
  213.               ELSE match := (N[i]^.name = w);
  214.               IF match THEN
  215.                 BEGIN
  216.                   j := j+1;
  217.                   IF j = 1 THEN k := i;
  218.                   IF Adjective = N[i]^.adj THEN
  219.                     BEGIN
  220.                       FoundRightOne := True;
  221.                       k := i;
  222.                       NumWithRightAdj := NumWithRightAdj+1;
  223.                       NounWithAdj := i;
  224.                       IF Is_Visible(i) THEN j := 1;
  225.                       {This is it -- visible and right adjective}
  226.                     END;
  227.                 END;              {match}
  228.             END;                  {exits if match found}
  229.           IF ((NOT FoundRightOne) AND (MaxCreature > MaxNoun)) THEN
  230.             BEGIN
  231.               i := First_creature-1;
  232.               WHILE (i <= MaxCreature) AND
  233.               (NOT FoundRightOne) DO
  234.                 BEGIN
  235.                   i := i+1;
  236.                   IF M[i]^.Has_Synonyms
  237.                   THEN match := (POS(' '+w+' ', M[i]^.synonyms) <> 0)
  238.                     {creature name also in synonym list}
  239.                   ELSE match := (M[i]^.name = w);
  240.                   IF match THEN
  241.                     BEGIN
  242.                       j := j+1;
  243.                       IF j = 1 THEN k := i;
  244.                       IF Adjective = M[i]^.adj THEN
  245.                         BEGIN
  246.                           FoundRightOne := True;
  247.                           k := i;
  248.                           NumWithRightAdj := NumWithRightAdj+1;
  249.                           NounWithAdj := i;
  250.                           IF Is_Visible(i) THEN j := 1;
  251.                           {This is it -- visible and right adjective}
  252.                         END;
  253.                     END;          {match}
  254.                 END;
  255.             END;                  {NOT FoundRightOne}
  256.           Duplicate := (j > 1);   {j = number of matches -- duplicates if > 1}
  257.           i := k;                 {i = first (maybe only) match}
  258.           IF NumWithRightAdj = 1 THEN
  259.             BEGIN
  260.               i := NounWithAdj;
  261.               Duplicate := False;
  262.               j := 1;
  263.             END;
  264.           IF (NOT Duplicate) THEN
  265.             IF j = 1
  266.             THEN Answer := i
  267.             ELSE Answer := 0;
  268.           IF Duplicate THEN
  269.             BEGIN
  270.               IF Is_Visible(i)    {i is first occurrance of name}
  271.               THEN BEGIN
  272.                 NumberInRoom := 1;
  273.                 DuplicatesInRoom[1].num := i;
  274.                 IF i <= MaxNoun
  275.                 THEN
  276.                   BEGIN
  277.                     DuplicatesInRoom[1].adj := N[i]^.adj;
  278.                     DuplicatesInRoom[1].name := N[i]^.name;
  279.                   END
  280.                 ELSE
  281.                   BEGIN
  282.                     DuplicatesInRoom[1].adj := M[i]^.adj;
  283.                     DuplicatesInRoom[1].name := M[i]^.name;
  284.                   END;
  285.               END                 {Is_Visible}
  286.               ELSE NumberInRoom := 0;
  287.               RightOne := i;      {to start with}
  288.               j := i;
  289.               REPEAT
  290.                 j := j+1;
  291.                 IF j <= MaxNoun
  292.                 THEN BEGIN        {noun}
  293.                   IF N[j]^.Has_Synonyms
  294.                   THEN match := (POS(' '+w+' ', N[j]^.synonyms) <> 0) {noun name also in list}
  295.                   ELSE match := (N[j]^.name = w);
  296.                   TempAdj := N[j]^.adj;
  297.                 END
  298.                 ELSE BEGIN        {creature}
  299.                   IF M[j]^.Has_Synonyms
  300.                   THEN match := (POS(' '+w+' ', M[j]^.synonyms) <> 0)
  301.                     {creature name also in synonym list}
  302.                   ELSE match := (M[j]^.name = w);
  303.                   TempAdj := M[j]^.adj;
  304.                 END;
  305.                 IF match AND (TempAdj = Adjective) {correct Adjective and match}
  306.                 THEN BEGIN
  307.                   FoundIt := True;
  308.                   RightOne := j;
  309.                 END;
  310.                 IF match AND (NOT FoundIt) AND Is_Visible(j) THEN
  311.                   BEGIN
  312.                     NumberInRoom := NumberInRoom+1;
  313.                     IF NumberInRoom <= MaxDupsInRoom THEN
  314.                       BEGIN
  315.                         DuplicatesInRoom[NumberInRoom].num := j;
  316.                         IF j <= MaxNoun
  317.                         THEN
  318.                           BEGIN
  319.                             DuplicatesInRoom[NumberInRoom].adj := N[j]^.adj;
  320.                             DuplicatesInRoom[NumberInRoom].name := N[j]^.name;
  321.                           END
  322.                         ELSE
  323.                           BEGIN
  324.                             DuplicatesInRoom[NumberInRoom].adj := M[j]^.adj;
  325.                             DuplicatesInRoom[NumberInRoom].name := M[j]^.name;
  326.                           END;
  327.                       END;
  328.                     RightOne := j;
  329.                   END;
  330.                 IF j = MaxNoun THEN j := Last_noun;
  331.               UNTIL ((j >= LastOne) OR FoundIt);
  332.               Answer := RightOne;
  333.               IF NumberInRoom < 2 THEN Duplicate := False;
  334.               IF FoundIt THEN Duplicate := False;
  335.             END;                  {IF Duplicate}
  336.         END;                      {main routine}
  337.     Noun_Number := Answer;
  338.   END;                            {Fn.Noun_Number}
  339.  
  340.  
  341.   { Function Name }
  342.   {Given an integer, returns a lowercase string}
  343.   {corresponding to the name of the room, noun,}
  344.   {or creature that has that number. }
  345.   FUNCTION name(num : Integer) : names;
  346.   VAR st : names;
  347.   BEGIN
  348.     IF num < First_noun           {then it's a room}
  349.     THEN st := Room[num]^.name
  350.     ELSE
  351.       IF num < First_creature
  352.       THEN st := N[num]^.name
  353.       ELSE st := M[num]^.name;
  354.     Normalize(st);
  355.     name := st;
  356.   END;                            {fn.name}
  357.  
  358.   { Function Location }
  359.   {Given an integer, returns its ROOM location }
  360.   {unless it's in a closed noun. If it's inside }
  361.   {a closed noun, that noun's number is returned,}
  362.   {else the room number is returned. Basically, }
  363.   {returns the location at which it is visible. }
  364.   FUNCTION location(num : Integer) : Integer;
  365.   VAR i : Integer;
  366.   BEGIN
  367.     IF num = 0 THEN location := 0
  368.     ELSE
  369.       IF num <= MaxNoun
  370.       THEN
  371.         BEGIN
  372.           i := N[num]^.location;
  373.           IF (i > MaxRoom) AND (i <> Wearing)
  374.           THEN IF N[i]^.open
  375.             THEN i := location(i);
  376.           location := i;
  377.         END
  378.       ELSE
  379.         BEGIN
  380.           i := M[num]^.location;
  381.           IF (i > MaxRoom) AND (i <> Wearing)
  382.           THEN IF N[i]^.open
  383.             THEN i := location(i);
  384.           location := i;
  385.         END;
  386.   END;                            {fn.Location}
  387.  
  388.   { Function Is_Visible }
  389.   {Given a noun number, returns true if the noun}
  390.   {is present in the room and is not inside a }
  391.   {closed noun -- i.e. if it can be seen by the }
  392.   {player in his/her current location. }
  393.   FUNCTION Is_Visible {(Num: integer): boolean} ;
  394.   VAR i : Integer;
  395.   BEGIN
  396.     i := location(num);
  397.     IF ((i = Current_room) OR (i = Player) OR (i = Wearing))
  398.     THEN Is_Visible := True
  399.     ELSE Is_Visible := False;
  400.   END;                            {fn.Is_Visible}
  401.  
  402.  
  403.   { Adjust_Count }
  404.   {Adjusts count of number items at PLACE}
  405.   {by added INCREMENT. }
  406.   PROCEDURE Adjust_Count(PLACE, INCREMENT : Integer);
  407.   BEGIN
  408.     IF PLACE = Wearing THEN Items_Being_Worn := Items_Being_Worn+INCREMENT;
  409.     IF PLACE = Player THEN Items_Being_Carried := Items_Being_Carried+INCREMENT;
  410.     IF (PLACE >= First_Room) AND (PLACE <= MaxRoom)
  411.     THEN Room[PLACE]^.nouns_inside := Room[PLACE]^.nouns_inside+INCREMENT;
  412.     IF (PLACE >= First_noun) AND (PLACE <= MaxNoun)
  413.     THEN N[PLACE]^.nouns_inside := N[PLACE]^.nouns_inside+INCREMENT;
  414.     IF (PLACE >= First_creature) AND (PLACE <= MaxCreature)
  415.     THEN M[PLACE]^.nouns_inside := M[PLACE]^.nouns_inside+INCREMENT;
  416.   END;                            {Adjust_Count}
  417.  
  418.   { SwapWords }
  419.   {Swaps two words in a sentence}
  420.   PROCEDURE SwapWords(FromWord, ToWord : words; VAR sentence : s; LowerCase : Boolean);
  421.   VAR
  422.     Spot, FromLength : Integer;
  423.   BEGIN
  424.     IF LowerCase THEN Normalize(ToWord); {make lower case}
  425.     FromLength := Length(FromWord);
  426.     WHILE POS(FromWord, sentence) <> 0 DO
  427.       BEGIN
  428.         Spot := POS(FromWord, sentence);
  429.         Delete(sentence, Spot, FromLength); {delete FromWord}
  430.         Insert(ToWord, sentence, Spot); {insert ToWord}
  431.       END;
  432.   END;                            {SwapWords}
  433.  
  434.   { Handle Word Combinations }
  435.   {Remove the specific word combination from the}
  436.   {sentence and replace them with other words.}
  437.   PROCEDURE Handle_Word_Combinations(VAR sentence : s);
  438.   BEGIN
  439.     SwapWords(',', ' AND ', sentence, False); {convert ,s to 'and'}
  440.     SwapWords(';', ' AND ', sentence, False); {convert ;s to 'and'}
  441.     SwapWords('  ', ' ', sentence, False); {remove any double spaces}
  442.     SwapWords(' AND AND ', ' AND ', sentence, False);
  443.     SwapWords(' AND THEN ', ' AND ', sentence, False);
  444.     SwapWords(' IN TO ', ' INTO ', sentence, False);
  445.     SwapWords(' NEAR BY ', ' BY ', sentence, False);
  446.     SwapWords(' NEXT TO ', ' NEAR ', sentence, False);
  447.   END;
  448.  
  449.  
  450.   { Check For Name }
  451.   {Checks to see if the command is being addressed to a creature}
  452.   {If it is then routine sets Global NameStr to name of creature and}
  453.   {  the Global NameNum to the creature's number.}
  454.   {If it is NOT then routine sets Global NameStr to '' and}
  455.   {  the Global NameNum to 0.}
  456.   {After returning from this routine, sentence has the name (if any) stripped off}
  457.   PROCEDURE CheckForName(VAR sentence : s);
  458.   VAR Fword : words;
  459.     num : Integer;
  460.   BEGIN
  461.     Fword := first_word(sentence);
  462.     num := Noun_Number(Fword);
  463.     IF ((num < First_creature) OR (num > Last_Creature))
  464.     THEN num := 0;                {Not a valid creature}
  465.     IF ((Fword = 'ANYONE') OR (Fword = 'ANYBODY'))
  466.     THEN num := Num_Verbs+1;
  467.     IF ((Fword = 'EVERYONE') OR (Fword = 'EVERYBODY'))
  468.     THEN num := Num_Verbs+2;
  469.     IF num = 0 THEN               {Command is NOT being addressed to a creature}
  470.       BEGIN
  471.         NameStr := '';
  472.         NameNum := 0;
  473.       END
  474.     ELSE BEGIN                    {Command is NOT being addressed to a creature}
  475.       NameNum := num;
  476.       Normalize(Fword);           {make lower case except for first letter}
  477.       IF (Fword[1] IN ['a'..'z'])
  478.       THEN Fword[1] := Char(Integer(Fword[1])-32);
  479.       NameStr := Fword;
  480.       sentence := But_First(sentence); {strip off name}
  481.       Fword := first_word(sentence); {second word of command}
  482.       IF Fword = 'AND' THEN sentence := But_First(sentence); {strip off AND}
  483.     END;
  484.   END;
  485.  
  486.