"Library header" )> ;"Filled in by compiler" > "Debugging" ;"Enables trace messages" > ;"Enables XTREE, XGOTO, etc." > '
> '(ELSE T)>> !.A> '(ELSE T)>> > >> > > ) (ELSE )> "Global variables" > ;"Player's location" ;"Score, or hours in V3 time games" ;"Turn count, or minutes in V3 time games" > ;"Interrupt queue" ;"Number of slots used in IQUEUE" > ;"Temporary table for miscellaneous use" ;"TODO: Make STANDARD-WAIT a constant" ;"TODO: Fix USAVE" ;"Whether the player's location is lit" ;"Verbosity modes (controlled by player)" ;"Report modes (automatically set)" > "Extensions for TELL" A * CT * CA * NOUN-PHRASE * OBJSPEC * SYNTAX-LINE * WORD * MATCHING-WORD * * * > "Version considerations: certain values are bytes on V3 but words on all other versions. These macros let us write the same code for all versions." > > > >) (ELSE > > > >)> "Property and flag defaults" > )> ;"These are all set on ROOMS in case no game objects define them." ;"TODO: Eliminate some standard flags or make them optional. 27 flags in the library only leaves 5 for V3 games." ;"Default property values. Even properties with uninteresting defaults are listed here in case no game objects define them." > > > > > > > > > > > > "Parser" > > ;"We need to use up to three sets of input buffers to parse an action before performing it. These sets are prefixed with KBD, EDIT, and CONT. >MAN, OPEN DOOR The command is read into KBD, then copied into EDIT and expanded, then copied into CONT. KBD: MAN, OPEN DOOR EDIT: ,TELL MAN . OPEN DOOR CONT: ,TELL MAN . OPEN DOOR Which do you mean, the tall man or the short man? >TLL The answer to the question is read into KBD, then copied into EDIT. KBD: TLL EDIT: TLL CONT: ,TELL MAN . OPEN DOOR I don't know the word 'tll'. >OOPS TALL The correction command is read into KBD, and the word in EDIT is corrected. KBD: OOPS TALL EDIT: TALL CONT: ,TELL MAN . OPEN DOOR The tall man opens the door." > > > > > > >>> >>>>> >>> >>>>> > > > > >>>> .A>> > > > >>> >>>>> ;"part of speech flags" ;"value for 1st part of speech" ;"value for 2nd part of speech") (T )> "Constants" ;"Determines whether a word has the given part of speech, and returns its part of speech value if so. Args: W: The word. PS: The part of speech's PS? constant, e.g. PS?VERB. P1: The part of speech's P1? constant, e.g. P1?VERB. If omitted, the value will not be returned, only a boolean indicating whether the word has the given part of speech. Returns: If the word does not have the given part of speech, returns 0. Otherwise, returns the word's value for the given part of speech if P1 was supplied, or 1 if not." )> > ) (<==? .P1> ) (ELSE )>)>> .F> ;"Gets the word at the given index in LEXBUF. Args: N: The index, starting at 1. Returns: A pointer to the vocab word, or 0 if the word at the given index was unrecognized." 1>>> .R> ;"Prints the word at the given index in LEXBUF. Args: N: The index, starting at 1." 1>>> >> 1>> > >>> ;"Number of words in the command" > ;"Verb number" > ;"Verb word pointer" ;"Verb word number; 0 = invalid, use P-V-WORD instead" ;"Number of noun phrases" > ;"Prep number before first NP" > ;"Prep number before second NP" > ;"Matched syntax line pointer" ;"Word number in held buffer where next parse should resume; 0 or less = get fresh input" "Structure type for OOPS" ) ;"Value of WINNER before parsing the failed command" (OOPS-WN FIX 'OFFSET 4 'NTH GETB 'PUT PUTB) ;"Word number in EDIT buffer to be corrected by OOPS" (OOPS-CONT FIX 'OFFSET 5 'NTH GETB 'PUT PUTB) ;"Value of P-CONT before parsing the failed command"> >>> >> '("ARGS" A) >>> '(OOPS-WN OOPS-CONT OOPS-O-REASON OOPS-WINNER)> "Structured types for storing noun phrases. NOUN-PHRASE: NP-YTBL and NP-NTBL are tables of OBJSPECs, with the corresponding counts in NP-YCNT and NP-NCNT. NP-MODE is a mode byte: either 0, MCM-ALL, or MCM-ANY. The helper macros NP-YSPEC and NP-NSPEC return an OBJSPEC by 1-based index. OBJSPEC: OBJSPEC-ADJ contains an adjective (number or voc word, depending on version) or special flag (TBD). OBJSPEC-NOUN contains a noun (voc word). Either field may be 0, but not both." 0 0 > 'NP-YTBL > 'NP-NTBL >>> ) ( <* ,P-OBJSPEC-SIZE <- .I 1>>>) (ELSE >>)>> ) ( <* ,P-OBJSPEC-SIZE <- .I 1>>>) (ELSE >>)>> ;"Resets a noun phrase to be empty with no mode." > ;"Copies the contents of one noun phrase into another." >> <* ,P-OBJSPEC-SIZE .C>> >> <* ,P-OBJSPEC-SIZE .C>> >> > ) (<=? .F ,MCM-ANY> )> ;"YSPECs" > ) (<=? .F ,MCM-ANY> )>) (ELSE > )> >>)> ;"NSPECs" > )> > )> >>> > > ) (.A ) (.N ) (ELSE )>> > >) (ELSE >)> )> )> >> > > > > .V> )> >> >)> "Noun phrase storage for direct/indirect objects" > > "Extra noun phrase for temporary use" > "Tables for objects recognized from object specs. These each have one length byte, a dummy byte (V4+ only), then P-MAX-OBJECTS bytes/words for the objects." >> "Matched direct objects" > "Matched indirect objects" > "Extra objects for temporary use" > .SRC .DEST <+ 1 ,P-MAX-OBJECTS>>> "Structured type for backing up a complete parsed command" 'PST-PRSOS 'PST-PRSIS 'PST-READBUF 'PST-LEXBUF >> > > > > > > > > > > > > ,P-PRSOS> ,P-PRSIS> > ,LEXBUF> ,READBUF> > > > > > > > ;"Set variables calculated from these" ) ( <0? >>> >) (<1? .L> >) (ELSE )> <0? >>> >) (<1? .L> >) (ELSE )> > > >)>> "Orphaning" "Pseudo-Objects" "Pronouns" <=? .X ,MANY-OBJECTS> >>> >>> > >>> >>> "Buzzwords" "Parser entry points" ;"Reads a command and processes it, repeating forever. The behavior of MAIN-LOOP can be extended by overriding macros such as HOOK-BEFORE-PARSER. These extensions will be respected by other code that simulates the main loop, e.g. V-WAIT." > .RESULT> > > ,M-END>> > )> > )> >> ;"Dummy implementations of MAIN-LOOP's BEFORE hooks." >> >> >> >> ;"Dummy implementations of MAIN-LOOP's AFTER hooks. These take a single parameter, an atom naming the local variable that stores the function's result." >> >> >> >> ;"Dummy implementations of miscellaneous MAIN-LOOP hooks." >> >> ;"Reads and parses a command. The primary outputs are PRSA, PRSO (+ PRSO-DIR), and PRSI, suitable for passing to PERFORM. If multiple objects are used for PRSO or PRSI, they will be set to MANY-OBJECTS and PERFORM will have to read P-PRSOS or P-PRSIS. Sets: P-LEN P-V P-NOBJ P-P1 P-P2 HERE PRSA PRSO PRSO-DIR P-PRSOS PRSI P-PRSIS P-BUTS P-EXTRA USAVE P-NP-DOBJ P-NP-IOBJ P-OOPS-DATA P-CONT " > > > > ;"Fill READBUF and LEXBUF" )> ) ( ;"Print a blank line between multiple commands" > )>)>) (ELSE > > )> > ;> > )> ;"Save undo state unless this looks like an undo command" <=? ,W?UNDO> <=? ,W?\. ,W?THEN>>>) (ELSE > )>)>> ;"Handle OOPS" ,W?OOPS>> > >) (ELSE )>) (<=? ,P-LEN 1> ) (ELSE )>)>)> ;"Save command in edit buffer for OOPS" )> ;"Handle an orphan response, which may abort parsing or ask us to skip steps" > )> ) (<=? .O-R ,O-RES-FAILED> > ) (<=? .O-R ,O-RES-SET-NP> ;"TODO: Set the P-variables somewhere else? Shouldn't we fill in what we know about the command-to-be when we ask the orphaning question, not when we get the response?" > > ;"Don't re-match P-NP-DOBJ when we've just orphaned PRSI. Use the saved match results. There won't be a NP to match if we GWIMmed PRSO." ) (ELSE )>) (<=? .O-R ,O-RES-SET-PRSTBL> ) (ELSE )>)> >)> ;"If we aren't handling this command as an orphan response, convert it if needed and copy it to CONT bufs" ;"Translate order syntax (HAL, OPEN THE POD BAY DOOR or TELL HAL TO OPEN THE POD BAY DOOR) into multi-command syntax (\,TELL HAL THEN OPEN THE POD BAY DOOR)." >)>)>)> ;"Identify parts of speech, parse noun phrases" > > > ;"Identify the verb, prepositions, and noun phrases" ) W V) ;"Reached the end of the command" ) (> >>> ;"Word not in vocabulary" ) (<=? .W ,W?THEN ,W?\.> ;"End of command, maybe start of a new one" > ) (ELSE )> ) ( > <=? .V ,ACT?WALK>>> ;"Found the verb" ) ( ,ACT?WALK> >> ;"Found a direction" ) (> ;"Found a preposition" ;"Only keep the first preposition for each object" > ) ( > )>) ( ;"Found a noun phrase" > >) (<==? .NOBJ 2> >) (ELSE )> ) (ELSE )>) (ELSE ;"Unexpected word type" )> >> "-" N " P2=" MATCHING-WORD ,P-P2 ,PS?PREPOSITION 0 "(" N ,P-P2 ") IOBJS=+" N "-" N "]" CR> ;"If we have a direction and nothing else except maybe a WALK verb, it's a movement command." ,ACT?WALK> <0? .NOBJ> > > > )> )> ;"Otherwise, a verb is required and a direction is forbidden." ) (.DIR )> >)> ;"Match syntax lines and objects" >> )>) ( ;"We already found a syntax line last time, but we need FIND-OBJECTS to match at least one noun phrase." > )>)> ;"Save command for AGAIN" > )> ;"If successful PRSO, back up PRSO for IT" > > >> ;"Stores WN and P-CONT in P-OOPS-WN/CONT, and copies LEXBUF/READBUF to EDIT-LEXBUF/READBUF if needed." )> ;"NOTE: P-OOPS-O-REASON is not set here." > ;"Replaces word P-OOPS-WN in EDIT-LEXBUF (and -READBUF) with word N from the active buffer, then sets the active buffer to the held buffer." > ;"Copy word into LEXBUF" > 1> .W> ;"Copy word into READBUF" 1>>> >> 1>>> >> .SL> ;"Copy the new word and overwrite the end of the old one with spaces" .SL> 1>> .MAX) >) ( ;"Shift the rest of the buffer up to make room" > >)> > ,READBUF-SIZE> >)> >> .SL> ;"Update pointers to subsequent words" > .MAX) 1> <+ 1>> .DELTA>>>)>)> ;"Activate held buffers, restore orphaning state, and clear oops state" > > > >> ;"Copy word into LEXBUF" 1> .NEW-WORD> ;"Copy word into READBUF" 1>>> >> > .NL> ;"Overwrite the end of the old word with spaces" 1>> .MAX) >) ( ;"Shift the rest of the buffer up to make room" > >)> > ,READBUF-SIZE> >)> >> ;"Update pointers to subsequent words" > .MAX) 1> <+ 1>> .DELTA>>>)>)> ;"Copy the new word" .NL> >> ) MIN BL S MAX NL DELTA) ) ( >)> > ;"Shift LEXBUF up to make room (sacrificing the last word if needed)" >)> > .MIN -2) > >>>)> ;"Write the new entry and set the word count" 1>>) (ELSE 1>>>)> 1> .NEW-WORD> .NL> 1> .S> > ;"Shift READBUF up to make room" > > >)> ,READBUF-SIZE> >)> >)> >> ;"Update pointers to subsequent words" > .MAX) 1> <+ 1>> .DELTA>>>)>)> ;"Write word into READBUF, with space before/after as appropriate" .NL> <- .S 1>) (ELSE <+ .S .NL>)> !\ > >> ;"Checks whether the command is an order, and if so, converts it to multi-command syntax (\,TELL THEN ). Sets: HELD-READBUF HELD-LEXBUF Returns: True if the command was converted." ) (> > ;"% instead of ,W?\, in the next line to work around a syntax highlighting bug." <=? %> >> ,PS?VERB> >> ) ( ,W?TELL> > <=? ,W?TO> >> ,PS?VERB> >> )>> ;"PRSO or PRSI are set to this when multiple objects are used." ;"PRSO or PRSI are set to this when a number is used as a noun. The actual parsed number is in the P-NUMBER global. The synonym is a word that can't be typed normally; we substitute it in the input buffer when we detect a number." ) (<=? ,P-NUMBER 1> ) (<=? ,P-NUMBER 2> ) (<=? ,P-NUMBER 3> ) (<=? ,P-NUMBER 4> ) (<=? ,P-NUMBER 5> ) (<=? ,P-NUMBER 6> ) (<=? ,P-NUMBER 7> ) (<=? ,P-NUMBER 8> ) (<=? ,P-NUMBER 9> ) (<=? ,P-NUMBER 10> ) (<=? ,P-NUMBER 42> ) (<=? ,P-NUMBER 1729> ) (<=? ,P-NUMBER 12345> ) (<=? ,P-NUMBER -32768 32767> ) (ELSE )> ) (ELSE " and " N <+ ,P-NUMBER 1>>) (ELSE " and " N <- ,P-NUMBER 1>>)>)> ) ( <=? ,P-NUMBER 5 10>> )>> ;"Tries to parse the given word as a number. If successful, the value is left in P-NUMBER, and the buffer is updated to point the word to W?\,NUMBER. Sets: P-NUMBER LEXBUF Returns: True if the number was parsed and the buffer updated; otherwise false." 1>>> >> 1>> )> > !\-> > >)> > ;"Special case for -32768" <=? .C !\8> .NEG <=? .I .MAX>> )> ;"Detect overflow" >> )> <- .C !\0>>>) (ELSE )> > > )> >)>> 1> ,W?\,NUMBER> > > >>> ;"Copies a number of bytes from one table to another. If the tables overlap, the result is undefined. Args: SRC: A pointer to the source table. DEST: A pointer to the destination table. LEN: The number of bytes to copy." > >>>) (EZIP > >>> > >>>) (ELSE >) (ELSE >)> > >)> ;"Determines whether a given word can start a noun phrase. For a word to pass this test, it must be an article, adjective, or noun. Args: W: The word to test. Returns: True if the word can start a noun phrase." >>> ;"Attempts to parse a noun phrase. If the match fails, an error message may be printed. Sets: P-OOPS-DATA Uses: P-LEN Args: WN: The 1-based word number where the noun clause starts. NP: A NOUN-PHRASE in which to return the parsed result. SILENT?: If true, don't print a message on failure, and don't set any error-related parser state (i.e. P-OOPS-DATA). Defaults to false. Returns: If parsing is successful, returns a positive number: the number of the first word that is not part of the noun phrase, which will be one greater than P-LEN if the noun phrase consumes the rest of the command. If parsing fails, returns zero, prints an error message (unless SILENT? is true) and may leave NP in an invalid state." ) "AUX" SPEC CNT W VAL MODE ADJ NOUN BUT SPEC-WN) > ) ;"fail if we found an unrecognized word" (> >>> )> ) ;"exit loop if THEN or period" ( ) ;"recognize BUT/EXCEPT" ( > >> >)> > ) ;"recognize ALL/ANY/ONE" ( )> )> ,MCM-ALL) (ELSE ,MCM-ANY)>> ) ;"match adjectives, keeping only the first" (>) (ELSE ,PS?ADJECTIVE>)> ;"if we already have a noun, this must start a new noun phrase" )> ;"word can be a noun" ;"next word is not adj/noun" >)) >>>>> ) (<==? .CNT ,P-MAX-OBJSPECS> )> ) ( ) (ELSE )>) ;"match nouns, exiting the loop if we already found one" ( ) (<==? .CNT ,P-MAX-OBJSPECS> )> ) (ELSE )>) ;"recognize AND/comma" ( >> > > )>) ;"recognize OF" ( >>> ;"This is a hack to deal with object names consisting of multiple NPs joined by OF. When we see OF before a word that could start a new noun phrase, we forget the current noun, so SMALL PIECE OF TASTY PIE parses as SMALL TASTY PIE (which in turn parses as SMALL PIE)." >) ;"skip buzzwords" ( ) ;"exit loop if we found any other word type" (ELSE )> >> ;"store final adj/noun pair" > )> ;"store phrase count and mode" ) (ELSE )> <+ .SPEC-WN 1>> ;"Attempts to match a syntax line for the current verb. Uses: P-V P-NOBJ P-P1 P-P2 Sets: PRSA P-SYNTAX Returns: True if a syntax line was matched." >> > > ;"Out of syntax lines" )> > > )>)> >> > ) (ELSE )>> > > > > )> )> )> )> > > > <=? ,P-P1 .PREP1> <=? ,P-P2 .PREP2>> ) ;"If object count >= expected count, this can't match." ( ) ;"If either preposition is nonzero yet different from expected, this can't match." ( > ) ;"If we have one object, and we expected a first preposition but didn't get it, this can't match. (If we have two objects, we already failed an earlier test.)" ( .PREP1 > ) ;"If we'd end up using FIND KLUDGEBIT for a missing noun and having to infer the preposition, don't match this line." ( <0? ,P-NOBJ> <0? ,P-P1> .PREP1 <=? ,KLUDGEBIT>> <0? ,P-P2> .PREP2 <=? ,KLUDGEBIT>>> )> ;"We have a possible match; now score how well it matches. Dock one point for each object we have to infer." > ;"Dock an extra two points for PRSO if we have to infer a preposition also." .PREP1> >)> ;"Dock an extra point for PRSI if we have to infer *no* preposition. This makes us prefer syntaxes with the direct object first (GIVE OBJECT TO OBJECT instead of GIVE OBJECT OBJECT)." >> >)> .R> ;"Attempts to match PRSO and PRSI, if necessary, after parsing a command. Prints a message if it fails. If multiple objects are used, sets PRSO or PRSI to MANY-OBJECTS. The objects are left in P-PRSOS and P-PRSIS. Args: KEEP: The number of already matched noun phrases to leave as-is (0, 1, or 2). Pass 1 when P-PRSOS was previously matched and should not be modified, e.g. when PRSO was set by GWIM and FIND-OBJECTS is being called to set PRSI from a new noun phrase after orphaning. Uses: P-NOBJ P-DOBJS P-SYNTAX Sets: PRSO PRSI P-PRSOS P-PRSIS Returns: True if all required objects were found, or false if not." )) ;"Direct object (PRSO)" > >) ( > >> ) (ELSE )>) (ELSE > > ,P-PRSOS>> >>> )>)> )>)> > >>>> )> ;"Indirect object (PRSI)" > >) ( > >> ) (ELSE )>) (ELSE > > ,P-PRSIS>> >>> )>)> )>)> >>> )> > > > > ;"TODO: use LONG-WORDS table for preposition words" > >) (ELSE >)> > ) (<=? .F ,PERSONBIT> ) (ELSE )> )> >)> > >)>)> >> ) (ELSE )>> ;"Applies the rules for the MANY syntax flag to PRSO or PRSI, printing a failure message if appropriate. Args: OBJ: PRSO or PRSI, which should equal MANY-OBJECTS if multiple objects were matched or a single object otherwise. OPTS: The corresponding search options, including the MANY flag if set. INDIRECT?: True if the failure message should say 'indirect objects' instead of 'direct objects'. Returns: True if the check passed, i.e. either a single object was matched or the MANY flag allowed multiple objects. False if multiple objects were matched but the MANY flag was not set." >> ) (ELSE )> )> )> > ;"Applies the rules for the HAVE and TAKE syntax flags to a set of parsed objects, printing a failure message if appropriate. Args: TBL: Either P-PRSOS or P-PRSIS. OPTS: The corresponding search options, including the HAVE and TAKE flags. Returns: True if the checks passed, i.e. either the objects don't have to be held by the WINNER, or they are held, possibly as the result of an implicit TAKE. False if the objects have to be held, the WINNER is not holding them, and they couldn't be taken implicitly." > ;"Attempt implicit take if WINNER isn't directly holding the objects" > >> >> > ) (ELSE )> )>)> )>> )>>)> ;"WINNER must (indirectly) hold the objects if SF-HAVE is set" > > )>>)> > ;"Like HAVE-TAKE-CHECK-TBL but for a single object. Args: OBJ: An object. OPTS: The corresponding search options, including the HAVE and TAKE flags. Returns: True if the checks passed, i.e. either the objects don't have to be held by the WINNER, or they are held, possibly as the result of an implicit TAKE. False if the objects have to be held, the WINNER is not holding them, and they couldn't be taken implicitly." > )>)>)> ;"WINNER must (indirectly) hold the object if SF-HAVE is set" )>)> > ;"The game can override these to change the precise conditions for TAKE and HAVE." > >>>>> >>> ;"Checks whether the objects listed in a table, which were part of a previous command, are still available to the player, and prints an error message if not. Args: TBL: A PRS table. Returns: True if the check passed, or false if at least one object has become unavailable and a message was printed." )) > "]" CR> >> > )>> > >> ;"Searches scope for a single object with the given flag set, and prints an inference message before returning it. The flag KLUDGEBIT is a special case that always finds ROOMS. Args: BIT: The flag to search for. If zero, all objects in scope will be considered. OPTS: The search options to use. PREP: The preposition to use in the message. Returns: The single object that matches, or false if zero or multiple objects match." ) ( )> ;"Look for exactly one matching object, excluding WINNER" >> ) (ELSE )>)>> ;"Print inference message" ;"TODO: use LONG-WORDS table for preposition word" > )> ) (ELSE )>> 2> 1>> > .PREP> .GPW>)>> > .O>> 255>> ;"Searches scope for a usable light source. Returns: An object providing light, or false if no light source was found." )> )>> > ;"Determines whether an object's contents are in scope (and provide light) when the object is in scope. Args: OBJ: The object to test. Returns: True if the object's contents are in scope, otherwise false." ;"We can see inside containers if they're open, transparent, or unopenable (= always-open)" >>>>>> ;"Attempts to find one or more objects in scope, given a noun phrase that describes them and a set of search options. The search options are used to guide the scope search toward the right objects, but are not hard requirements. Specifically, when ALL/ANY is used, we first look for a match in only the preferred scope stages, and then expand to all stages if no matches are found. When ALL/ANY is not used, we first use all scope stages, and then narrow to only the preferred stages if more than one match is found. Args: NP: The NOUN-PHRASE describing the objects. OUT: A table (in the form of P-PRSOS or P-PRSIS) in which to return the matched objects. BITS: A FIND flag and search options, as returned by ENCODE-NOUN-BITS. Uses: PRSA HERE Returns: The matched object, or MANY-OBJECTS if multiple objects were matched, or false if no objects were matched." > > > >>)> ;"ALL with no YSPECs matches all objects, or if the action is TAKE/DROP, all objects with TAKEBIT/TRYTAKEBIT, skipping generic/global objects." ) (>) (>) ( ) (ELSE > )>>) (ELSE ;"Go through all YSPECs and find matching objects for each one. Give an error if any YSPEC has no matches, but it's OK if all the matches for some YSPEC are excluded by NSPECs. Keep track of the match quality and only select the best matches." > > > > > ;"Erase previous matches if this is better" )> > ) ( ) (ELSE > )>)>> ;"Look for a pseudo-object if we didn't find a real one." >> > >) ( ) (ELSE > >)>)>)> ;"Try expanding the search if we can." ;"Avoid bouncing between <1 and >1 matches" )> ) (ELSE )> ) ( )>>)> ;"Check the number of objects" ;"This means ALL matched nothing, or BUT excluded everything. Try expanding the search if we can." >> )> ;"Avoid bouncing between <1 and >1 matches" ) (<1? .NOUT> >) ( > ) (<=? .MODE ,MCM-ANY> ;"Pick a random object" >>> ) (ELSE ;"TODO: Do this check when we're matching YSPECs, so each YSPEC can be disambiguated individually." ;"Try narrowing the search if we can." )> > )> ) (ELSE )> )>>> <=? .OBJ ,WINNER> >>>>>> ) F R) ) ,P?GENERIC>> > )>>> %<+ ,L-PRSTABLE ,L-THE ,L-OR>> > ;"Determines whether an object is excluded by a NOUN-PHRASE's NTBL. Note: NP may be evaluated twice." .O>> .PDO>> )> )> >> > )> )> >> > ;"Determines whether an object is excluded by a NOUN-PHRASE's NTBL. Note: NP may be evaluated twice." .O>> .PDO>> ;"Determines whether a local-global object is present in a given room. Args: O: The local-global object. R: The room. Returns: True if the object is present in the room's GLOBAL property. Otherwise, false." > >> ;"Determines whether an OBJSPEC refers to a given object. The OBJSPEC may have an adjective, a noun, or both. It may also have a word in its noun slot that's actually an adjective. Args: SPEC: The OBJSPEC. O: The object. Returns: A quality score. 0 means the spec didn't match at all, 1 means it matched as adjective-only, 2 means it matched as noun-only, 3 means it was a two-word match." ) (N )) > )>) (.N ) (>) (ELSE >)> )>)>) (.A )>)> > ;"Attempts to locate a word in a property table. Args: O: The object containing the property. P: The property number. V: The word to locate. Returns: True if the word is located, otherwise false." > 2> .V>>> ;"Attempts to locate a byte in a property table. Args: O: The object containing the property. P: The property number. V: The byte to locate. Must be 255 or lower. Returns: True if the byte is located, otherwise false." > .V>>> > > .V> )>> > > > .V> )>> >) (EZIP ;"V4 only has the 3-argument (word) form of INTBL?" >> > > .V> )>> >) (T ;"use built-in INTBL? in V5+" >> >>)> ) (P <+ ,LEXBUF 2>)) ) (<==? ,LEXBUF ,EDIT-LEXBUF> ) (<==? ,LEXBUF ,CONT-LEXBUF> ) (ELSE )> > )> >> > ;"Prints the raw contents of LEXBUF." )) ; CR>>> ;"Prints the raw contents of READBUF." )) ; CR>>> ;"Prints the contents of various LEXBUFS using DUMPLINE." > ;"Prints a vocabulary word and its parts of speech." > )> )> )> )> )> )> ) (ELSE )>>> ;"Copies a LEXBUF-like table." )) <* 2 .WDS>>> ;"Copies a READBUF-like table." >> ;"Measures the length of a READBUF-like table (not including the null terminator on V3-4)." > > >)>>) (EZIP > > >)>>) (ELSE >)>> ;"Fills READBUF and LEXBUF by reading a command from the player. Args: PROMPT?: Whether to print the prompt first. Sets (contents): READBUF LEXBUF" ">)> > ;"The read buffer has a slightly different format on V3." )> >> ;"Sets temporary values for one or more global variables, runs some code, then restores them. Example: )) > Expands to: > >" > 2> ATOM>>> ) (ELSE <1 .F>)>> .TEMPS>> >>> .GATOMS>> > >> .TEMPATOMS .GATOMS>> > .GATOMS .NEWVALUES>> >> .GATOMS .TEMPATOMS>> ;"And finally..." > !.RESTORES '.?RESULT>> >>> )> .F '>>) (ELSE >)> "Action framework" ;"Invokes the handlers for a given action (and objects). Uses: WINNER Sets (temporarily): PRSA PRSO PRSO-DIR PRSI" )> )> > > > >> ;"Warn about improper number use, and handle multiple objects" 1> >) ( > >) (ELSE > > >>)>) ( > > >>) (ELSE >)> .WON> ) ( > .O> )>>)> ) ( > .O> )>>)> .R> ;"Helper function to call action handlers, respecting a search order. The routine searches for handlers in a set order, calling each one it finds until one returns true to indicate that it has handled the action. The search order is as follows: ACTION property of WINNER (with M-WINNER parameter) ACTION property of WINNER's location (with M-BEG parameter) Verb preaction CONTFCN property of PRSI's location ACTION property of PRSI CONTFCN property of PRSO's location ACTION property of PRSO Verb action Uses: WINNER PRSO PRSO-DIR PRSI Args: PRTN: The verb preaction routine, or false for no preaction. RTN: The verb action routine. Returns: True if the action was handled." > > ) (> > > ) ( > ) (> > ") CONTFCN]" CR> > ) (> > ) ( > > ") CONTFCN]" CR> > ) ( > > ) (ELSE )>> ;"Moves the player to a new location, notifies the location that the player has entered, and prints an appropriate room introduction. If the old and/or new location is dark, DARKNESS-F will be given a chance to print the room introduction before DESCRIBE-ROOM and DESCRIBE-OBJECTS. Uses: WINNER Sets: HERE Args: RM: The room to move into." ,M-ENTER> ;"Call SEARCH-FOR-LIGHT down here in case M-ENTER adjusts the light." > ;"moved descriptors into GOTO so they'll be called when you call GOTO from a PER routine, etc" >) ( > )>) (,HERE-LIT) ( > )> > )> )>> "Misc Routines" ;"Searches an object to find exactly one child with a given flag set, and optionally prints a message about it. If no matching child is found, the search expands to any LOCAL-GLOBALS present. Args: C: The container or location to search. BIT: The flag to look for. WORD: A string to print in a message describing the found object, e.g. 'with' to print '[with the purple key]'. If omitted, no message will be shown. Returns: If exactly one object was found, returns the found object. If zero or multiple objects were found, returns false." > )> > >> > >)> > )) > )> >> )> > ) ;"if the routine was given the optional word, print [ the object]" (.WORD )> .W> )> ;"Prints a string with italics for emphasis (if supported). Args: STR: The string to emphasize." )> )>> ;"Returns a random element from a table, not repeating until every element has been returned once. Args: TABL: The table, which should be an LTABLE with word elements. The first element of the table (after the length word) is used as a counter and must be 2 initially. Returns: A random element from the table." > > >> > ; > .LENGTH> )>> ; > 1>> ; > > > > )> > ;"Returns a random element from a table, possibly repeating. Args: TABL: The table, which should be an LTABLE with word elements. Returns: A random element from the table." >> > > ;"The game can override this with SETG. It doesn't go through DARKNESS-F, since it has to be a constant on V3." > > >>) (T ;"Splits the screen and clears a 1-line status line." > ;"Writes the location name, score, and turn count in the status line. Uses: HERE HERE-LIT SCORE MOVES" ) (ELSE )> > > > > ;"Fills the top row with spaces." 1 -1) > >)> ;"Prints a message and ends the game, prompting the player to restart, (possibly) undo, restore, or quit. Args: TEXT: The message to print before the 'game is over' banner. Returns: True if RESURRECT? indicated that the game should resume. Otherwise, never returns." )> ">) (ELSE ">)> >> ) ( ;"only returns on failure" ) ( ) ( ;"only returns on failure" ) (T ">) (ELSE ">)>)>>>> > > > > ;"Empties the contents of one object into another, or removes them from play. The WORNBIT flag will also be cleared on the objects, unless the destination is a person. Args: VICTIM: The object that will be emptied. DEST: The object where the contents will be placed. If omitted or false, the contents will be removed from play instead." > )> )> ) (ELSE )>>> ;"Prompts the player to answer a yes/no question by pressing 'y' or 'n', repeating the prompt if they press any other key. The question should be printed before calling this routine. Returns: True if the user pressed 'y', false if they pressed 'n'." "> >) (EZIP >) (ELSE >) (ELSE )>)> ) ( ) (T ; " >)>>> >>) (ELSE >)> ;"Determines whether an object can be seen by the player. Uses: HERE WINNER PSEUDO-LOC Args: OBJ: The object to check. Returns: True if the object is visible, otherwise false." >)> > )> > > > <=? .P ,GLOBAL-OBJECTS ,GENERIC-OBJECTS>> ) (ELSE )>)> ) (> ) (ELSE >)>>> ;"Determines whether an object can be touched by the player. Uses: HERE WINNER Args: OBJ: The object to check. Returns: True if the object is accessible, otherwise false." > ,HERE>> ; )> > >> ; ) ( ; ) (ELSE >)>>> ;"Determines whether an object is contained by another object (or the player). Uses: WINNER Args: OBJ: The object to check. HLDR: The container to check. If omitted or false, defaults to WINNER. Returns: True if OBJ is contained by HLDR, otherwise false." )) > ) (<=? .HLDR> ) (ELSE >)>>> ;"Finds the room that ultimately contains a given object. Args: OBJ: The object. Returns: The room that encloses the object, or false if it isn't in a room." > ) ( )>>> ;"Checks whether the player has entered darkness, printing a message if so. This should be called when the player has done something that might cause a light source to go away." >> > )>> ;"Checks whether the player is no longer in darkness, printing a message if so. This should be called when the player has done something that might activate or reveal a light source." > >)>> "Objects" ) (ELSE #SPLICE ())> ;"This has all the flags, just in case other objects don't define them." (FLAGS !,KNOWN-FLAGS)> ;"Action handler for the player." ) ( )>>