home *** CD-ROM | disk | FTP | other *** search
-
- {SPCTOOLS.PA2 -- special GAGS tools}
-
- { Is_verb }
- {Searches verb list via ascii name. }
- {Returns TRUE if found and FALSE otherwise}
- {NOTE: Synonyms have already been taken care of in PARSE}
- FUNCTION Is_Verb(w : words) : Boolean;
- VAR i : Integer; {index to verbs array}
- match : Boolean;
- BEGIN
- i := 0; {start with 'ANY'}
- match := False;
- REPEAT
- match := (V[i] = w);
- i := i+1;
- UNTIL ((i > MaxVerb) OR (match)); {exits if match found}
- IF NOT match THEN IF w = 'VERB' THEN match := True;
- Is_Verb := match;
- END; {Is_Verb}
-
- { Is_direction }
- {Searches direction list via ascii name. }
- {Returns TRUE if found and FALSE otherwise}
- FUNCTION Is_Direction(w : words) : Boolean;
- VAR i : Integer;
- match : Boolean;
- BEGIN
- i := 1;
- match := False;
- REPEAT
- match := (V[i] = w);
- i := i+1;
- UNTIL ((i > Num_Dirs) OR (match)); {exits if match found}
- Is_Direction := match;
- END; {Is_Verb}
-
- { Is_noun }
- {Searches noun.name list via ascii name. }
- {Also matches for valid synonyms to valid nouns.}
- {Returns TRUE if found and FALSE otherwise. }
- {Also Returns TRUE if word is number. }
- FUNCTION Is_Noun(w : words) : Boolean;
- VAR i, code : Integer;
- match : Boolean;
- BEGIN
- Capitalize(w);
- match := False;
- Val(w, i, code);
- IF code = 0 THEN match := True {If noun is a number, then OK noun}
- ELSE BEGIN {not number -- so search list of nouns}
- i := First_noun;
- IF w <> '' THEN
- WHILE (i <= MaxNoun) AND
- (NOT match) DO
- BEGIN
- IF N[i]^.Has_Synonyms
- THEN match := (POS(' '+w+' ', N[i]^.synonyms) <> 0)
- {noun name also in synonym list}
- ELSE match := (N[i]^.name = w);
- i := i+1;
- END; {exits if match found}
- IF NOT match THEN
- IF w = 'ALL' THEN match := True ELSE
- IF w = 'EXITS' THEN match := True ELSE
- IF w = 'DOORS' THEN match := True ELSE
- IF w = 'GAME' THEN match := True ELSE
- IF w = 'IT' THEN match := True ELSE
- IF w = 'THEM' THEN match := True ELSE
- IF w = 'HIM' THEN match := True ELSE
- IF w = 'HER' THEN match := True ELSE
- IF w = 'VERB' THEN match := True ELSE
- IF w = 'NAME' THEN match := True ELSE
- IF w = 'NOUN' THEN match := True ELSE
- IF w = 'OBJECT' THEN match := True ELSE
- IF w = 'ANY' THEN match := True ELSE
- IF w = 'DOOR' THEN match := True;
- END; {not number}
- Is_Noun := match;
- END; {Is_Noun}
-
- { Is_creature }
- {Searches creature.name list via ascii name}
- {Returns TRUE if found and FALSE otherwise.}
- FUNCTION Is_Creature(w : words) : Boolean;
- VAR i : Integer; {index to creature array}
- match : Boolean;
- BEGIN
- i := First_creature;
- match := False;
- IF w <> '' THEN
- WHILE (i <= MaxCreature) AND
- (NOT match) DO
- BEGIN
- IF M[i]^.Has_Synonyms
- THEN match := (POS(' '+w+' ', M[i]^.synonyms) <> 0)
- {creature name also in synonym list}
- ELSE match := (M[i]^.name = w);
- i := i+1;
- END; {exits if match found}
- Is_Creature := match;
- END; {Is_Creature}
-
- { Is_prep }
- {Checks word against hard-coded list of preps.}
- {Returns TRUE if found and FALSE otherwise. }
- FUNCTION Is_Prep(w : words) : Boolean;
- BEGIN
- Is_Prep := ((w = 'IN')
- OR (w = 'ON')
- OR (w = 'OFF')
- OR (w = 'UP')
- OR (w = 'DOWN')
- OR (w = 'THRU')
- OR (w = 'THROUGH')
- OR (w = 'INSIDE')
- OR (w = 'NEAR')
- OR (w = 'BESIDE')
- OR (w = 'BY')
- OR (w = 'UNDER')
- OR (w = 'OVER')
- OR (w = 'ACROSS')
- OR (w = 'BEHIND')
- OR (w = 'ANY')
- OR (w = 'ABOUT')
- OR (w = 'AT')
- OR (w = 'FROM')
- OR (w = 'FOR')
- OR (w = 'WITH')
- OR (w = 'INTO')
- OR (w = 'TO'));
- END; {Is_Prep}
-
- PROCEDURE Parse(VAR sentence : s;
- VAR verb, noun, prep, object_word : words;
- VAR syntax_error : Boolean); FORWARD;
-
- { Function Verb_Number }
- {Searches verb list via ascii name. }
- {Returns number if found and 0 otherwise}
- FUNCTION Verb_Number(w : words) : Integer;
- VAR i : Integer; {index to verbs array}
- match : Boolean;
- BEGIN
- i := 0;
- match := False;
- REPEAT
- match := (V[i] = w);
- i := i+1;
- UNTIL ((i > MaxVerb) OR (match)); {exits if match found}
- IF match
- THEN Verb_Number := i-1
- ELSE Verb_Number := 0;
- END; {Verb_Number}
-
- FUNCTION Is_Visible(num : Integer) : Boolean; FORWARD;
-
-
- { Function Noun_Number }
- {Given a string (of type words), checks to see }
- {if it's a noun or a creature. If it is, returns}
- {the integer value of that noun or creature; }
- {else it returns the value 0. }
-
- {This function will work with nouns that have }
- {the same names. It does this by matching on }
- {the adjective (if one has been entered) as well}
- {as the noun. This function also looks at where}
- {the noun is, i.e., if only one of the nouns }
- {(with the same name) is in the room, being }
- {carried or being worn -- that is assumed to be }
- {the correct noun. If there is more than one }
- {noun (with the same name) present, then an }
- {error message asks the player to repeat his }
- {command and be more specific about which noun }
- {is meant. }
- {Also matches for valid synonyms to valid nouns.}
-
- FUNCTION Noun_Number(w : words) : Integer;
-
- VAR i, j, k, Answer, RightOne, LastOne : Integer;
- NumWithRightAdj, NounWithAdj : Integer;
- match, FoundIt, FoundRightOne : Boolean;
- TempAdj : words;
- BEGIN
- {$V-} Capitalize(w); {$V+}
- Duplicate := False;
- FoundIt := False;
- NumWithRightAdj := 0;
- NounWithAdj := 0;
- IF MaxCreature > MaxNoun
- THEN LastOne := MaxCreature
- ELSE LastOne := MaxNoun;
- IF (w = noun) AND (NounNumber <> 0)
- THEN Answer := NounNumber ELSE
- IF w = '' THEN
- Answer := 0
- ELSE
- IF (w = object_word) AND (ObjectNumber <> 0)
- THEN Answer := ObjectNumber
- ELSE BEGIN
- {main routine}
- i := First_noun-1;
- FoundRightOne := False;
- j := 0; {number of matches}
- k := 0; {number of first match}
- WHILE (i <= MaxNoun) AND
- (NOT FoundRightOne) DO
- BEGIN
- i := i+1;
- IF N[i]^.Has_Synonyms
- THEN match := (POS(' '+w+' ', N[i]^.synonyms) <> 0) {noun name also in list}
- ELSE match := (N[i]^.name = w);
- IF match THEN
- BEGIN
- j := j+1;
- IF j = 1 THEN k := i;
- IF Adjective = N[i]^.adj THEN
- BEGIN
- FoundRightOne := True;
- k := i;
- NumWithRightAdj := NumWithRightAdj+1;
- NounWithAdj := i;
- IF Is_Visible(i) THEN j := 1;
- {This is it -- visible and right adjective}
- END;
- END; {match}
- END; {exits if match found}
- IF ((NOT FoundRightOne) AND (MaxCreature > MaxNoun)) THEN
- BEGIN
- i := First_creature-1;
- WHILE (i <= MaxCreature) AND
- (NOT FoundRightOne) DO
- BEGIN
- i := i+1;
- IF M[i]^.Has_Synonyms
- THEN match := (POS(' '+w+' ', M[i]^.synonyms) <> 0)
- {creature name also in synonym list}
- ELSE match := (M[i]^.name = w);
- IF match THEN
- BEGIN
- j := j+1;
- IF j = 1 THEN k := i;
- IF Adjective = M[i]^.adj THEN
- BEGIN
- FoundRightOne := True;
- k := i;
- NumWithRightAdj := NumWithRightAdj+1;
- NounWithAdj := i;
- IF Is_Visible(i) THEN j := 1;
- {This is it -- visible and right adjective}
- END;
- END; {match}
- END;
- END; {NOT FoundRightOne}
- Duplicate := (j > 1); {j = number of matches -- duplicates if > 1}
- i := k; {i = first (maybe only) match}
- IF NumWithRightAdj = 1 THEN
- BEGIN
- i := NounWithAdj;
- Duplicate := False;
- j := 1;
- END;
- IF (NOT Duplicate) THEN
- IF j = 1
- THEN Answer := i
- ELSE Answer := 0;
- IF Duplicate THEN
- BEGIN
- IF Is_Visible(i) {i is first occurrance of name}
- THEN BEGIN
- NumberInRoom := 1;
- DuplicatesInRoom[1].num := i;
- IF i <= MaxNoun
- THEN
- BEGIN
- DuplicatesInRoom[1].adj := N[i]^.adj;
- DuplicatesInRoom[1].name := N[i]^.name;
- END
- ELSE
- BEGIN
- DuplicatesInRoom[1].adj := M[i]^.adj;
- DuplicatesInRoom[1].name := M[i]^.name;
- END;
- END {Is_Visible}
- ELSE NumberInRoom := 0;
- RightOne := i; {to start with}
- j := i;
- REPEAT
- j := j+1;
- IF j <= MaxNoun
- THEN BEGIN {noun}
- IF N[j]^.Has_Synonyms
- THEN match := (POS(' '+w+' ', N[j]^.synonyms) <> 0) {noun name also in list}
- ELSE match := (N[j]^.name = w);
- TempAdj := N[j]^.adj;
- END
- ELSE BEGIN {creature}
- IF M[j]^.Has_Synonyms
- THEN match := (POS(' '+w+' ', M[j]^.synonyms) <> 0)
- {creature name also in synonym list}
- ELSE match := (M[j]^.name = w);
- TempAdj := M[j]^.adj;
- END;
- IF match AND (TempAdj = Adjective) {correct Adjective and match}
- THEN BEGIN
- FoundIt := True;
- RightOne := j;
- END;
- IF match AND (NOT FoundIt) AND Is_Visible(j) THEN
- BEGIN
- NumberInRoom := NumberInRoom+1;
- IF NumberInRoom <= MaxDupsInRoom THEN
- BEGIN
- DuplicatesInRoom[NumberInRoom].num := j;
- IF j <= MaxNoun
- THEN
- BEGIN
- DuplicatesInRoom[NumberInRoom].adj := N[j]^.adj;
- DuplicatesInRoom[NumberInRoom].name := N[j]^.name;
- END
- ELSE
- BEGIN
- DuplicatesInRoom[NumberInRoom].adj := M[j]^.adj;
- DuplicatesInRoom[NumberInRoom].name := M[j]^.name;
- END;
- END;
- RightOne := j;
- END;
- IF j = MaxNoun THEN j := Last_noun;
- UNTIL ((j >= LastOne) OR FoundIt);
- Answer := RightOne;
- IF NumberInRoom < 2 THEN Duplicate := False;
- IF FoundIt THEN Duplicate := False;
- END; {IF Duplicate}
- END; {main routine}
- Noun_Number := Answer;
- END; {Fn.Noun_Number}
-
-
- { Function Name }
- {Given an integer, returns a lowercase string}
- {corresponding to the name of the room, noun,}
- {or creature that has that number. }
- FUNCTION name(num : Integer) : names;
- VAR st : names;
- BEGIN
- IF num < First_noun {then it's a room}
- THEN st := Room[num]^.name
- ELSE
- IF num < First_creature
- THEN st := N[num]^.name
- ELSE st := M[num]^.name;
- Normalize(st);
- name := st;
- END; {fn.name}
-
- { Function Location }
- {Given an integer, returns its ROOM location }
- {unless it's in a closed noun. If it's inside }
- {a closed noun, that noun's number is returned,}
- {else the room number is returned. Basically, }
- {returns the location at which it is visible. }
- FUNCTION location(num : Integer) : Integer;
- VAR i : Integer;
- BEGIN
- IF num = 0 THEN location := 0
- ELSE
- IF num <= MaxNoun
- THEN
- BEGIN
- i := N[num]^.location;
- IF (i > MaxRoom) AND (i <> Wearing)
- THEN IF N[i]^.open
- THEN i := location(i);
- location := i;
- END
- ELSE
- BEGIN
- i := M[num]^.location;
- IF (i > MaxRoom) AND (i <> Wearing)
- THEN IF N[i]^.open
- THEN i := location(i);
- location := i;
- END;
- END; {fn.Location}
-
- { Function Is_Visible }
- {Given a noun number, returns true if the noun}
- {is present in the room and is not inside a }
- {closed noun -- i.e. if it can be seen by the }
- {player in his/her current location. }
- FUNCTION Is_Visible {(Num: integer): boolean} ;
- VAR i : Integer;
- BEGIN
- i := location(num);
- IF ((i = Current_room) OR (i = Player) OR (i = Wearing))
- THEN Is_Visible := True
- ELSE Is_Visible := False;
- END; {fn.Is_Visible}
-
-
- { Adjust_Count }
- {Adjusts count of number items at PLACE}
- {by added INCREMENT. }
- PROCEDURE Adjust_Count(PLACE, INCREMENT : Integer);
- BEGIN
- IF PLACE = Wearing THEN Items_Being_Worn := Items_Being_Worn+INCREMENT;
- IF PLACE = Player THEN Items_Being_Carried := Items_Being_Carried+INCREMENT;
- IF (PLACE >= First_Room) AND (PLACE <= MaxRoom)
- THEN Room[PLACE]^.nouns_inside := Room[PLACE]^.nouns_inside+INCREMENT;
- IF (PLACE >= First_noun) AND (PLACE <= MaxNoun)
- THEN N[PLACE]^.nouns_inside := N[PLACE]^.nouns_inside+INCREMENT;
- IF (PLACE >= First_creature) AND (PLACE <= MaxCreature)
- THEN M[PLACE]^.nouns_inside := M[PLACE]^.nouns_inside+INCREMENT;
- END; {Adjust_Count}
-
- { SwapWords }
- {Swaps two words in a sentence}
- PROCEDURE SwapWords(FromWord, ToWord : words; VAR sentence : s; LowerCase : Boolean);
- VAR
- Spot, FromLength : Integer;
- BEGIN
- IF LowerCase THEN Normalize(ToWord); {make lower case}
- FromLength := Length(FromWord);
- WHILE POS(FromWord, sentence) <> 0 DO
- BEGIN
- Spot := POS(FromWord, sentence);
- Delete(sentence, Spot, FromLength); {delete FromWord}
- Insert(ToWord, sentence, Spot); {insert ToWord}
- END;
- END; {SwapWords}
-
- { Handle Word Combinations }
- {Remove the specific word combination from the}
- {sentence and replace them with other words.}
- PROCEDURE Handle_Word_Combinations(VAR sentence : s);
- BEGIN
- SwapWords(',', ' AND ', sentence, False); {convert ,s to 'and'}
- SwapWords(';', ' AND ', sentence, False); {convert ;s to 'and'}
- SwapWords(' ', ' ', sentence, False); {remove any double spaces}
- SwapWords(' AND AND ', ' AND ', sentence, False);
- SwapWords(' AND THEN ', ' AND ', sentence, False);
- SwapWords(' IN TO ', ' INTO ', sentence, False);
- SwapWords(' NEAR BY ', ' BY ', sentence, False);
- SwapWords(' NEXT TO ', ' NEAR ', sentence, False);
- END;
-
-
- { Check For Name }
- {Checks to see if the command is being addressed to a creature}
- {If it is then routine sets Global NameStr to name of creature and}
- { the Global NameNum to the creature's number.}
- {If it is NOT then routine sets Global NameStr to '' and}
- { the Global NameNum to 0.}
- {After returning from this routine, sentence has the name (if any) stripped off}
- PROCEDURE CheckForName(VAR sentence : s);
- VAR Fword : words;
- num : Integer;
- BEGIN
- Fword := first_word(sentence);
- num := Noun_Number(Fword);
- IF ((num < First_creature) OR (num > Last_Creature))
- THEN num := 0; {Not a valid creature}
- IF ((Fword = 'ANYONE') OR (Fword = 'ANYBODY'))
- THEN num := Num_Verbs+1;
- IF ((Fword = 'EVERYONE') OR (Fword = 'EVERYBODY'))
- THEN num := Num_Verbs+2;
- IF num = 0 THEN {Command is NOT being addressed to a creature}
- BEGIN
- NameStr := '';
- NameNum := 0;
- END
- ELSE BEGIN {Command is NOT being addressed to a creature}
- NameNum := num;
- Normalize(Fword); {make lower case except for first letter}
- IF (Fword[1] IN ['a'..'z'])
- THEN Fword[1] := Char(Integer(Fword[1])-32);
- NameStr := Fword;
- sentence := But_First(sentence); {strip off name}
- Fword := first_word(sentence); {second word of command}
- IF Fword = 'AND' THEN sentence := But_First(sentence); {strip off AND}
- END;
- END;
-