!---------------------------------------------------------------------------
!       NewbieGrammar.h, by Emily Short ([email protected])
!
!       Being grammar statements and a couple of verbs to accomodate and
!       respond to nonstandard kinds of input.  It interprets who and what
!       questions, as well as correcting some standard errors and redirecting
!       other questions to Help.
!
!       The current contents of this file are dictated by people's r*if posts about
!       their frustrations with early attempts to play IF, and on the messages
!       log on phpZork, which reveals what an assortment of random players
!       have been known to attempt.
!
!       Note that the general trend of these grammar lines are to catch things that
!       are not what one might consider "legitimate" IF commands, or could not
!       be translated easily into another IF action.  There is a separate library,
!       called ExpertGrammar, that provides some extra verb synonyms and equivalencies
!       -- many of which were also suggested by analysis of newbie commands.
!       The two libraries are separated because it is possible that one will want
!       the ExpertGrammar without all the extra encumbrances of this library file.
!
!       Version 0.6 -- still imperfect.  If you have suggestions about
!               more things the library should handle, please contact me to
!               suggest them.
!
!       Thanks to Roger Firth for his corrections.
!
!       5/21/03
!
!
!
!       RIGHTS:
!
!       This library file may be treated as public domain.  It may be
!       included with or without credit to the original author.  It may be
!       modified at the user's discretion.  It may be freely redistributed.
!
!       CONTENTS:
!
!               Parsing for the following forms:
!
!               PLEASE... <anything> calls TooPolite, which tells the player such
!                       forms are not necessary
!
!               I AM, YOU ARE, HE/SHE/IT IS... calls NewbieGrammar, which reminds
!                       the player to use imperative verbs.
!
!               WHO AM I? calls MustXMe, which teaches the syntax for EXAMINE ME,
!                       then executes that command.
!
!               WHO ARE YOU? calls ParserHelp, which explains the parser a bit.
!
!               WHERE AM I? calls MustLook, which teaches LOOK, then executes that
!                       command.
!
!               WHERE DO I FIND MORE GAMES LIKE THIS (and a wide range of variants)
!                       calls ArchiveIntro, which explains about the IF archive.
!
!               WHERE CAN I GO NOW? (and variants) calls Exits, which is defined
!                       in this file just to tell the player to look around.  If you
!                       would like to improve the functionality, you might want to look
!                       at one of the libraries that handles an EXITS command.
!
!               WHAT DO I DO NEXT? (and a wide range of variants) calls
!                       Help.
!
!               WALK TO (and variants) calls LocalGo, which tells you
!                       that movement within a room is unnecessary.
!
!               GO BACK (and variants) calls NoReturn, which tells you
!                       to be specific about which direction you want to return.
!
!               CHECK FOR, LOOK FOR (and variants) calls SpecificSearch, which
!                       tells you to be specific about how to search for something
!
!               Moreover, there is a catch-all, omnipresent item, which
!               goes everywhere the player goes and reacts to
!
!               -- attempts to use body parts to do things.  This is to counteract
!                       newbie commands such as
!                       OPEN DOOR WITH FOOT, INFLATE RAFT WITH MOUTH, etc.
!               -- vague instructions, such as KILL SOMEONE or TAKE SOMETHING
!               -- vague locations such as HERE or ANYWHERE
!
!       POSSIBLE DIRECTIONS:
!
!       A couple of things one might also do if one really wanted to take this
!       further:
!
!       --      Use the UnknownVerb entrypoint to try to catch cases where the player is
!               using a known noun to begin a sentence.  Call NewbieGrammar in this case.
!
!       --      Use ChooseObjects to make the allbodyparts item dispreferred in any
!               disambiguation
!
!       --      Use BeforeParsing to look for certain standard adverbs, or else modify
!               the "I only understood you as far as..." library message to remind the
!               player that adverbs are not allowed.  Many of the defective commands
!               found in a study of newbie command structure included things such as
!
!               >SWIM ANYWAY
!               >JUMP ACROSS
!               >HELP PLEASE
!
!       -- Implement a fully functioning "GO BACK" verb that would return the
!               player to his previous location.  A. O. Muniz has already released
!               a library to do this with Platypus; with the standard Inform library
!               it is a bit more challenging, but not impossible.
!
!
!       INSTALLATION:
!
!       Include "NewbieGrammar" after Grammar in your gamefile.
!
!       Note that if you are actually using who, what, or where verbs in your
!       gave for legitimate purposes, you will need to change the grammar
!       lines accordingly.
!
!       Set a ChooseObjects to make sure that allbodyparts doesn't show up
!       on commands like GET ALL.
!
!       It is also suggested that you Replace HelpSub before including this
!       file.  What is here is pretty minimal.  If you wish to avoid compiling
!       the grammar lines for 'help' (perhaps because you plan to use something
!       else), define the constant NO_HELP_GRAMMAR before including this file.
!
!---------------------------------------------------------------------------

Object allbodyparts,
       with
       short_name [;
               print "that";
               rtrue;
       ],
       number 0,
       source 0,
       parse_name
       [ i j w;
               for (::)
               {
                       j = 0; w = NextWord();
                       if ((self.number == 0 or 1) &&
                               ((w == 'my' or 'head' or 'hands' or 'hand' or 'ear' or 'ears') ||
                                (w == 'fist' or 'fists' or 'finger' or 'fingers' or 'thumb' or 'thumbs') ||
                                (w == 'arm' or 'arms' or 'leg' or 'legs' or 'foot' or 'feet') ||
                                (w == 'eye' or 'eyes' or 'face' or 'nose' or 'mouth' or 'teeth') ||
                                (w == 'tooth' or 'tongue' or 'lips' or 'lip')))
                       {       self.number = 1; j = 1;
                       }
                       if ((self.number == 0 or 2) &&
                               (w == 'someone' or 'something' or 'anyone' or 'anything'))
                       {       self.number = 2; j = 1;
                       }
                       if ((self.number == 0 or 3) &&
                               (w == 'here' or 'everywhere'))
                       {       self.number = 3; j = 1;
                       }
                       if (j~=0)  i++; else return i;
               }
       ],
       found_in [;
               rtrue;
       ],
       react_before [;
               if ((noun && noun == self) || (second && second == self))
               {
                       self.message(self.number);
                       self.number = 0;
                       rtrue;
               }
               rfalse;
       ],
       message [ x;
               switch(x)
               {
               1:  "Generally speaking, there is no need to refer to your body
                       parts individually in interactive fiction.  WEAR SHOES ON FEET
                       will not necessarily be implemented, for instance; WEAR SHOES
                       is enough.  And unless you get some hint to the contrary,
                       you probably cannot OPEN DOOR WITH FOOT or
                       PUT THE SAPPHIRE RING IN MY MOUTH.";
               2:  "The game will not arbitrarily guess what you want.  Be specific --
                       use a noun for an object you can see around you.";
               3: switch(action)
                       {
                               ##Look, ##Search: <<look>>;
                               default: "You don't really need to refer to places in the game
                                       this way.";
                       }
               }
       ],
       has proper scenery;

[ IsAmAre;
       if (NextWord()=='is' or 'am' or 'are' or 'was' or 'were')
               return GPR_PREPOSITION;
       return GPR_FAIL;
];
[ DoCan;
       if (NextWord()=='do' or 'does' or 'would' or 'will' or 'shall' or
                        'can' or 'could' or 'should' or 'may' or 'must')
               return GPR_PREPOSITION;
       return GPR_FAIL;
];

[ Anybody;
       if (NextWord()=='I//' or 'me' or 'he' or 'she' or 'it' or
               'we' or 'you' or 'they' or 'person' or 'one' or
               'someone' or 'somebody' or 'anyone' or 'anybody')
               return GPR_PREPOSITION;
       return GPR_FAIL;
];

[ More;
       if (NextWord()=='more' or 'other' or 'another' or 'others')
               return GPR_PREPOSITION;
       return GPR_FAIL;
];

[ SomeDirection w flag num;
       for(::)
       {
               w = NextWord();
               if (w==0)
               {
                       if (flag)
                       {       return GPR_PREPOSITION;
                       }
                       return GPR_FAIL;
               }
               if (w == 'left' or 'right' or 'straight' or 'ahead' or 'back'
                       or 'backwards' or 'forward' or 'backward' or 'forwards' or 'on'
                       or 'onward' or 'onwards' or 'around')
               {       flag = 1; num++;
               }
       }
];

[ InternalNouns w flag num;
       for(::)
       {
               w = NextWord();
               if (w==0)
               {
                       if (flag)
                       {       return GPR_PREPOSITION;
                       }
                       return GPR_FAIL;
               }
               if (w == 'song' or 'music' or 'songs')
               {       flag = 1; num++;
               }
               if (w == 'thought' or 'idea' or 'concept')
               {       flag = 1; num++;
               }
               if (w == 'the' or 'a' or 'some' or 'any')
               {       flag = 0; num++;
               }
       }
];

[ ThePoint w flag num;
       for(::)
       {
               w = NextWord();
               if (w==0)
               {
                       if (flag)
                       {       return GPR_PREPOSITION;
                       }
                       return GPR_FAIL;
               }
               if (w == 'point' or 'point?' or 'idea' or 'idea?' or 'goal'
                       or 'goal?' or 'purpose' or 'purpose?')
               {       flag = 1; num++;
               }
               else
               {       if (w == 'the' or 'a')
                       {       flag = 0; num++;
                       }
                       else
                       {       if (flag)
                               {       return GPR_PREPOSITION;
                               }
                               return GPR_FAIL;
                       }
               }
       }
];
[ IsThisGame w flag num;
       for(::)
       {
               w = NextWord();
               if (w==0)
               {
                       if (flag)
                       {       return GPR_PREPOSITION;
                       }
                       return GPR_FAIL;
               }
               if (w == 'this' or 'these' or 'this?' or 'these?')
               {       flag = 1; num++;
               }
               if (w == 'kind' or 'kinds' or 'of' or 'sort' or 'sorts' or 'like'
                       or 'such' or 'a' or 'as' or 'all' or 'is' or 'are')
               {       flag = 0; num++;
               }
               if (w == 'game' or 'games' or 'story' or 'stories'
                       or 'game?' or 'games?' or 'story?' or 'stories?' or
                       'interactive' or 'fiction' or 'text' or 'adventure'
                       or 'adventures' or 'fiction?' or 'adventures?')
               {       flag = 1; num++;
               }
       }
];

[ ThisGame w flag num;
       for(::)
       {
               w = NextWord();
               if (w==0)
               {
                       if (flag)
                       {       return GPR_PREPOSITION;
                       }
                       return GPR_FAIL;
               }
               if (w == 'this' or 'these' or 'this?' or 'these?')
               {       flag = 1; num++;
               }
               if (w == 'kind' or 'kinds' or 'of' or 'sort' or 'sorts' or 'like'
                       or 'such' or 'a' or 'as' or 'all')
               {       flag = 0; num++;
               }
               if (w == 'game' or 'games' or 'story' or 'stories'
                       or 'game?' or 'games?' or 'story?' or 'stories?' or
                       'interactive' or 'fiction' or 'text' or 'adventure'
                       or 'adventures' or 'fiction?' or 'adventures?')
               {       flag = 1; num++;
               }
       }
];
[ GetFind;
       if (NextWord()=='get' or 'find' or 'acquire')
               return GPR_PREPOSITION;
       return GPR_FAIL;
];
[ HelpName;
       if (NextWord()=='help' or 'assistance' or 'instructions'
               or 'help?' or 'assistance?' or 'instructions?')
               return GPR_PREPOSITION;
       return GPR_FAIL;
];
[ Meant;
       if (NextWord()=='supposed' or 'meant' or 'intended')
               return GPR_PREPOSITION;
       return GPR_FAIL;
];
[ NextThing;
       if (NextWord()=='now' or 'now?' or 'next' or 'next?'
               or 'here' or 'here?')
               return GPR_PREPOSITION;
       return GPR_FAIL;
];
[ PlayUse;
       if (NextWord()=='play' or 'play?' or 'use' or 'use?' or 'operate' or 'operate?'
               or 'type' or 'type?' or 'do' or 'do?' or 'understand' or 'understand?'
               or 'learn' or 'learn?' or 'work' or 'work?')
               return GPR_PREPOSITION;
       return GPR_FAIL;
];

Verb meta 'hello' 'hi' 'howdy' 'greetings'
                               *                                                                -> HelloThere;

Verb meta 'you' 'he' 'she' 'it' 'they' 'we' 'its' 'theyre' 'were'
       'youre' 'hes' 'shes'
                               * topic                                                  -> NewbieGrammar;

Verb meta 'who' 'wh' 'whos'
                               * IsAmAre 'I'/'I?' -> MustXMe
                               * IsAmAre 'you'/'you?' -> ParserHelp
                               * IsAmAre noun                  -> Examine;
Verb meta 'where'
                               * IsAmAre 'I'/'I?'/'this'/'here'/'this?'/'here?' ->MustLook
                               * IsAmAre noun  -> RightHere
                               * IsAmAre ThePoint ThisGame                                     -> BoredHelp
                               * IsAmAre topic -> SpecificSearch
                               * DoCan Anybody 'go'/'go?'              -> Exits
                               * DoCan Anybody 'go' NextThing  -> Exits
                               * DoCan Anybody GetFind ThisGame ->
                                       ArchiveIntro
                               * DoCan Anybody GetFind More ThisGame ->
                                       ArchiveIntro
                               * DoCan Anybody 'look' 'for' ThisGame ->
                                       ArchiveIntro
                               * DoCan Anybody 'look' 'for' More ThisGame ->
                                       ArchiveIntro
                               * DoCan Anybody GetFind HelpName -> OutsideHelp
                               * DoCan Anybody GetFind HelpName 'with'/'for'/'on' ThisGame -> OutsideHelp ;
Verb meta 'wheres'
                               * 'here'                        -> MustLook
                               * IsAmAre ThePoint ThisGame                                     -> Help;
Verb meta 'what'
                               * NextThing                                             -> Help
                               * IsAmAre 'I'/'I?'                                                      -> MustXMe
                               * IsAmAre 'you'/'you?'                                                  -> ParserHelp
                               * IsAmAre 'here'/'here?'                                        -> MustLook
                               * IsAmAre 'this'/'this?'                                        -> Help
                               * IsAmAre Anybody Meant 'to' PlayUse -> Help
                               * IsAmAre Anybody Meant 'to' PlayUse
                                       NextThing -> Help
                               * IsAmAre Anybody Meant 'to' PlayUse
                                       'in'/'on'/'for'/'with' ThisGame                 -> Help
                               * IsAmAre noun                                                          -> Examine
                               * IsAmAre ThePoint                                                              -> BoredHelp
                               * IsAmAre ThePoint ThisGame                                     -> BoredHelp
                               * IsAmAre ThisGame 'about'/'about?'/'for?'/'for'                -> BoredHelp
                               * IsAmAre ThisGame 'about'/'about?'/'for?'/'for'                -> BoredHelp
                               * IsAmAre 'I' topic                                             -> Help
                               * IsThisGame                                    -> IntroHelp
                               * DoCan Anybody PlayUse -> VerbHelp
                               * DoCan Anybody PlayUse NextThing       -> VerbHelp
                               * DoCan Anybody PlayUse
                                       'in'/'on'/'for'/'with' ThisGame                 -> VerbHelp
                               * IsAmAre ThisGame                                                      -> IntroHelp;
Verb meta 'whats'
                               * 'here'                        -> MustLook
                               * noun                          -> Examine
                               * ThePoint ThisGame                                     -> BoredHelp;
Verb meta 'how'
                               * DoCan Anybody PlayUse -> Help
                               * IsAmAre Anybody Meant 'to' PlayUse -> Help
                               * IsAmAre Anybody Meant 'to' PlayUse ThisGame -> Help
                               * DoCan Anybody PlayUse ThisGame -> Help
                               * DoCan Anybody GetFind ThisGame -> ArchiveIntro
                               * DoCan Anybody GetFind More ThisGame -> ArchiveIntro
                               * DoCan Anybody GetFind HelpName -> OutsideHelp
                               * DoCan Anybody GetFind HelpName 'with'/'for'/'on' ThisGame -> OutsideHelp
                               * DoCan ThisGame 'work'/'work?' -> OutsideHelp;

#ifndef NO_HELP_GRAMMAR;   !!! added
Verb 'help'             *       -> Help
                               * topic -> Help;
#endif;   !!! added

Verb 'please' 'kindly'  * topic -> TooPolite;


Extend only 'i//'
               * topic                                                  -> NewbieGrammar;
Extend  'walk'          * SomeDirection                         -> NoReturn
                                       * 'back' noun=ADirection         -> Go
                                       * 'around'/'about'/'away'
                                                                                       -> VagueGo
                                       * 'on'/'over'/'across' noun             -> Enter
                                       * 'to'/'towards'/'around'/'past'/'under' noun
                                                                                                               -> LocalGo
                                       * 'over'/'up'/'down' 'to'/'towards' noun
                                                                                                               -> LocalGo;
Extend 'turn'           * SomeDirection                          -> NoReturn;
Extend  'climb'         * SomeDirection                                  -> NoReturn
                                       * 'back' noun=ADirection         -> Go;
Verb    'keep'          * 'going'/'walking'/'heading'/'running'
                                                                        noun=ADirection -> NoReturn
                                       * 'going'/'walking'/'heading'/'running'
                                                                        noun=ADirection -> MustGo;
Verb    'continue'      *  noun=ADirection -> MustGo
                                       * 'going'/'walking'/'heading'/'running'
                                                                       noun=ADirection -> MustGo;
Verb    'return' 'back' *                                                        -> NoReturn
                                       * 'to' topic                             -> NoReturn;

Extend  'check'         * 'for' noun                             -> Examine
                                       * 'for' topic                            -> SpecificSearch;
Extend  'look'          * 'for' noun                             -> Examine
                                       * 'for' topic                            -> SpecificSearch;
Extend  'search'        * 'for' noun                             -> RightHere
                                       * 'for' topic                            -> SpecificSearch;
Verb    'find'          * noun                                           -> RightHere
                                       * topic                                          -> SpecificSearch;
Extend  'wear'          * noun 'on' noun                         -> Wear;
Extend  'sing'          * InternalNouns                          -> InternalAccusative;
Extend  'think'         * InternalNouns                          -> InternalAccusative;

[ TooPoliteSub;
       "The parser does not understand polite formulations such as
       PLEASE LOOK AROUND NOW or KINDLY OPEN THE BOX.  Start your commands
       with an imperative verb and they will work better.";
];

[ InternalAccusativeSub;
       "In constructions like SING A SONG, the ~A SONG~ part is what is known
       as an internal accusative -- a direct object that is not actually necessary.
       In short: SING will do just as well.  The game has difficulty with
       parsing abstracts like ~a song~.";
];

[ MustGoSub;
       print "[Generally, it is necessary to phrase commands like this as a simple
               direction: GO NORTH, NORTH, etc., rather than KEEP GOING NORTH, HEAD BACK NORTH,
               etc.]^^";
       <<Go noun>>;
];

[ RightHereSub;
       print "", (The) noun, " is ";
       if (IndirectlyContains(player, noun)) "already in your possession!";
       "in plain sight!";
];

[ SpecificSearchSub;
       "If you want to look for something, try LOOK (to see
       the room as a whole); LOOK IN containers; LOOK UNDER large items;
       and SEARCH such items as piles and heaps.^^If you still can't
       find whatever it is, you're probably out of luck...";
];

[ NoReturnSub;
       "The game does not keep track of your path through the rooms, nor
       your orientation within them.  Instead, you should rely on absolute
       compass directions.  If you
       wish to visit a new location or return to a previous one, you will have to
       type the directions to take you there -- NORTH, UP, etc.";
];

[ ParserHelpSub;
       "The voice with which you are communicating is the narrator of the
       game.^^[If you are having trouble with the game, try HELP.]";
];
[ NewbieGrammarSub;
       "If the game is not understanding you, try issuing your commands in the imperative:
       e.g., >THROW THE KNIFE, but not >I WOULD REALLY LIKE TO THROW THE KNIFE.  Chatty sentences
       such as >YOU ARE A VERY STUPID GAME will only prove themselves true.^^If you really
       feel that the game is looking for a word that is not a verb (as the solution
       to a riddle, eg.) try some variations, such as SAY FLOOBLE.";
];
[ MustLookSub;
       print "[You can do this in the future by typing LOOK, which is quicker and
               more standard.]^";
       <<Look>>;
];
[ MustXMeSub;
       print "[You're the main character of the game.  Of course, the game author may
               have given you a description.  You can see this description in the future
               by typing EXAMINE ME, which is quicker and more standard.]^^";
       <<Examine player>>;
];

Verb 'intro' * -> TotalIntro;
[ TotalIntroSub;
#ifdef BasicBrief;
       BasicBrief(); new_line;
#endif;
#ifdef StartingInstructions;
       StartingInstructions(); rtrue;
#endif;
       "This is a work of interactive fiction.  You should explore and try to do things.";
];
[ BoredHelpSub;
#ifdef StartingInstructions;
       StartingInstructions(); rtrue;
#ifnot;
       <<Help>>;
#endif;
];

[ OutsideHelpSub;
#ifdef OnlineHelp;
       OnlineHelp(); rtrue;
#ifnot;
       <<Help>>;
#endif;
];

Verb 'verbs' *  -> VerbHelp;
[ VerbHelpSub;
#ifdef StandardVerbs;
       StandardVerbs(); rtrue;
#ifnot;
       <<Help>>;
#endif;
];

Verb 'hint' 'hints' *   -> HintHelp;
[ HintHelpSub;
#ifdef StuckInstructions;
       StuckInstructions(); rtrue;
#ifnot;
       <<Help>>;
#endif;
];

[ ArchiveIntroSub;
#ifdef MoreGames;
       MoreGames(); rtrue;
#ifndef MoreGames;
       "You can find more games like this at the Interactive Fiction archive,
       http://www.ifarchive.org, and a guide to the archive at
       http://www.wurb.com/if/.";
#endif;
];

[ HelloThereSub;
       "Hi!^^If you are new to Interactive Fiction, you may want to type HELP.";
];

[ ExitsSub;
       "If you LOOK, you may notice some compass directions you can use to
       move to new rooms.";
];

[ LocalGoSub;
       if (noun has door) <<enter noun>>;
       "There's no need to walk towards items that are already
       in your vicinity.";
];

Verb 'demo' * -> Demo;
[ DemoSub;
#ifdef CheeseSample;
       CheeseSample();
#ifnot;
       "No demo is available.";
#endif;
];

[ HelpSub;
       "If you would like a list of verbs you could try, type VERBS.^^If the problem is more
       that you don't know how to get going with the game, type INTRO.^^If you'd like a sample
       of a game being played, type DEMO.^^Finally, if you know what you want to achieve
       but can't figure out how to achieve it, type HINT.
       ^^If you are having further difficulty with IF, try looking at some of the online help sites
       such as http://www.brasslantern.org.";
];

[ IntroHelpSub;
#ifdef BasicBrief;
       BasicBrief(); rtrue;
#ifnot;
       "This is a work of interactive fiction, in which you play the role of the
       main character.  You interact by typing text at the prompt.";
#endif;
];