#charset "us-ascii"
#include "adv3.h"
#include "en_us.h"

//---------------------------------------------------------------
// MSG_CUSTOM.T
// by Greg Boettcher
// Version 2.1
// Released 18 November 2007
// Version 2.1 (very slight bug fix) released 23 Jun 2010
//
// Copyright 2006-2007 Greg Boettcher.
//
// This file is freeware. You may use it for any purpose without
// permission, but please credit me appropriately.
//
// My email address:
// <gregXatXgregboettcherXdotXcom>
//---------------------------------------------------------------

ModuleID
 name = 'Msg_custom.t'
 byLine = 'by Greg Boettcher'
 htmlByLine = 'by Greg Boettcher'
 version = '2'
 //showCredit { "<<name>> <<htmlByLine>>"; }
;

/*

--------------------
ABOUT THIS EXTENSION
--------------------

With this file, you can change the standard TADS 3 messages in
any or all of the following ways:

1. You can deal with "smart quotes" as follows:
  - sometimes use smart quotes (TADS 3.0.9 default)
  - always use smart quotes (TADS 3.0.10+ default)
  - never use smart quotes

2. You can deal with contractions as follows:
  - sometimes use contractions (TADS 3 default)
  - usually use contractions
  - always use contractions
  - or you can use contractions even less often than the
    standard library does. Not recommended unless your
    game's narrator and/or its NPCs are supposed to speak
    like Lieutenant Commander Data of Star Trek.

3. You can, if you want, make the standard messages less formal
  and more casual. If you do, then "appears" is replaced with
  "seems"; "you see no" is replaced with "you don't see any"; etc.

4. You can make it so that when your TADS 3 project refers to
  itself as "the story," this phrase is changed to any of the
  following:
  - "the story"
  - "this story"
  - "the game"
  - "this game"

5. You can adjust the phrasing in cases where TADS 3 tells you
  something "you must" do. You can do this in any of five ways,
  exemplified as follows:
  - "You must stand up before you can do that." (TADS 3 default)
  - "You'll have to stand up before you can do that."
  - "You'd have to stand up before you could do that."
  - "You'll need to stand up before you can do that."
  - "You'd need to stand up before you could do that."

These changes should work correctly even if you are doing
something unusual, such as putting your game in the past tense
or if your game is in the first person or third person.

Msg_custom.t should produce the exact same output as msg_neu.t
until you adjust its settings to suit your taste. Also, just to
be clear, all of its settings are independent of each other.
So you can certainly use it even if only one of its features
interests you.

Although I tested this extension quite thoroughly and it seems
relatively bug-free, it is very complicated, so I'm sure there
could be some bugs lurking in it. As such, I will need people's
help in reporting any and all bugs they may may find. While I
can't make any promises for the future, I at least *intend* to
maintain this file as needed.

-------------------------
HOW TO USE THIS EXTENSION
-------------------------

Put msg_custom.t into your project after the standard library
files, but before your own files. (And you do need to include
the standard library files. Msg_custom.t is not meant to
replace msg_neu.t or en_us.t.)

Then put something into your project that looks like this:

modify libGlobal
 thisStoryNotTheStory = sometimes
 gameNotStory = nil
 youMustPref = youMust
 useContractions = sometimes
 preferCasual = true
 useSmartQuotes = always
;

The above example sets each of the variables to their
default settings, and as such accomplishes nothing. But
you can adjust the values of each of those variables, as
described below in the "message variables" comments.
The TADS 3 library should respond accordingly.

For more details on how to do this for each of the individual
variables, see directly below in my "message variables"
comments.

Have fun! And by all means email me with any bugs you may
find.

Greg

*/

///////////////////////////////////////////////////////////
// MESSAGE VARIABLES
///////////////////////////////////////////////////////////

modify libGlobal
 // thisStoryNotTheStory:
 //   = sometimes  "*The* story has never referred   (T3 default)
 //                  to any such footnote."
 //                "*This* story has no ABOUT
 //                  information."
 //   = always     "*This* story has never referred  (my preference)
 //                  to any such footnote."
 //                "*This* story has no ABOUT
 //                  information."
 //   = never      "*The* story has never referred
 //                  to any such footnote."
 //                "*The* story has no ABOUT
 //                  information."
 thisStoryNotTheStory = sometimes
 // gameNotStory:
 //   = nil   "This story has no ABOUT information."  (T3 default)
 //   = true  "This game has no ABOUT information."   (my preference)
 gameNotStory = nil
 // youMustPref: (when the game is in present tense)
 //   = youMust      "You must stand up before        (T3 default)
 //                    you can do that."
 //   = youllHaveTo  "You'll have to stand up before  (my preference)
 //                    you can do that."
 //   = youdHaveTo   "You'd have to stand up before
 //                    you could do that."
 //   = youllNeedTo  "You'll need to stand up before
 //                    you can do that."
 //   = youdNeedTo   "You'd need to stand up before
 //                    you could do that."
 // youMustPref: (when the game is in past tense)
 //   = youMust        "You had to stand up before    (T3 default)
 //                      you could do that."
 //   = youllHaveTo    "You would have had to stand   (my preference)
 //     OR youdHaveTo    up before you can do that."
 //   = youllNeedTo    "You needed to stand up before
 //                      you could do that.
 //   = youdNeedTo     "You would have needed to stand
 //                      up before you could do that."
 youMustPref = youMust
 // useContractions:
 //   = always    (always use contractions, even "YOU'VE DIED," etc.)
 //   = usually   (my preference)
 //   = sometimes (T3 default)
 //   = seldom    (narrator talks like Lt. Cmdr. Data)
 //   = never     (narrator and all NPCs talk like Lt. Cmdr. Data)
 useContractions = sometimes
 // preferCasual:
 //   = nil  "You *see no* box here."              (T3 default)
 //          "Bob does not *appear* interested."
 //          [give a "must" example?]
 //   = true "You *don't see any* box here."      (my preference)
 //          "Bob does not *seem* interested."
 //          [give a "must" example?]
 preferCasual = nil
 // useSmartQuotes:
 //   = always     Replace:                       (my preference,
 //                  (1) all double quotes,         and TADS 3.0.10+
 //                  (2) all single quotes, and     default)
 //                  (3) all apostrophes
 //                with
 //                  (1) '<q>', '</q>',
 //                  (2) '&rsquo;', '&lsquo;', and
 //                  (3) '&rsquo;'.
 //   = sometimes  (Default TADS 3.0.9            (TADS 3.0.9
 //                  usage, using smart             default)
 //                  quotes only sometimes.)
 //   = never      (Never use any smart
 //                  quotes.)
 useSmartQuotes = always
;

///////////////////////////////////////////////////////////
// ENUMS
///////////////////////////////////////////////////////////

#ifndef never
enum never;
#endif

#ifndef seldom
enum seldom;
#endif

#ifndef sometimes
enum sometimes;
#endif

#ifndef usually
enum usually;
#endif

#ifndef always
enum always;
#endif

#ifndef youMust
enum youMust;
#endif

#ifndef youllHaveTo
enum youllHaveTo;
#endif

#ifndef youdHaveTo
enum youdHaveTo;
#endif

#ifndef youllNeedTo
enum youllNeedTo;
#endif

#ifndef youdNeedTo
enum youdNeedTo;
#endif

///////////////////////////////////////////////////////////
// MISC. MODIFICATIONS FOR TADS 3.0.8
///////////////////////////////////////////////////////////

// This extension was originally designed to run on games
// compiled with TADS 3.0.9+. With some modifications, however,
// we can make sure it works with 3.0.8 as well.

modify GameMainDef
   usePastTense = nil
;

// In TADS 3.0.9, tSel() is defined as a macro rather than
// a function. I don't know why, but I can't help thinking
// that a function would work too, and would also provide
// a better across-the-board solution for all the files
// in a project.
#ifndef tSel
//#define tSel(presVal, pastVal) \
//    (gameMain.usePastTense ? (pastVal) : (presVal))
tSel(presVal, pastVal) {
   return (gameMain.usePastTense ? pastVal : presVal);
}
#endif

modify langMessageBuilder
   pastEnding_ = nil
;

modify Thing
   verbEndingSD = (tSel(verbEndingS, 'd'))
   verbEndingSEd = (tSel(verbEndingS, 'ed'))
   verbEndingSMessageBuilder_ =
       (tSel(verbEndingS, langMessageBuilder.pastEnding_))
   verbToDo = (tSel('do' + verbEndingEs, 'did'))
   nameDoes = (theName + ' ' + verbToDo)
   verbToGo = (tSel('go' + verbEndingEs, 'went'))
   verbToCome = (tSel('come' + verbEndingS, 'came'))
   verbToLeave = (tSel('leave' + verbEndingS, 'left'))
   verbToSee = (tSel('see' + verbEndingS, 'saw'))
   nameSees = (theName + ' ' + verbToSee)
   verbToSay = (tSel('say' + verbEndingS, 'said'))
   nameSays = (theName + ' ' + verbToSay)
   verbMust = (tSel('must', 'had to'))
   verbCan = (tSel('can', 'could'))
   verbCannot = (tSel('cannot', 'could not'))
   verbCant = (tSel('can&rsquo;t', 'couldn&rsquo;t'))
   verbWill = (tSel('will', 'would'))
   verbWont = (tSel('won&rsquo;t', 'wouldn&rsquo;t'))
;

modify NameAsOther
   verbEndingSD = (targetObj.verbEndingSD)
   verbEndingSEd = (targetObj.verbEndingSEd)
   verbToDo = (targetObj.verbToDo)
   nameDoes = (targetObj.nameDoes)
   verbToGo = (targetObj.verbToGo)
   verbToCome = (targetObj.verbToCome)
   verbToLeave = (targetObj.verbToLeave)
   verbToSee = (targetObj.verbToSee)
   nameSees = (targetObj.nameSees)
   verbToSay = (targetObj.verbToSay)
   nameSays = (targetObj.nameSays)
   verbMust = (targetObj.verbMust)
   verbCan = (targetObj.verbCan)
   verbCannot = (targetObj.verbCannot)
   verbCant = (targetObj.verbCant)
   verbWill = (targetObj.verbWill)
   verbWont = (targetObj.verbWont)
;

///////////////////////////////////////////////////////////
// CUSTOM MESSAGE OBJECT
///////////////////////////////////////////////////////////

custMsgObj: object
 // Used only when "you" means the player; not when "you" means
 // the player character.
 youllStr() {
   if (libGlobal.useContractions == seldom ||
       libGlobal.useContractions == never)
     return 'you will';
   else
     return 'you' + custMsgObj.rsquoPlainStr + 'll';
 }
 youWillStr() {
   if (libGlobal.useContractions == usually ||
       libGlobal.useContractions == always)
     return 'you' + custMsgObj.rsquoPlainStr + 'll';
   else
     return 'you will';
 }
 youveStr() {
   if (libGlobal.useContractions == seldom ||
       libGlobal.useContractions == never)
     return 'you have';
   else
     return 'you' + custMsgObj.rsquoPlainStr + 've';
 }
 youreStr() {
   if (libGlobal.useContractions == seldom ||
       libGlobal.useContractions == never)
     return 'you are';
   else
     return 'you' + custMsgObj.rsquoPlainStr + 're';
 }
 youdStr() {
   if (libGlobal.useContractions == seldom ||
       libGlobal.useContractions == never)
     return 'you would';
   else
     return 'you' + custMsgObj.rsquoPlainStr + 'd';
 }
 cantStr() {
   if (libGlobal.useContractions == seldom ||
       libGlobal.useContractions == never)
     return 'cannot';
   else
     return 'can' + custMsgObj.rsquoPlainStr + 't';
 }
 storyStr() {
   //return 'storyStr';
   if (libGlobal.gameNotStory) return 'game';
   else return 'story';
 }
 theStoryStrFunc(caps, theNotThis) {
   local str;
   // str = 'story' or 'game'
   str = storyStr();
   switch (libGlobal.thisStoryNotTheStory) {
     // Add 'he ' or 'his ' depending on whether it's
     // 'the' or 'this'
     case never:
       str = 'he ' + str;
       break;
     case always:
       str = 'his ' + str;
       break;
     default:
       if (theNotThis) str = 'he ' + str;
       else str = 'his ' + str;
       break;
   }
   if (caps) str = 'T' + str;
   else str = 't' + str;
   return str;
 }
 theStoryStr()  { return theStoryStrFunc(nil , true); }
 thisStoryStr() { return theStoryStrFunc(nil , nil ); }
 TheStoryStr()  { return theStoryStrFunc(true, true); }
 ThisStoryStr() { return theStoryStrFunc(true, nil ); }
 // Use this when saying something that will never be in the
 // past tense, e.g. "You, the player, cannot do something."
 // Do not use for PCs or NPCs, where the verb "cannot"
 // would change depending on whether the game is in the
 // past tense.
 cannotStr() {
   if (libGlobal.useContractions != usually &&
       libGlobal.useContractions != always) return 'cannot';
   else if (libGlobal.useSmartQuotes == always) return 'can&rsquo;t';
   else return 'can\'t';
 }
 // For use only when a given clause is always in the
 // past tense.
 wereNotStr() {
   if (libGlobal.useContractions != usually &&
       libGlobal.useContractions != always) return 'were not';
   else if (libGlobal.useSmartQuotes == always) return 'weren&rsquo;t';
   else return 'weren\'t';
 }
 appearStr() {
   if (libGlobal.preferCasual) return 'seem';
   else return 'appear';
 }
 lsquoStr() {
   if (libGlobal.useSmartQuotes == never)
     return '\'';
   else
     return '&lsquo;';
 }
 rsquoStr() {
   if (libGlobal.useSmartQuotes == never)
     return '\'';
   else
     return '&rsquo;';
 }
 lsquoPlainStr() {
   if (libGlobal.useSmartQuotes == always)
     return '&lsquo;';
   else
     return '\'';
 }
 rsquoPlainStr() {
   if (libGlobal.useSmartQuotes == always)
     return '&rsquo;';
   else
     return '\'';
 }

 ldquoStr() {
   if (libGlobal.useSmartQuotes == never)
     return '\"'; //return '\"';
   else
     return '&ldquo;'; //return '&ldquo;';
 }
 rdquoStr() {
   if (libGlobal.useSmartQuotes == never)
     return '\"'; //return '\"';
   else
     return '&rdquo;'; //return '&rdquo;';
 }
 ldquoPlainStr() {
   if (libGlobal.useSmartQuotes == always)
     return '&ldquo;'; //return '&ldquo;';
   else
     return '\"'; //return '\"';
 }
 rdquoPlainStr() {
   if (libGlobal.useSmartQuotes == always)
     return '&rdquo;'; //return '&rdquo;';
   else
     return '\"'; //return '\"';
 }

 sOrWasStr() {
   if (gameMain.usePastTense)
     return ' was';
   else if (libGlobal.useContractions == seldom ||
            libGlobal.useContractions == never)
     return ' is';
   else
     return rsquoPlainStr + 's';
 }
 _not() {
   if (libGlobal.useContractions == usually
     || libGlobal.useContractions == always)
     return 'n' + rsquoPlainStr + 't';
   else
     return ' not';
 }
 ntAbbr() {
   if (libGlobal.useContractions == seldom ||
       libGlobal.useContractions == never)
     return ' not';
   else
     return 'n' + rsquoPlainStr + 't';
 }
;

///////////////////////////////////////////////////////////
// LANGMESSAGEBUILDER MODIFICATIONS
///////////////////////////////////////////////////////////

// I tried to append to langMessageBuilder.paramList_, but
// I found it more difficult than I expected. So I had to
// replace the list, rather than modify it.

modify langMessageBuilder
   // I was wanted to append to this list, but I failed to
   // find a way to make this happen before the list is
   // processed. Therefore, I had to replace the entire list.
   paramList_ =
   [
       // parameters that imply the actor as the target object
       ['you/he', &theName, 'actor', nil, true],
       ['you/she', &theName, 'actor', nil, true],
       ['you\'re/he\'s', &itIsContraction, 'actor', nil, true],
       ['you\'re/she\'s', &itIsContraction, 'actor', nil, true],
       ['you\'re', &itIsContraction, 'actor', nil, true],
       ['you/him', &theNameObj, 'actor', &itReflexive, nil],
       ['you/her', &theNameObj, 'actor', &itReflexive, nil],
       ['your/her', &theNamePossAdj, 'actor', nil, nil],
       ['your/his', &theNamePossAdj, 'actor', nil, nil],
       ['your', &theNamePossAdj, 'actor', nil, nil],
       ['yours/hers', &theNamePossNoun, 'actor', nil, nil],
       ['yours/his', &theNamePossNoun, 'actor', nil, nil],
       ['yours', &theNamePossNoun, 'actor', nil, nil],
       ['yourself/himself', &itReflexive, 'actor', nil, nil],
       ['yourself/herself', &itReflexive, 'actor', nil, nil],
       ['yourself', &itReflexive, 'actor', nil, nil],

       // parameters that don't imply any target object
       ['the/he', &theName, nil, nil, true],
       ['the/she', &theName, nil, nil, true],
       ['the/him', &theNameObj, nil, &itReflexive, nil],
       ['the/her', &theNameObj, nil, &itReflexive, nil],
       ['the\'s/her', &theNamePossAdj, nil, &itPossAdj, nil],
       ['the\'s/hers', &theNamePossNoun, nil, &itPossNoun, nil],

       // Verb 's' endings.  In most cases, you should use 's/d', 's/ed',
       // or 's/?ed' rather than 's', except in places where you know you
       // will never need the past tense form, because 's' doesn't handle
       // the past tense.  Don't use 's/?ed' with a literal question
       // mark; put a consonant in place of the question mark instead.
       ['s', &verbEndingS, nil, nil, true],
       ['s/d', &verbEndingSD, nil, nil, true],
       ['s/ed', &verbEndingSEd, nil, nil, true],
       ['s/?ed', &verbEndingSMessageBuilder_, nil, nil, true],

       ['es', &verbEndingEs, nil, nil, true],
       ['es/ed', &verbEndingEs, nil, nil, true],
       ['ies', &verbEndingIes, nil, nil, true],
       ['ies/ied', &verbEndingIes, nil, nil, true],
       ['is', &verbToBe, nil, nil, true],
       ['are', &verbToBe, nil, nil, true],
       ['was', &verbWas, nil, nil, true],
       ['were', &verbWas, nil, nil, true],
       ['has', &verbToHave, nil, nil, true],
       ['have', &verbToHave, nil, nil, true],
       ['does', &verbToDo, nil, nil, true],
       ['do', &verbToDo, nil, nil, true],
       ['goes', &verbToGo, nil, nil, true],
       ['go', &verbToGo, nil, nil, true],
       ['comes', &verbToCome, nil, nil, true],
       ['come', &verbToCome, nil, nil, true],
       ['leaves', &verbToLeave, nil, nil, true],
       ['leave', &verbToLeave, nil, nil, true],
       ['sees', &verbToSee, nil, nil, true],
       ['see', &verbToSee, nil, nil, true],
       ['says', &verbToSay, nil, nil, true],
       ['say', &verbToSay, nil, nil, true],
       ['must', &verbMust, nil, nil, true],
       ['can', &verbCan, nil, nil, true],
       ['cannot', &verbCannot, nil, nil, true],
       ['can\'t', &verbCant, nil, nil, true],
       ['will', &verbWill, nil, nil, true],
       ['won\'t', &verbWont, nil, nil, true],
       ['a/he', &aName, nil, nil, true],
       ['an/he', &aName, nil, nil, true],
       ['a/she', &aName, nil, nil, true],
       ['an/she', &aName, nil, nil, true],
       ['a/him', &aNameObj, nil, &itReflexive, nil],
       ['an/him', &aNameObj, nil, &itReflexive, nil],
       ['a/her', &aNameObj, nil, &itReflexive, nil],
       ['an/her', &aNameObj, nil, &itReflexive, nil],
       ['it/he', &itNom, nil, nil, true],
       ['it/she', &itNom, nil, nil, true],
       ['it/him', &itObj, nil, &itReflexive, nil],
       ['it/her', &itObj, nil, &itReflexive, nil],

       // note that we don't have its/his, because that leaves
       // ambiguous whether we want an adjective or noun form - so we
       // only use the feminine pronouns with these, to make the
       // meaning unambiguous
       ['its/her', &itPossAdj, nil, nil, nil],
       ['its/hers', &itPossNoun, nil, nil, nil],

       ['it\'s/he\'s', &itIsContraction, nil, nil, true],
       ['it\'s/she\'s', &itIsContraction, nil, nil, true],
       ['it\'s', &itIsContraction, nil, nil, true],
       ['that/he', &thatNom, nil, nil, true],
       ['that/she', &thatNom, nil, nil, true],
       ['that/him', &thatObj, nil, &itReflexive, nil],
       ['that/her', &thatObj, nil, &itReflexive, nil],
       ['that\'s', &thatIsContraction, nil, nil, true],
       ['itself', &itReflexive, nil, nil, nil],
       ['itself/himself', &itReflexive, nil, nil, nil],
       ['itself/herself', &itReflexive, nil, nil, nil],

       // default preposition for standing in/on something
       ['on', &actorInName, nil, nil, nil],
       ['in', &actorInName, nil, nil, nil],
       ['outof', &actorOutOfName, nil, nil, nil],
       ['offof', &actorOutOfName, nil, nil, nil],
       ['onto', &actorIntoName, nil, nil, nil],
       ['into', &actorIntoName, nil, nil, nil],

       // The special invisible subject marker - this can be used to
       // mark the subject in sentences that vary from the
       // subject-verb-object structure that most English sentences
       // take.  The usual SVO structure allows the message builder to
       // see the subject first in most sentences naturally, but in
       // unusual sentence forms it is sometimes useful to be able to
       // mark the subject explicitly.  This doesn't actually result in
       // any output; it's purely for marking the subject for our
       // internal book-keeping.
       //
       // (The main reason the message builder wants to know the subject
       // in the first place is so that it can use a reflexive pronoun
       // if the same object ends up being used as a direct or indirect
       // object: "you can't open yourself" rather than "you can't open
       // you.")
       ['subj', &dummyName, nil, nil, true]

       //MSG_CUSTOM ADDITIONS
       ,['n\'t', &ntAbbr, nil, nil, nil]
       ,['_not', &_not, nil, nil, nil]
       ,['that_isn\'t', &thatIsnt, nil, nil, true]
       ,['that_is_not', &thatIsNot, nil, nil, true]
       ,['you_would_have_to', &nameWouldHaveTo, 'actor', nil, true]
       //,['you_will_have_to', &nameWillHaveTo, 'actor', nil, true]
       ,['you_could', &itCould, 'actor', nil, true]
       ,['you_see_no', &nameSeesNo, 'actor', nil, true]
       ,['you_are', &nameIs, 'actor', nil, true]
   ]
;

// The following just didn't work, so I resorted to replacing
// the entire set of values for langMessageBuilder.paramList_
//custMsgPreinit: PreinitObject
//  execute() {
//    langMessageBuilder.paramList_.append(
//      ['n\'t', &ntAbbr, nil, nil, true],
//      ['_not', &_not, nil, nil, true]
//    );
//  }
//  execAfterMe = [adv3LibPreinit]
//;

///////////////////////////////////////////////////////////
// THING MODIFICATIONS
///////////////////////////////////////////////////////////

modify Thing
 thatIsContraction {
   if (gameMain.usePastTense)
     return thatNom + ' ' + verbToBe;
   // From now on, we assume present tense.
   else if (libGlobal.useContractions == seldom ||
            libGlobal.useContractions == never) // Lt. Cmdr. Data scenario
     return thatNom + ' ' + verbToBe;
   else if (isPlural)
     return thatNom + ' are';
   else
     return thatNom + custMsgObj.rsquoPlainStr + 's';
 }
 itIsContraction {
   if (gameMain.usePastTense)
     return itNom + ' ' + verbToBe; // "it was"/"they were"
   // From now on, we assume present tense.
   else if (libGlobal.useContractions == seldom ||
            libGlobal.useContractions == never) // Lt. Cmdr. Data scenario
     return itNom + ' ' + verbToBe; // "it is"/"they are"
   else if (isPlural)
     return itNom + custMsgObj.rsquoPlainStr + 're'; // "they're"
   else
     return itNom + custMsgObj.rsquoPlainStr + 's'; // "it's"
 }
 theNamePossAdj {
   return theName +
     (isPlural && theName.endsWith('s')
       ? custMsgObj.rsquoPlainStr
       : custMsgObj.rsquoPlainStr + 's');
 }
 pluralNameFrom(str) {
   local len;
   local lastChar;
   local lastPair;
   if (isPlural)
     return str;


   //// The following will become part of TADS 3 in the version
   //// that follows 3.0.9.
   //if (rexMatch(patOfPhrase, str) != nil) {
   //  local ofSuffix;
   //  str = rexGroup(1)[3];
   //  ofSuffix = rexGroup(2)[3];
   //  return pluralNameFrom(str) + ofSuffix;
   //}


   len = str.length();
   if (len == 0)
     return '';
   if (len == 1) {
     if (rexMatch(patSingleApostropheS, str) != nil)
       return str + custMsgObj.rsquoPlainStr + 's';
     else
       return str + 's';
   }
   lastChar = str.substr(len, 1);
   lastPair = (len == 1 ? lastChar : str.substr(len - 1, 2));
   if (rexMatch(patUpperOrDigit, lastChar) != nil)
     return str + 's';
   if (lastChar == '.')
     return str + custMsgObj.rsquoPlainStr + 's';
   if (rexMatch(patVowelY, lastPair) != nil)
     return str.substr(1, len - 1) + 'ies';
   if ('sxzh'.find(lastChar) != nil)
     return str + 'es';
   return str + 's';
 }
 nameIsnt {
   if (libGlobal.useContractions == seldom ||
       libGlobal.useContractions == never) // Lt. Cmdr. Data scenario
     return nameIs + ' not';
   else
     return nameIs + 'n' + custMsgObj.rsquoPlainStr + 't';
 }
 nameIsNot {
   if (libGlobal.useContractions == usually ||
       libGlobal.useContractions == always)
     return theName + ' ' + verbToBe + custMsgObj.ntAbbr;
   else
     return theName + ' ' + verbToBe + ' not';
 }
 verbCant() {
   if (gameMain.usePastTense) {
     if (libGlobal.useContractions != never &&
         libGlobal.useContractions != seldom)
       return 'couldn' + custMsgObj.rsquoPlainStr + 't';
     else
       return 'could not';
   }
   else { // use present tense
     if (libGlobal.useContractions != never &&
         libGlobal.useContractions != seldom)
       return 'can' + custMsgObj.rsquoPlainStr + 't';
     else
       return 'cannot';
   }
 }
 verbWont() {
   if(gameMain.usePastTense) {
     if (libGlobal.useContractions != never &&
         libGlobal.useContractions != seldom)
       return 'wouldn' + custMsgObj.rsquoPlainStr + 't';
     else
       return 'would not';
   }
   else { // use present tense
     if (libGlobal.useContractions != never &&
         libGlobal.useContractions != seldom)
       return 'won' + custMsgObj.rsquoPlainStr + 't';
     else
       return 'will not';
   }
 }
 verbCannot() {
   if (gameMain.usePastTense) {
     if (libGlobal.useContractions == usually ||
         libGlobal.useContractions == always)
       return 'couldn' + custMsgObj.rsquoPlainStr + 't';
     else
       return 'could not';
   }
   else { // use present tense
     if (libGlobal.useContractions == usually ||
         libGlobal.useContractions == always)
       return 'can' + custMsgObj.rsquoPlainStr + 't';
     else
       return 'cannot';
   }
 }
 // Presumably in all relevant cases
 // Thing.nameWouldHaveTo is overridden by
 // Actor.nameWouldHaveTo. But just in case...
 nameWouldHaveTo {
   if (libGlobal.youMustPref == youMust)
     return theName + ' ' + verbMust;
   else if (gameMain.usePastTense) {
     if (libGlobal.youMustPref == youllNeedTo)
       return theName + ' needed to';
     if (libGlobal.youMustPref == youdNeedTo)
       return theName + ' would have needed to';
     else
       return theName + ' would have had to';
   }
   else { // present tense
     switch (libGlobal.youMustPref) {
       case youllHaveTo: return theName + ' will have to';
       case youdHaveTo:  return theName + ' would have to';
       case youllNeedTo: return theName + ' will need to';
       case youdNeedTo:  return theName + ' would need to';
       default:          return theName + ' ' + verbMust; // should never happen; covered above
     }
   }
 }
 // Use this when it makes no sense to use the subjective,
 // so you want to, e.g., substitute "would" with "will".
 nameWillHaveTo {
   if (gameMain.usePastTense) {
     switch (libGlobal.youMustPref) {
       case youllHaveTo:
       case youdHaveTo:  return theName + ' had to';
       case youllNeedTo:
       case youdNeedTo:  return theName + ' needed to';
       default:          return theName + ' had to';
     }
   }
   // present tense
   switch (libGlobal.youMustPref) {
     case youllHaveTo:
     case youdHaveTo:  return theName + ' will have to';
     case youllNeedTo:
     case youdNeedTo:  return theName + ' will need to';
     default:          return theName + ' must';
   }
 }
 itCould {
   if (gameMain.usePastTense
       || libGlobal.youMustPref == youdHaveTo
       || libGlobal.youMustPref == youdNeedTo)
     return itNom + ' could';
   else
     return itNom + ' can';
 }
 nameSeesNo {
   if (!libGlobal.preferCasual)
     return theName + ' ' + verbToSee + ' no';
   else
     return nameDoes + custMsgObj.ntAbbr + ' see any';
 }
 hasNo {
   if (!libGlobal.preferCasual)
     return verbToHave + ' no';
   else
     return verbToDo + custMsgObj.ntAbbr + ' have any';
 }
 thatIsNot {
   if (libGlobal.useContractions == usually ||
       libGlobal.useContractions == always)
     return thatIsnt;
   else
     return thatNom + ' ' + verbToBe + ' not';
 }
 thatIsnt {
   if (libGlobal.useContractions == seldom ||
       libGlobal.useContractions == never) {
     return thatNom + ' ' + verbToBe + ' not';
   }
   // I prefer "That's not" to "That isn't." Therefore, do
   // it that way whenever possible if libGlobal.useContractions
   // is usually or always.
   else if (libGlobal.useContractions == usually ||
            libGlobal.useContractions == always) {
     if (!isPlural && !gameMain.usePastTense)
       return thatIsContraction + ' not'; // "that's not"
     else
       // "those aren't", "that wasn't", "those weren't"
       return thatNom + ' ' + verbToBe + custMsgObj.ntAbbr;
   }
   else { // libGlobal.useContractions == sometimes (default)
     return thatNom + ' ' + verbToBe + custMsgObj.ntAbbr;
   }
 }
 _not() {
   if (libGlobal.useContractions == usually ||
       libGlobal.useContractions == always)
     return 'n' + custMsgObj.rsquoPlainStr + 't';
   else
     return ' not';
 }
 ntAbbr() {
   if (libGlobal.useContractions == seldom ||
       libGlobal.useContractions == never)
     return ' not';
   else
     return 'n' + custMsgObj.rsquoPlainStr + 't';
 }
;

//This function proved unnecessary.
//function ltCmdrData(str1, str2) {
//  if (libGlobal.useContractions == seldom ||
//      libGlobal.useContractions == never)
//    return str2;
//  else
//    return str1;
//}


//Unused portions of code which for some reason I don't want
//to throw away:
//modify Thing
//  verbCannotCant() {
//    if (!libGlobal.preferContractions)
//      return tSel('cannot', 'could not');
//    else if (libGlobal.useSmartQuotes == always)
//      return tSel('can&rsquo;t', 'couldn&rsquo;t');
//    else
//      return tSel('can\'t', 'couldn\'t');
//  }
//  verbDoesNot() {
//    if (!libGlobal.preferContractions)
//      return tSel('do' + verbEndingEs + ' not', 'did not');
//    else if (libGlobal.useSmartQuotes == always)
//      return tSel('do' + verbEndingEs + 'n&rsquo;t', 'didn&rsquo;t');
//    else
//      return tSel('do' + verbEndingEs + 'n\'t', 'didn\'t');
//  }
//  verbIsNot() {
//    if (!libGlobal.preferContractions)
//      return tSel(isPlural ? 'are not' : 'is not',
//                  isPlural ? 'were not' : 'was not');
//    else if (libGlobal.useSmartQuotes == always)
//      return tSel(isPlural ? 'aren&rsquo;t' : 'isn&rsquo;t',
//                  isPlural ? 'weren&rsquo;t' : 'wasn&rsquo;t');
//    else
//      return tSel(isPlural ? 'aren\'t' : 'isn\'t',
//                  isPlural ? 'weren\'t' : 'wasn\'t');
//  }
//  verbSeesNo() {
//    if (!libGlobal.preferCasual)
//      return verbToSee + ' no';
//    else
//      return verbToDo + custMsgObj.ntAbbr + ' see any';
//  }
//;

///////////////////////////////////////////////////////////
// ACTOR MODIFICATIONS
///////////////////////////////////////////////////////////

modify Actor
 thatIsContraction {
   if (libGlobal.useContractions == seldom ||
       libGlobal.useContractions == never) // Lt. Cmdr. Data scenario
     return thatNom + ' ' + verbToBe;
   else
     return thatNom +
       tSel([custMsgObj.rsquoPlainStr + 'm',
             custMsgObj.rsquoPlainStr + 're',
             custMsgObj.rsquoPlainStr + 's',
             custMsgObj.rsquoPlainStr + 're',
             custMsgObj.rsquoPlainStr + 're',
             ' are'][conjugationSelector], ' ' + verbToBe);
 }
 itIsContraction {
   if (libGlobal.useContractions == seldom ||
       libGlobal.useContractions == never) // Lt. Cmdr. Data scenario
     return itNom + ' ' + verbToBe;
   else
     return itNom +
       tSel(custMsgObj.rsquoPlainStr +
         ['m',
          're',
          's',
          're',
          're',
          're'][conjugationSelector], ' ' + verbToBe);
 }
 nameIs {
   if (referralPerson == ThirdPerson)
     return theName + ' ' + verbToBe;
   else if (libGlobal.useContractions == usually ||
            libGlobal.useContractions == always)
     // Do thatIsContraction in order to get the proper contractions
     // whenever appropriate.
     return thatIsContraction;
   else
     return theName + ' ' + verbToBe;
 }
 nameIsnt {
   if (libGlobal.useContractions == seldom ||
       libGlobal.useContractions == never) // Lt. Cmdr. Data scenario
     return nameIs + ' not';
   // I think, e.g., "you're not" sounds more natural than "you aren't",
   // so if the author picks my settings -- namely, if they set it so
   // libGlobal.useContractions == usually -- then change this appropriately.
   else if (libGlobal.useContractions == usually ||
            libGlobal.useContractions == always)
     return tSel(['I' + custMsgObj.rsquoPlainStr + 'm not',
                  'you' + custMsgObj.rsquoPlainStr + 're not',
                  nameIs + 'n' + custMsgObj.rsquoPlainStr + 't',
                  'we' + custMsgObj.rsquoPlainStr + 're not',
                  'you' + custMsgObj.rsquoPlainStr + 're not',
                  nameIs + 'n' + custMsgObj.rsquoPlainStr + 't'][conjugationSelector],
                nameIs + 'n' + custMsgObj.rsquoPlainStr + 't');
   else
     return (conjugationSelector == 1 && !gameMain.usePastTense
       ? 'I' + custMsgObj.rsquoPlainStr + 'm not' : inherited);
 }
 nameIsNot {
   if (libGlobal.useContractions == usually ||
       libGlobal.useContractions == always)
     return nameIsnt;
   else
     return theName + ' ' + verbToBe + ' not';
 }
 thatIsnt {
   // This is complicated, but fortunately, whenever
   // referralPerson is FirstPerson or SecondPerson,
   // what we want is identical with nameIsnt, so that
   // makes it easier.
   if (referralPerson == FirstPerson ||
       referralPerson == SecondPerson)
     return nameIsnt;
   // All remaining stuff is ThirdPerson.
   else if (libGlobal.useContractions == seldom ||
            libGlobal.useContractions == never)
     return thatNom + ' ' + verbToBe + ' not';
   // All remaining cases will do the contraction
   // (and are in ThirdPerson).
   else if (!isPlural && !gameMain.usePastTense)
     // "that's not", "he's not", "she's not"
     return thatNom + custMsgObj.sOrWasStr + ' not';
   else
     // "those aren't", "those weren't",
     // "that wasn't", "he wasn't", "she wasn't"
     return thatNom + ' ' + verbToBe + custMsgObj.ntAbbr;
 }
 // Commented out because this should be the same as Thing.thatIsNot
 //thatIsNot {
 //  if (libGlobal.useContractions == usually ||
 //      libGlobal.useContractions == always)
 //    return thatIsnt;
 //  else
 //    return thatNom + ' ' + verbToBe + ' not';
 //}
 nameWouldHaveTo {
   // Actor.nameWouldHaveTo is in large measure similar to
   // Thing.nameWouldHaveTo...
   if (libGlobal.youMustPref == youMust)
     return theName + ' ' + verbMust;
   else if (gameMain.usePastTense) {
     if (libGlobal.youMustPref == youllNeedTo ||
         libGlobal.youMustPref == youdNeedTo)
       return theName + ' would have needed to';
     else
       return theName + ' would have had to';
   }
   // ... butActor.nameWouldHaveTo differs from
   // Thing.nameWouldHaveTo in its use of contractions.

   // The following are all present tense.
   else if (referralPerson == 3) {
     switch (libGlobal.youMustPref) {
       case youllHaveTo: return theName + ' will have to';
       case youdHaveTo:  return theName + ' would have to';
       case youllNeedTo: return theName + ' will need to';
       case youdNeedTo:  return theName + ' would need to';
       default:          return theName + ' ' + verbMust; // should never happen; covered above
     }
   }
   // All other cases involve the use of a pronoun followed
   // by a contraction.
   else {
     switch (libGlobal.youMustPref) {
       case youllHaveTo: return theName + custMsgObj.rsquoStr + 'll have to';
       case youdHaveTo:  return theName + custMsgObj.rsquoStr + 'd have to';
       case youllNeedTo: return theName + custMsgObj.rsquoStr + 'll need to';
       case youdNeedTo:  return theName + custMsgObj.rsquoStr + 'd need to';
       default:          return theName + ' ' + verbMust; // should never happen; covered above
     }
   }
 }
 // Use this when it makes no sense to use the subjective,
 // so you want to, e.g., substitute "would" with "will".
 nameWillHaveTo {
   if (gameMain.usePastTense) {
     switch (libGlobal.youMustPref) {
       case youllHaveTo:
       case youdHaveTo:  return theName + ' had to';
       case youllNeedTo:
       case youdNeedTo:  return theName + ' needed to';
       default:          return theName + ' had to';
     }
   }
   // present tense
   switch (libGlobal.youMustPref) {
     case youllHaveTo:
     case youdHaveTo:
       if (referralPerson == 3)
         return theName + ' will have to';
       else
         return theName + custMsgObj.rsquoStr + 'll have to';
     case youllNeedTo:
     case youdNeedTo:
       if (referralPerson == 3)
         return theName + ' will need to';
       else
         return theName + custMsgObj.rsquoStr + 'll need to';
     default:
       return theName + ' must';
   }
 }

 // The following Actor modifications are to correct an inconsistency
 // (a bug?) in the TADS 3.0.9 library, whereby 1st person plural
 // comes out as "I" instead of "we" in some cases (even though
 // 1st person plural does work in other cases). As of right now
 // (the morning of April 8, 2006), I don't know whether this will
 // be corrected in the T3 library, but I am correcting it here.
 theName {
   return (referralPerson == ThirdPerson
           ? inherited : itNom);
 }
 theNameObj {
   return (referralPerson == ThirdPerson
           ? inherited : itObj);
 }
 theNamePossAdj {
   return (referralPerson == ThirdPerson
           ? inherited : itPossAdj);
 }
 theNamePossNoun {
   return (referralPerson == ThirdPerson
           ? inherited : itPossNoun);
 }
 aName {
   return (referralPerson == ThirdPerson
           ? inherited : itNom);
 }
 aNameObj {
   return (referralPerson == ThirdPerson
           ? inherited : itObj);
 }
;


///////////////////////////////////////////////////////////
// MSG_NEU.T MODIFICATIONS
///////////////////////////////////////////////////////////

//buildParam(typeString, nm) {
//    return '{' + typeString + ' ' + nm + '}';
//}
//buildSynthParam(typeString, obj) {
//    return '{' + typeString + ' ' + gSynthMessageParam(obj) + '}';
//}

modify libMessages //superclass is MessageHelper
   whomPronoun = 'whom'
   offerOopsNote = true
   commandLookAround = 'look around'
   commandFullScore = 'full score'
   announceRemappedAction(action) {
       return '<./p0>\n<.assume>' + action.getParticiplePhrase()
           + '<./assume>\n';
   }
   announceImplicitAction(action, ctx) {
       return ctx.buildImplicitAnnouncement(action.getImplicitPhrase(ctx));
   }
   silentImplicitAction(action, ctx) { return ''; }
   announceMoveToBag(action, ctx) {
       return ctx.buildImplicitAnnouncement(
           action.getImplicitPhrase(ctx) + ' to make room');
   }
   showCredit(name, byline) { "<<name>> <<byline>>"; }
   showVersion(name, version) { "<<name>> version <<version>>"; }
   noAboutInfo {
       "<.parser><<custMsgObj.ThisStoryStr>> has no
           ABOUT information.<./parser> ";
       // I was going to do it the following way, but decided I like
       // the original best after all.
       //"<.parser><<custMsgObj.ThisStoryStr>> ";
       //if (!libGlobal.preferCasual)
       //    "has no";
       //else
       //    "does<<custMsgObj.ntAbbr>> have any";
       //" ABOUT information.<./parser> ";
   }
   showListState(state) { " (<<state>>)"; }
   allInSameListState(lst, stateName)
       { " (<<lst.length() == 2 ? 'both' : 'all'>> <<stateName>>)"; }
   distantThingDesc(obj) {
       gMessageParams(obj);
       "{It's obj} too far away to make out any detail. ";
   }
   obscuredThingDesc(obj, obs) {
       gMessageParams(obj, obs);
       "{You/he} {can\'t} make out any detail through {the obs/him}. ";
   }
   distantThingSoundDesc(obj)
       { "{You/he} {can\'t} hear any detail from this distance. "; }
   obscuredThingSoundDesc(obj, obs) {
       gMessageParams(obj, obs);
       "{You/he} {can\'t} hear any detail through {the obs/him}. ";
   }
   distantThingSmellDesc(obj)
       { "{You/he} {can\'t} smell much at this distance. "; }
   obscuredThingSmellDesc(obj, obs) {
       gMessageParams(obj, obs);
       "{You/he} {can\'t} smell much through {the obs/him}. ";
   }
   thingTasteDesc(obj) {
       gMessageParams(obj);
       "{It/he obj} taste{s/d} much as {you/he} would {|have}
       expect{|ed}. ";
   }
   thingFeelDesc(obj) {
       "{You/he} ";
       if (!libGlobal.preferCasual)
           "{feel[s actor]|felt} no";
       else
           "<<gActor.verbToDo>><<custMsgObj.ntAbbr>> feel any";
       "thing out of the ordinary. ";
   }
   obscuredReadDesc(obj) {
       gMessageParams(obj);
       "{You/he} {can\'t} see {that obj/him} well enough to read
       {it/him}. ";
   }
   dimReadDesc(obj) {
       gMessageParams(obj);
       "There<<custMsgObj.sOrWasStr>>
       not enough light to read {that obj/him}. ";
   }
   litMatchDesc(obj) { "\^<<obj.nameIs>> lit. "; }
   unlitMatchDesc(obj) { "\^<<obj.nameIs>> an ordinary match. "; }
   litCandleDesc(obj) { "\^<<obj.nameIs>> lit. "; }
   putDestContainer(obj) { return 'into ' + obj.theNameObj; }
   putDestSurface(obj) { return 'onto ' + obj.theNameObj; }
   putDestUnder(obj) { return 'under ' + obj.theNameObj; }
   putDestBehind(obj) { return 'behind ' + obj.theNameObj; }
   putDestFloor(obj) { return 'to ' + obj.theNameObj; }
   listSepMiddle = ", "
   listSepTwo = " and "
   listSepEnd = ", and "
   longListSepMiddle = "; "
   longListSepTwo = ", and "
   longListSepEnd = "; and "
   showScoreMessage(points, maxPoints, turns) {
       "In <<turns>> move<<turns == 1 ? '' : 's'>>,
       <<libGlobal.useContractions == always
       ? 'you' + custMsgObj.rsquoPlainStr + 've' : 'you have'>>
       scored <<points>> of a possible <<maxPoints>> point<<
         maxPoints == 1 ? '' : 's'>>. ";
   }
   showScoreNoMaxMessage(points, turns) {
       "In <<turns>> move<<turns == 1 ? '' : 's'>>,
       <<libGlobal.useContractions == always
       ? 'you' + custMsgObj.rsquoPlainStr + 've' : 'you have'>>
       scored <<points>> point<<points == 1 ? '' : 's'>>. ";
   }
   showScoreRankMessage(msg) { "This makes you <<msg>>. "; }
   showFullScorePrefix = "Your score consists of:"
   fullScoreItemPoints(points) {
       "<<points>> point<<points == 1 ? '' : 's'>> for ";
   }
   firstScoreChange(delta) {
       "<.commandsep><.notification><<
           basicScoreChange(delta)>><./notification>
       \n<.notification>If <<custMsgObj.youdStr>>
       prefer not to be notified about
       score changes in the future, type <<
       aHref('notify off', 'NOTIFY OFF', 'Turn off score notifications')
       >>.<./notification> ";
   }
   scoreChange(delta) {
       "<.commandsep><.notification><<
       basicScoreChange(delta)>><./notification> ";
   }
   basicScoreChange(delta) {
       "Your <<aHref(commandFullScore, 'score', 'Show full score')>>
       has just <<delta > 0 ? 'in' : 'de'>>creased by
       <<spellInt(delta > 0 ? delta : -delta)>>
       point<<delta is in (1, -1) ? '' : 's'>>.";
   }
   footnoteRef(num) {
       local str;
       str = '<sup>[<a href="footnote ' + num + '"><.a>';
       str += num;
       str += '<./a></a>]</sup>';
       return str;
   }
   firstFootnote() {
       "<.commandsep><.notification>A number in [square brackets] like
       the one above refers to a footnote, which you can read by typing
       FOOTNOTE followed by the number:
       <<aHref('footnote 1', 'FOOTNOTE 1', 'Show footnote [1]')>>,
       for example.  Footnotes usually contain added background information
       that might be interesting but is<<custMsgObj.ntAbbr>>
       essential to the story.
       If <<custMsgObj.youdStr>> prefer not to see footnotes at all,
       you can control their appearance by typing
       <<aHref('footnotes', 'FOOTNOTES',
               'Control footnote appearance')>>.<./notification> ";
   }
   noSuchFootnote(num) {
       "<.parser><<custMsgObj.TheStoryStr>> has never referred to any such
       footnote.<./parser> ";
   }
   showFootnoteStatus(stat) {
       "The current setting is FOOTNOTES ";
       switch(stat)
       {
       case FootnotesOff:
           "OFF, which hides all footnote references.
           Type <<aHref('footnotes medium', 'FOOTNOTES MEDIUM',
                        'Set footnotes to Medium')>> to
           show references to footnotes except those
           <<custMsgObj.youveStr>>
           already seen, or <<aHref('footnotes full', 'FOOTNOTES FULL',
                                    'Set footnotes to Full')>>
           to show all footnote references. ";
           break;
       case FootnotesMedium:
           "MEDIUM, which shows references to unread footnotes, but
           hides references to those <<custMsgObj.youveStr>>
           already read.  Type
           <<aHref('footnotes off', 'FOOTNOTES OFF',
                   'Turn off footnotes')>> to hide
           footnote references entirely, or <<aHref(
               'footnotes full', 'FOOTNOTES FULL',
               'Set footnotes to Full')>> to show every reference, even to
           notes <<custMsgObj.youveStr>> already read. ";
           break;
       case FootnotesFull:
           "FULL, which shows every footnote reference, even to
           notes <<custMsgObj.youveStr>>
           already read.  Type <<aHref('footnotes medium',
           'FOOTNOTES MEDIUM', 'Set footnotes to Medium')>> to show
           only references to notes you
           have<<custMsgObj.ntAbbr>> yet read, or
           <<aHref('footnotes off', 'FOOTNOTES OFF', 'Turn off footnotes')>>
           to hide footnote references entirely. ";
           break;
       }
   }
   acknowledgeFootnoteStatus(stat) {
       "<.parser>The setting is now
       <<shortFootnoteStatus(stat)>>.<./parser> ";
   }
   shortFootnoteStatus(stat) {
       "FOOTNOTES <<
         stat == FootnotesOff ? 'OFF'
         : stat == FootnotesMedium ? 'MEDIUM'
         : 'FULL' >>";
   }
   mainCommandPrompt(which) { "\b&gt;"; }
   parserErrorString(actor, msg) { say(msg); }
   emptyCommandResponse = "<.parser>I beg your pardon?<./parser> "
   invalidCommandToken(ch) {
       "<.parser><<custMsgObj.TheStoryStr>>
       does<<custMsgObj.ntAbbr>> know how to use the character
       <<custMsgObj.lsquoStr>><<ch>><<custMsgObj.rsquoStr>>
       in a command.<./parser> ";
   }
   commandResultsPrefix = '<.p0>'
   commandInterruptionPrefix = '<.p>'
   commandResultsSeparator = '<.p>'
   complexResultsSeparator = '<.p>'
   internalResultsSeparator = '<.p>'
   commandResultsSuffix = ''
   commandResultsEmpty =
       ('Nothing obvious happen' + tSel('s', 'ed') + '.<.p>')
   intraCommandSeparator = '<.p>'
   smellDescSeparator() {
       "<.p>";
   }
   soundDescSeparator() {
       "<.p>";
   }
   cannotTalkTo(targetActor, issuingActor) {
       "\^<<targetActor.nameIs>> not something <<issuingActor.itNom>>
       <<issuingActor.verbCan>> talk to. ";
   }
   alreadyTalkingTo(actor, greeter) {
       "\^<<greeter.theName>> already <<greeter.verbToHave>>
       <<actor.theNamePossAdj>> attention. ";
   }
   noTopicsNotTalking = "<.parser>{You're} not currently talking
                         to anyone.<./parser> "
   oopsNote() {
       if (offerOopsNote) {
           "<.commandsep><.notification>If this was an accidental
           misspelling, you can correct it by typing OOPS followed by the
           corrected word now.  Any time the <<custMsgObj.storyStr>> points out an unknown
           word, you can correct a misspelling using OOPS as your next
           command.<./notification> ";
           libMessages.offerOopsNote = nil;
       }
   }
   oopsOutOfContext = "<.parser>You can only use OOPS to correct
       a misspelling immediately after the <<custMsgObj.storyStr>>
       points out a word
       it does<<custMsgObj.ntAbbr>> know.<./parser> "
   oopsMissingWord = "<.parser>To use OOPS to correct a misspelling,
       put the corrected word after OOPS, as in OOPS BOOK.<./parser> "
   acknowledgeVerboseMode(verbose) {
       if (verbose)
           "<.parser>VERBOSE mode is now selected.<./parser> ";
       else
           "<.parser>TERSE mode is now selected.<./parser> ";
   }
   shortVerboseStatus(stat) { "<<stat ? 'VERBOSE' : 'TERSE'>> mode"; }
   showNotifyStatus(stat) {
       "<.parser>Score notifications are
       currently <<stat ? 'on' : 'off'>>.<./parser> ";
   }
   shortNotifyStatus(stat) { "NOTIFY <<stat ? 'ON' : 'OFF'>>"; }
   acknowledgeNotifyStatus(stat) {
       "<.parser>Score notifications are now
       <<stat ? 'on' : 'off'>>.<./parser> ";
   }
   // announceMultiActionObject() and announceAmbigActionObject()
   // are handled differently in TADS 3.0.9 vs. TADS 3.0.10+,
   // and furthermore we don't need to modify either version of
   // either of those two methods. So just don't override them at all.
   // TADS 3.0.9 methods:
   //announceMultiActionObject(obj, whichObj, action) {
   //    return '<./p0>\n<.announceObj>' + obj.name
   //        + ':<./announceObj> <.p0>';
   //}
   //announceAmbigActionObject(obj, whichObj, action) {
   //    return '<.assume>' + obj.theNameObj + '<./assume>\n';
   //}
   // TADS 3.0.15 methods:
   //announceMultiActionObject(obj, whichObj) {
   //    addReport(new MultiObjectAnnouncement(obj, whichObj, gAction));
   //}
   //announceAmbigActionObject(obj, whichObj) {
   //    addReport(new AmbigObjectAnnouncement(obj, whichObj, gAction));
   //}
   announceDefaultObject(obj, whichObj, action, resolvedAllObjects) {
       return '<.assume>'
           + action.announceDefaultObject(obj, whichObj, resolvedAllObjects)
           + '<./assume>\n';
   }
   noCommandForAgain() {
       "<.parser>There<<(libGlobal.useContractions == seldom ||
         libGlobal.useContractions == never) ? ' is'
         : custMsgObj.rsquoPlainStr + 's' >>
       nothing to repeat.<./parser> ";
   }
   againCannotChangeActor() {
       "<.parser>To repeat a command like
       <<custMsgObj.ldquoStr>>turtle, go north,<<custMsgObj.rdquoStr>>
       just say <<custMsgObj.ldquoStr>>again,<<custMsgObj.rdquoStr>> not
       <<custMsgObj.ldquoStr>>turtle, again.<<custMsgObj.rdquoStr>><./parser> ";
   }
   againCannotTalkToTarget(issuer, target) {
       "\^<<issuer.theName>> <<issuer.verbCannot>> repeat that command. ";
   }
   againNotPossible(issuer) {
       "That command <<issuer.verbCannot>> be repeated now. ";
   }
   systemActionToNPC() {
       "<.parser>This command cannot be directed to another
       character in <<custMsgObj.theStoryStr>>.<./parser> ";
   }
   confirmQuit() {
       "Do you really want to quit?\ (<<aHref('y', 'Y', 'Confirm quitting')
       >> is affirmative) >\ ";
   }
   okayQuitting() { }
   notTerminating() {
       "<.parser>Continuing the <<custMsgObj.storyStr>>.<./parser> ";
   }
   confirmRestart() {
       "Do you really want to start over?\ (<<aHref('Y', 'Y',
       'Confirm restart')>> is affirmative) >\ ";
   }
   notRestarting() { "<.parser>Continuing the <<custMsgObj.storyStr>>.<./parser> "; }
   showFinishMsg(msg) { "<.p>*** <<msg>>\ ***<.p>"; }
   //finishDeathMsg = ('YOU'
   //    + tSel((libGlobal.useContractions == always
   //       ? custMsgObj.rsquoPlainStr + 'VE' : ' HAVE'), '')
   //    + ' DIED')
   finishDeathMsg =
     (gPlayerChar.theName.toUpper
       + tSel(
           (libGlobal.useContractions == always
             ? (gPlayerChar.referralPerson != ThirdPerson ? '&rsquo;VE' : ' HAVE')
             : ' HAVE' )
         , '')
       + ' DIED')
   finishVictoryMsg = ('YOU'
       + tSel((libGlobal.useContractions == always
          ? custMsgObj.rsquoPlainStr + 'VE' : ' HAVE'), '')
       + ' WON')
   finishFailureMsg = ('YOU'
       + tSel((libGlobal.useContractions == always
          ? custMsgObj.rsquoPlainStr + 'VE' : ' HAVE'), '')
       + ' FAILED')
   finishGameOverMsg = 'GAME OVER'
   getSavePrompt =
       'Please select a file in which to save the current position'
   getRestorePrompt = 'Please select the saved position file to restore'
   saveOkay() { "<.parser>Saved.<./parser> "; }
   saveCanceled() { "<.parser>Canceled.<./parser> "; }
   saveFailed(exc) {
       "<.parser>Failed; your computer might be running low
       on disk space, or you might not have the necessary permissions
       to write this file.<./parser> ";
   }
   noteMainRestore() { "<.parser>Restoring saved game...<./parser>\n"; }
   restoreOkay() { "<.parser>Restored.<./parser> "; }
   restoreCanceled() { "<.parser>Canceled.<./parser> "; }
   restoreInvalidFile() {
       "<.parser>Failed: this is not a valid saved
       position file.<./parser> ";
   }
   restoreCorruptedFile() {
       "<.parser>Failed: this saved state file appears to be
       corrupted.  This can occur if the file was modified by another
       program, or the file was copied between computers in a non-binary
       transfer mode, or the physical media storing the file were
       damaged.<./parser> ";
   }
   restoreInvalidMatch() {
       "<.parser>Failed: the file was not saved by
       <<custMsgObj.thisStoryStr>>
       (or was saved by an incompatible version of
       <<custMsgObj.theStoryStr>>).<./parser> ";
   }
   restoreFailed(exc) {
       "<.parser>Failed: the position could not be
       restored.<./parser> ";
   }
   filePromptFailed() {
       "<.parser>A system error occurred asking for a filename.
       Your computer might be running low on memory, or might have a
       configuration problem.<./parser> ";
   }
   pausePrompt() {
       "<.parser><<custMsgObj.TheStoryStr>> is now paused.  Please press
       the space bar when you are ready to resume the
       <<custMsgObj.storyStr>>, or
       press the <<custMsgObj.lsquoPlainStr>>S<<custMsgObj.rsquoPlainStr>>
       key to save the current position.<./parser><.p>";
   }
   pauseSaving() {
       "<.parser>Saving the <<custMsgObj.storyStr>>...<./parser><.p>";
   }
   pauseEnded() {
       "<.parser>Resuming the <<custMsgObj.storyStr>>.<./parser> ";
   }
   inputScriptOkay(fname) {
       "<.parser>Reading commands from
       <<custMsgObj.ldquoStr>><<fname.htmlify()
        >><<custMsgObj.rdquoStr>>...<./parser>\n ";
   }
   getScriptingPrompt = 'Please select a name for the new script file'
   scriptingOkay() {
       "<.parser>Text will now be saved to the script file.
       Type <<aHref('script off', 'SCRIPT OFF', 'Turn off scripting')>> to
       discontinue scripting.<./parser> ";
   }
   scriptingCanceled = "<.parser>Canceled.<./parser> "
   scriptOffOkay = "<.parser>Scripting ended.<./parser> "
   scriptOffIgnored = "<.parser>No script is currently being
                       recorded.<./parser> "
   getRecordingPrompt = 'Please select a name for the new command log file'
   recordingOkay = "<.parser>Commands will now be recorded.  Type
                    <<aHref('record off', 'RECORD OFF',
                            'Turn off recording')>>
                    to stop recording commands.<.parser> "
   recordingCanceled = "<.parser>Canceled.<./parser> "
   recordOffOkay = "<.parser>Command recording ended.<./parser> "
   recordOffIgnored = "<.parser>No command recording is currently being
                       made.<./parser> "
   getReplayPrompt = 'Please select the command log file to replay'
   replayCanceled = "<.parser>Canceled.<./parser> "
   undoOkay(actor, cmd) {
       "<.parser>Taking back one turn: <<custMsgObj.ldquoStr>>";
       if (actor != nil)
           "<<actor>>, ";
       "<<cmd>><<custMsgObj.rdquoStr>>.<./parser><.p>";
   }
   undoFailed() {
       "<.parser>No more undo information is
       available.<./parser> ";
   }
   noteWithScript = "<.parser>Comment recorded.<./parser> "
   noteWithoutScript = "<.parser>Comment <b>not</b> recorded.<./parser> "
   noteWithoutScriptWarning = "<.parser>Comment <b>not</b> recorded.
       Use <<aHref('script', 'SCRIPT', 'Begin saving the transcript')
         >> if you want to start recording the transcript.<./parser> "
   // noteAccepted is only for TADS 3.0.9 and earlier
   noteAccepted = "<.parser>Noted.<./parser> "
   // noteWithoutNote is only for TADS 3.0.9 and earlier
   noteWithoutNote = "<.p><.notification>You can enter notes into the
       transcript by typing NOTE followed by any text you wish to enter
       as your note.  NOTE without any message text is fine, too, in
       case you simply want to call attention to something immediately
       preceding in the transcript.<./notification> "
   // For the sake of reference, here is the TADS 3.0.9 version of
   // noteWithoutScript:
   //noteWithoutScript = "<.p><.notification>Note that the transcript
   //    is<<custMsgObj.ntAbbr>>
   //    currently being recorded.  NOTE is usually used to provide feedback
   //    to the author by putting a comment in the transcript, so it's most
   //    useful when you're saving the transcript to a file.  If you want
   //    to start saving the transcript, please type <<
   //      aHref('script', 'SCRIPT', 'Begin saving the transcript')
   //      >>.<./notification> "
   invalidFinishOption(resp) {
       "\bThat is<<custMsgObj.ntAbbr>> one of the options. ";
   }
   exitsOnOffOkay(stat, look) {
       if (stat && look)
           "<.parser>The list of exits will now be shown in both
           the status line and in each room description.<./parser> ";
       else if (!stat && !look)
           "<.parser>The list of exits will no longer be shown in
           either the status line or room description.<./parser> ";
       else
           "<.parser>The list of exits <<stat ? 'will' : 'will not'>> be
           shown in the status line, and
           <<look ? 'will' : 'wo' + custMsgObj.ntAbbr>>
           be included in room descriptions.<./parser> ";
   }
   explainExitsOnOff =
       "<.p><.notification>You can control the exit listings with the
       EXITS command.
       <<aHref('exits status', 'EXITS STATUS',
               'Turn on status line exit listings')>> shows the exit
       list in the status line,
       <<aHref('exits look', 'EXITS LOOK',
               'List exits in room descriptions')>>
       shows a full exit list in each room description,
       <<aHref('exits on', 'EXITS ON', 'Turn on all exit lists')>>
       shows both, and
       <<aHref('exits off', 'EXITS OFF', 'Turn off all exit lists')>>
       turns off both kinds of exit lists.<./notification> "
   currentExitsSettings(statusLine, roomDesc) {
       "EXITS ";
       if (statusLine && roomDesc)
           "ON";
       else if (statusLine)
           "STATUSLINE";
       else if (roomDesc)
           "LOOK";
       else
           "OFF";
   }
   hintsDisabled = '<.parser>Hints are now disabled.<./parser> '
   sorryHintsDisabled () {
       return '<.parser>Sorry, but hints have been disabled
           for this session, as you requested.  If '
           + custMsgObj.youveStr + ' changed your mind, '
           + custMsgObj.youllStr + ' have to save your
           current position, exit the TADS interpreter,
           and start a new interpreter session.<./parser> ';
   }
   hintsNotPresent = '<.parser>Sorry, ' + custMsgObj.thisStoryStr
                      + ' does' + custMsgObj.ntAbbr
                      + ' have any built-in hints.<./parser> '
   currentlyNoHints = '<.parser>Sorry, no hints are currently available.
                       Please check back later.<./parser> '
   showHintWarning =
      "<.notification>Warning: Some people do<<custMsgObj.ntAbbr>>
      like built-in hints, since the temptation to ask for help
      prematurely can become overwhelming when hints are so close
      at hand.  If <<custMsgObj.youreStr>> worried that your willpower
      <<(libGlobal.useContractions == seldom
        || libGlobal.useContractions == never)
        ? 'will not' : 'won' + custMsgObj.rsquoPlainStr + 't' >>
      hold up, you can disable hints for the
      rest of this session by typing <<aHref('hints off', 'HINTS OFF')
      >>.  If you still want to see the hints now, type
      <<aHref('hint', 'HINT')>>.<./notification> "
   hintsDone = '<.parser>Done.<./parser> '
   commandNotPresent = "<.parser>That command is<<custMsgObj.ntAbbr>>
       needed in <<custMsgObj.thisStoryStr>>.<./parser> "
   scoreNotPresent = "<.parser><<custMsgObj.ThisStoryStr>>
       does<<custMsgObj.ntAbbr>> use scoring.<./parser> "
   mentionFullScore = "<.p><.notification>To see a detailed accounting
       of your score, type <<
         aHref('full score', 'FULL SCORE') >>.<./notification> "
   // These methods causes errors when compiled with older versions
   // of TADS 3. Furthermore, we don't need to change them. So don't.
   //savedDefaults() {
   //    "<.parser>Your current settings have been stored as the
   //    default settings for new games.  The saved settings are: ";
   //    settingsUI.showAll();
   //    ".  Most newer games will apply these settings automatically
   //    whenever you start (or RESTART) the game, but note that older
   //    games will not.<./parser> ";
   //}
   //restoredDefaults() {
   //    "<.parser>The saved default settings have been put into
   //    effect.  The new settings are: ";
   //    settingsUI.showAll();
   //    ".<./parser> ";
   //}
   settingsItemSeparator = "; "
   defaultsFileNotSupported = "<.parser>Sorry, but the version of the
       TADS interpreter <<custMsgObj.youreStr>> using
       does<<custMsgObj.ntAbbr>> support saving or
       restoring defaults.  You must install a more recent version
       in order to use this feature.<./parser> "
   defaultsFileWriteError = "<.parser>An error occurred writing
       the default settings file.  The defaults have not been
       saved.  You might be out of disk space, or you might not
       have the necessary permissions to write the file.<./parser> "
   menuKeyList = [
                  ['q'],
                  ['p', '[left]', '[bksp]', '[esc]'],
                  ['u', '[up]'],
                  ['d', '[down]'],
                  ['ENTER', '\n', '[right]', ' ']
                 ]
   prevMenuLink = '<font size=-1>Previous</font>'
   nextMenuTopicLink = '<font size=-1>Next</font>'
   textMenuMainPrompt(keylist) {
       "\bSelect a topic number, or press
       <<custMsgObj.lsquoStr>><<
       keylist[M_PREV][1]>><<custMsgObj.rsquoStr>>
       for the previous menu or
       <<custMsgObj.lsquoStr>><<
       keylist[M_QUIT][1]>><<custMsgObj.rsquoStr>>
       to quit:\ ";
   }
   textMenuTopicPrompt() {
       "\bPress the space bar to display the next line,
       <<custMsgObj.lsquoStr>><b>P</b><<custMsgObj.rsquoStr>>
       to go to the previous menu, or
       <<custMsgObj.lsquoStr>><b>Q</b><<custMsgObj.rsquoStr>>
       to quit.\b";
   }
   menuTopicProgress(cur, tot) { " [<<cur>>/<<tot>>]"; }
   menuTopicListEnd = '[The End]'
   menuLongTopicEnd = '[The End]'
   menuInstructions(keylist, prevLink) {
       "<tab align=right ><b>\^<<keylist[M_QUIT][1]>></b>=Quit <b>\^<<
       keylist[M_PREV][1]>></b>=Previous Menu<br>
       <<prevLink != nil ? aHrefAlt('previous', prevLink, '') : ''>>
       <tab align=right ><b>\^<<keylist[M_UP][1]>></b>=Up <b>\^<<
       keylist[M_DOWN][1]>></b>=Down <b>\^<<
       keylist[M_SEL][1]>></b>=Select<br>";
   }
   menuNextChapter(keylist, title, hrefNext, hrefUp) {
       "Next: <a href='<<hrefNext>>'><<title>></a>;
       <b>\^<<keylist[M_PREV][1]>></b>=<a href='<<hrefUp>>'>Menu</a>";
   }
   cannotReachObject(obj) {
       "{You/he} {cannot} reach <<obj.theNameObj>>. ";
   }
   cannotReachContents(obj, loc) {
       gMessageParams(obj, loc);
       return '{You/he} {cannot} reach {the obj/him} through '
              + '{the loc/him}. ';
   }
   cannotReachOutside(obj, loc) {
       gMessageParams(obj, loc);
       return '{You/he} {cannot} reach {the obj/him} through '
              + '{the loc/him}. ';
   }
   soundIsFromWithin(obj, loc) {
       "\^<<obj.theName>>
         <<custMsgObj.appearStr>><<obj.verbEndingSEd>> to be
       coming from inside <<loc.theNameObj>>. ";
   }
   soundIsFromWithout(obj, loc) {
       "\^<<obj.theName>>
       <<custMsgObj.appearStr>><<obj.verbEndingSEd>> to be
       coming from outside <<loc.theNameObj>>. ";
   }
   smellIsFromWithin(obj, loc) {
       "\^<<obj.theName>>
       <<custMsgObj.appearStr>><<obj.verbEndingSEd>> to be
       coming from inside <<loc.theNameObj>>. ";
   }
   smellIsFromWithout(obj, loc) {
       "\^<<obj.theName>>
       <<custMsgObj.appearStr>><<obj.verbEndingSEd>> to be
       coming from outside <<loc.theNameObj>>. ";
   }
   pcDesc(actor) {
       "\^<<actor.theName>> look<<actor.verbEndingSEd>> the same
       as usual. ";
   }
   roomActorStatus(actor) {
       if (actor.posture != standing)
           " (<<actor.posture.participle>>)";
   }
   actorInRoomStatus(actor, room)
       { " (<<actor.posture.participle>> <<room.actorInName>>)"; }
   roomDarkName = 'In the dark'
   roomDarkDesc = "It<<custMsgObj.sOrWasStr>> pitch black. "
   roomActorHereDesc(actor) {
       "\^<<actor.nameIs>> <<actor.posture.participle>>
       <<tSel('here', 'there')>>. ";
   }
   roomActorThereDesc(actor) {
       "\^<<actor.nameIs>> <<actor.posture.participle>> nearby. ";
   }
   actorInRoom(actor, cont) {
       "\^<<actor.nameIs>> <<actor.posture.participle>>
       <<cont.actorInName>>. ";
   }
   actorInRoomPosture(actor, room) {
       "\^<<actor.itIs>> <<actor.posture.participle>>
       <<room.actorInName>>. ";
   }
   roomActorPostureDesc(actor) {
       if (actor.posture != standing)
           "\^<<actor.itIs>> <<actor.posture.participle>>. ";
   }
   actorInRemoteRoom(actor, room, pov) {
       "\^<<actor.nameIs>> <<actor.posture.participle>>
       <<room.inRoomName(pov)>>. ";
   }
   actorInRemoteNestedRoom(actor, inner, outer, pov) {
       "\^<<actor.nameIs>> <<outer.inRoomName(pov)>>,
       <<actor.posture.participle>> <<inner.actorInName>>. ";
   }
   actorInGroupPrefix(posture, cont, lst) { "\^"; }
   actorInGroupSuffix(posture, cont, lst) {
       " <<lst.length() == 1 ? tSel('is', 'was') : tSel('are', 'were')>>
       <<posture.participle>> <<cont.actorInName>>. ";
   }
   actorInRemoteGroupPrefix(pov, posture, cont, remote, lst) { "\^"; }
   actorInRemoteGroupSuffix(pov, posture, cont, remote, lst) {
       " <<lst.length() == 1 ? tSel('is', 'was') : tSel('are', 'were')>>
       <<remote.inRoomName(pov)>>, <<posture.participle>>
       <<cont.actorInName>>. ";
   }
   actorHereGroupPrefix(posture, lst) { "\^"; }
   actorHereGroupSuffix(posture, lst) {
       " <<lst.length() == 1 ? tSel('is', 'was') : tSel('are', 'were')>>
       <<posture.participle>> <<tSel('here', 'there')>>. ";
   }
   actorThereGroupPrefix(pov, posture, remote, lst) { "\^"; }
   actorThereGroupSuffix(pov, posture, remote, lst) {
       " <<lst.length() == 1 ? tSel('is', 'was') : tSel('are', 'were')>>
       <<posture.participle>> <<remote.inRoomName(pov)>>. ";
   }
   sayArriving(traveler) {
       "\^<<traveler.travelerName(true)>> enter<<traveler.verbEndingSEd>>
       <<traveler.travelerLocName>>. ";
   }
   sayDeparting(traveler) {
       "\^<<traveler.travelerName(nil)>> <<traveler.verbToLeave>>
       <<traveler.travelerLocName>>. ";
   }
   sayArrivingLocally(traveler, dest) {
       "\^<<traveler.travelerName(true)>> enter<<traveler.verbEndingSEd>>
       <<traveler.travelerLocName>>. ";
   }
   sayDepartingLocally(traveler, dest)
   {
       "\^<<traveler.travelerName(true)>> <<traveler.verbToLeave>>
       <<traveler.travelerLocName>>. ";
   }
   sayTravelingRemotely(traveler, dest)
   {
       "\^<<traveler.travelerName(true)>> <<traveler.verbToGo>> to
       <<traveler.travelerLocName>>. ";
   }
   sayArrivingDir(traveler, dirName) {
       "\^<<traveler.travelerName(true)>> enter<<traveler.verbEndingSEd>>
       <<traveler.travelerRemoteLocName>> from the <<dirName>>. ";
   }
   sayDepartingDir(traveler, dirName) {
       local nm = traveler.travelerRemoteLocName;
       "\^<<traveler.travelerName(nil)>> <<traveler.verbToLeave>>
       to the <<dirName>><<nm != '' ? ' from ' + nm : ''>>. ";
   }
   sayArrivingShipDir(traveler, dirName) {
       "\^<<traveler.travelerName(true)>> enter<<traveler.verbEndingSEd>>
       <<traveler.travelerRemoteLocName>> from <<dirName>>. ";
   }
   sayDepartingShipDir(traveler, dirName) {
       local nm = traveler.travelerRemoteLocName;
       "\^<<traveler.travelerName(nil)>> <<traveler.verbToLeave>>
       to <<dirName>><<nm != '' ? ' from ' + nm : ''>>. ";
   }
   sayDepartingAft(traveler) {
       local nm = traveler.travelerRemoteLocName;
       "\^<<traveler.travelerName(nil)>> <<traveler.verbToGo>>
       aft<<nm != '' ? ' from ' + nm : ''>>. ";
   }
   sayDepartingFore(traveler) {
       local nm = traveler.travelerRemoteLocName;
       "\^<<traveler.travelerName(nil)>> <<traveler.verbToGo>>
       forward<<nm != '' ? ' from ' + nm : ''>>. ";
   }
   notOnboardShip = "That direction {is|was}<<custMsgObj.ntAbbr>>
       meaningful {|t}here. "
   sayDepartingThroughPassage(traveler, passage) {
       "\^<<traveler.travelerName(nil)>> <<traveler.verbToLeave>>
       <<traveler.travelerRemoteLocName>> through <<passage.theNameObj>>. ";
   }
   sayArrivingThroughPassage(traveler, passage) {
       "\^<<traveler.travelerName(true)>> enter<<traveler.verbEndingSEd>>
       <<traveler.travelerRemoteLocName>> through <<passage.theNameObj>>. ";
   }
   sayDepartingViaPath(traveler, passage) {
       "\^<<traveler.travelerName(nil)>> <<traveler.verbToLeave>>
       <<traveler.travelerRemoteLocName>> via <<passage.theNameObj>>. ";
   }
   sayArrivingViaPath(traveler, passage) {
       "\^<<traveler.travelerName(true)>> enter<<traveler.verbEndingSEd>>
       <<traveler.travelerRemoteLocName>> via <<passage.theNameObj>>. ";
   }
   sayDepartingUpStairs(traveler, stairs) {
       "\^<<traveler.travelerName(nil)>> <<traveler.verbToGo>>
       up <<stairs.theNameObj>>. ";
   }
   sayDepartingDownStairs(traveler, stairs) {
       "\^<<traveler.travelerName(nil)>> <<traveler.verbToGo>>
       down <<stairs.theNameObj>>. ";
   }
   sayArrivingUpStairs(traveler, stairs) {
       local nm = traveler.travelerRemoteLocName;
       "\^<<traveler.travelerName(true)>> <<traveler.verbToCome>>
       up <<stairs.theNameObj>><<nm != '' ? ' to ' + nm : ''>>. ";
   }
   sayArrivingDownStairs(traveler, stairs) {
       local nm = traveler.travelerRemoteLocName;
       "\^<<traveler.travelerName(true)>> <<traveler.verbToCome>>
       down <<stairs.theNameObj>><<nm != '' ? ' to ' + nm : ''>>. ";
   }
   sayDepartingWith(traveler, lead) {
       "\^<<traveler.travelerName(nil)>> <<traveler.verbToCome>>
       with <<lead.theNameObj>>. ";
   }
   sayDepartingWithGuide(guide, lead) {
       "\^<<lead.theName>> let<<tSel(lead.verbEndingS, '')>>
       <<guide.theNameObj>> lead the way. ";
   }
   sayOpenDoorRemotely(door, stat) {
       "Someone <<stat ? 'open' + tSel('s', 'ed')
                       : 'close' + tSel('s', 'd')>>
       <<door.theNameObj>> from the other side. ";
   }
   openMsg(obj) { return 'open'; }
   closedMsg(obj) { return 'closed'; }
   currentlyOpen = '{It\'s dobj} currently open. '
   currentlyClosed = '{It\'s dobj} currently closed. '
   openStatusMsg(obj) { return obj.itIsContraction + ' ' + obj.openDesc; }
   lockedMsg(obj) { return 'locked'; }
   unlockedMsg(obj) { return 'unlocked'; }
   currentlyLocked = '{It\'s dobj} currently locked. '
   currentlyUnlocked = '{It\'s dobj} currently unlocked. '
   onMsg(obj) { return 'on'; }
   offMsg(obj) { return 'off'; }
   matchBurnedOut(obj) {
       gMessageParams(obj);
       "{The obj/he} finish{es/ed} burning, and disappear{s/ed} into a
       cloud of ash. ";
   }
   candleBurnedOut(obj) {
       gMessageParams(obj);
       "{The obj/he} burn{s/ed} down too far to stay lit, and {goes}
       out. ";
   }
   objBurnedOut(obj) {
       gMessageParams(obj);
       "{The obj/he} {goes} out. ";
   }
;

modify playerMessages // superclass = libMessages
   commandNotUnderstood(actor) {
       "<.parser><<custMsgObj.TheStoryStr>> does<<custMsgObj.ntAbbr>>
       understand that command.<./parser> ";
   }
   specialTopicInactive(actor) {
       "<.parser>That command <<custMsgObj.cantStr>> be used
       right now.<./parser> ";
   }
   //noMatch(actor, action, txt) { action.noMatch(self, actor, txt); }
   noMatchCannotSee(actor, txt)
       { "\^<<gActor.nameSeesNo>> <<txt>> {|t}here. "; }
   noMatchNotAware(actor, txt) {
       "\^<<gActor.nameIsNot>> aware of any <<txt>> {|t}here. ";
   }
   //"cannot" is permitted here, because it feels right to me
   //in this case.
   allNotAllowed(actor) {
       //"<.parser><q>All</q> <<custMsgObj.cannotStr>> be used with that verb.<./parser> ";
       "<.parser><<custMsgObj.ldquoStr>>All<<custMsgObj.rdquoStr>>
       <<(libGlobal.useContractions == usually ||
         libGlobal.useContractions == always)
         ? 'can' + custMsgObj.rsquoPlainStr + 't'
         : 'cannot'>>
       be used with that verb.<./parser> ";
   }
   noMatchForAll(actor) {
       "<.parser>\^<<gActor.nameSeesNo>>thing suitable {|t}here.<./parser> ";
   }
   noMatchForAllBut(actor) {
       "<.parser>\^<<gActor.nameSeesNo>>thing else
       {|t}here.<./parser> ";
   }
   noMatchForListBut(actor) { noMatchForAllBut(actor); }
   noMatchForPronoun(actor, typ, pronounWord) {
       "<.parser>The word
       <<custMsgObj.ldquoStr>><<pronounWord>><<custMsgObj.rdquoStr>>
       does<<custMsgObj.ntAbbr>> refer to anything right now.<./parser> ";
   }
   askMissingObject(actor, action, which) {
       reportQuestion('<.parser>\^' + action.whatObj(which)
                      + ' do you want '
                      + (actor.referralPerson == ThirdPerson
                         ? actor.theName : '')
                      + ' to '
                      + action.getQuestionInf(which) + '?<./parser> ');
   }
   missingObject(actor, action, which) {
       "<.parser>";
       switch (libGlobal.youMustPref) {
         case youllHaveTo:
         case youdHaveTo:  "You<<custMsgObj.rsquoPlainStr>>ll have"; break;
         case youllNeedTo:
         case youdNeedTo:  "You<<custMsgObj.rsquoPlainStr>>ll need"; break;
         default:          "You need"; break;
       }
       " to be more specific
         about <<action.whatObj(which)>> you want
         <<actor.referralPerson == ThirdPerson ? actor.theName : ''>>
         to <<action.getQuestionInf(which)>>.<./parser> ";
   }
   askMissingLiteral(actor, action, which) {
       askMissingObject(actor, action, which);
   }
   missingLiteral(actor, action, which) {
       "<.parser>Please be more specific
       about <<action.whatObj(which)>> to
       <<action.getQuestionInf(which)>>.  Try, for example,
       <<action.getQuestionInf(which)>>
       <<custMsgObj.ldquoStr>>something<<custMsgObj.rdquoStr>>.<./parser> ";
   }
   reflexiveNotAllowed(actor, typ, pronounWord) {
       "<.parser><<custMsgObj.TheStoryStr>>
       does<<custMsgObj.ntAbbr>> understand how to use the word
       <<custMsgObj.ldquoStr>><<pronounWord>><<custMsgObj.rdquoStr>>
       like that.<./parser> ";
   }
   wrongReflexive(actor, typ, pronounWord) {
       "<.parser><<custMsgObj.TheStoryStr>>
       does<<custMsgObj.ntAbbr>> understand what the word
       <<custMsgObj.ldquoStr>><<pronounWord>><<custMsgObj.rdquoStr>>
       refers to.<./parser> ";
   }
   noMatchForPossessive(actor, owner, txt) {
       "<.parser>\^<<owner.nameDoes>>
       not <<custMsgObj.appearStr>> to have any such thing.<./parser> ";
   }
   noMatchForPluralPossessive(actor, txt) {
       "<.parser>\^They <<tSel('do', 'did')>> not
       <<custMsgObj.appearStr>> to have any such
       thing.<./parser> ";
   }
   noMatchForLocation(actor, loc, txt) {
       "<.parser>\^<<actor.nameSeesNo>>
       <<loc.childInName(txt)>>.<./parser> ";
   }
   nothingInLocation(actor, loc) {
       "<.parser>\^<<actor.nameSees>>
       <<loc.childInName('nothing unusual')>>.<./parser> ";
   }
   noMatchDisambig(actor, origPhrase, disambigResponse) {
       "<.parser>That
       was not
       one of the choices. ";
   }
   emptyNounPhrase(actor) {
       "<.parser>You seem to have left out some words.<./parser> ";
   }
   zeroQuantity(actor, txt) {
       "<.parser>\^<<actor.theName>> <<actor.verbCant>> do that to zero of
       something.<./parser> ";
   }
   insufficientQuantity(actor, txt, matchList, requiredNum) {
       "<.parser>\^<<actor.nameDoes>><<custMsgObj.ntAbbr>> see that many
       <<txt>> <<tSel('here', 'there')>>.<./parser> ";
   }
   uniqueObjectRequired(actor, txt, matchList) {
       "<.parser>You <<custMsgObj.cantStr>> use multiple
       objects there.<./parser> ";
   }
   singleObjectRequired(actor, txt) {
       "<.parser>Multiple objects are<<custMsgObj.ntAbbr>> allowed with that
       command.<./parser> ";
   }
   disambigOrdinalOutOfRange(actor, ordinalWord, originalText) {
       "<.parser>There <<custMsgObj.wereNotStr>> that many choices. ";
   }
   askDisambig(actor, originalText, matchList, fullMatchList,
               requiredNum, askingAgain, dist)
   {
       reportQuestion('');
       if (!askingAgain)
           "<.parser>";
       if (requiredNum == 1) {
           if (askingAgain)
               "Which did you mean,
               <<askDisambigList(matchList, fullMatchList, nil, dist)>>?";
           else
               "Which <<originalText>> do you mean,
               <<askDisambigList(matchList, fullMatchList, nil, dist)>>?";
       }
       else {
           if (askingAgain)
               "Which <<spellInt(requiredNum)>> (of
               <<askDisambigList(matchList, fullMatchList, true, dist)>>)
               did you mean?";
           else
               "Which <<spellInt(requiredNum)>>
               (of <<askDisambigList(matchList, fullMatchList,
                                     true, dist)>>) do you mean?";
       }
       "<./parser> ";
   }
   ambiguousNounPhrase(actor, originalText, matchList, fullMatchList) {
       "<.parser><<custMsgObj.TheStoryStr>> does<<custMsgObj.ntAbbr>> know which
       <<originalText>> you mean.<./parser> ";
   }
   missingActor(actor) {
       "<.parser>You must be more specific about <<
       whomPronoun>> you want<<tSel('', 'ed')>> to address.<./parser> ";
   }
   singleActorRequired(actor) {
       "<.parser>You can only address one person at a time.<./parser> ";
   }
   cannotChangeActor() {
       "<.parser>You <<custMsgObj.cannotStr>> address more than one
       character on a single command line in
       <<custMsgObj.thisStoryStr>>.<./parser> ";
   }
   askUnknownWord(actor, txt) {
       "<.parser>The word
       <<custMsgObj.ldquoStr>><<txt>><<custMsgObj.rdquoStr>>
       is<<custMsgObj._not>> necessary in
       <<custMsgObj.thisStoryStr>>.<./parser> ";
       oopsNote();
   }
   wordIsUnknown(actor, txt) {
       "<.parser><<custMsgObj.TheStoryStr>> does<<custMsgObj.ntAbbr>> understand that
       command.<./parser> ";
   }
   refuseCommandBusy(targetActor, issuingActor) {
       "\^<<targetActor.nameIs>> busy. ";
   }
   cannotAddressMultiple(actor) {
       "<.parser>\^<<actor.theName>> <<actor.verbCannot>> address
       multiple people at once.<./parser> ";
   }
   explainCancelCommandLine() {
   }
;

modify npcMessages // superclass = playerMessages
   commandNotHeard(actor) {
       "\^<<actor.nameDoes>><<custMsgObj._not>> respond. ";
   }
   noMatchCannotSee(actor, txt)
       { "\^<<actor.nameSees>> no <<txt>>. "; }
   noMatchNotAware(actor, txt)
       { "\^<<actor.nameIsNot>> aware of any <<txt>>. "; }
   noMatchForAll(actor) {
       "<.parser>\^<<actor.nameDoes>><<custMsgObj.ntAbbr>> see anything
       suitable.<./parser> ";
   }
   noMatchForAllBut(actor) {
       "<.parser>\^<<actor.nameSeesNo>>thing
       else.<./parser> ";
   }
   insufficientQuantity(actor, txt, matchList, requiredNum) {
       "<.parser>\^<<actor.nameDoes>><<custMsgObj.ntAbbr>> see that many
        <<txt>>.<./parser> ";
   }
   ambiguousNounPhrase(actor, originalText, matchList, fullMatchList) {
       "<.parser>\^<<actor.nameDoes>><<custMsgObj.ntAbbr>> know which
       <<originalText>> you mean<<tSel('', 't')>>.<./parser> ";
   }
   askMissingObject(actor, action, which) {
       reportQuestion('<.parser>\^' + action.whatObj(which)
                      + ' do you want ' + actor.theNameObj + ' to '
                      + action.getQuestionInf(which) + '?<./parser> ');
   }
   missingObject(actor, action, which) {
       "<.parser>You must be more specific
       about <<action.whatObj(which)>> you want <<actor.theNameObj>> to
       <<action.getQuestionInf(which)>>.<./parser> ";
   }
   missingLiteral(actor, action, which) {
       "<.parser>You must be more specific about <<action.whatObj(which)>>
       you want <<actor.theNameObj>> to <<action.getQuestionInf(which)>>.
       For example: <<actor.theName>>, <<action.getQuestionInf(which)>>
       <<custMsgObj.ldquoStr>>something<<custMsgObj.rdquoStr>>.<./parser> ";
   }
;

// This default implementation simply doesn't report deferred errors at
// all.

modify npcDeferredMessages // superclass = object
;

modify npcMessagesDirect // superclass = npcMessages
   noMatchCannotSee(actor, txt) {
       "\^<<actor.nameVerb('look')>> around.
       <<custMsgObj.ldquoStr>>I
       <<libGlobal.useContractions == never ? 'do not'
         : 'don' + custMsgObj.rsquoPlainStr + 't'>>
       see any <<txt>>.<<custMsgObj.rdquoStr>> ";
   }
   noMatchNotAware(actor, txt) {
       "<<custMsgObj.ldquoStr>><<libGlobal.useContractions == never ?
         'I am' : 'I' + custMsgObj.rsquoPlainStr + 'm'>> not aware of any
       <<txt>>,<<custMsgObj.rdquoStr>> <<actor.nameSays>>. ";
   }
   noMatchForAll(actor) {
       "\^<<actor.nameSays>>, <<custMsgObj.ldquoStr>>I
       <<libGlobal.useContractions == never ? 'do not'
         : 'don' + custMsgObj.rsquoPlainStr + 't'>>
       see anything suitable.<<custMsgObj.rdquoStr>> ";
   }
   noMatchForAllBut(actor) {
       "\^<<actor.nameSays>>, <<custMsgObj.ldquoStr>>I ";
       if (!libGlobal.preferCasual)
         "see no";
       else
         "<<libGlobal.useContractions == never ? 'do not'
           : 'don' + custMsgObj.rsquoPlainStr + 't'>> see any";
       "thing else here.<<custMsgObj.rdquoStr>> ";
   }
   zeroQuantity(actor, txt) {
       "\^<<actor.nameSays>>,
       <<custMsgObj.ldquoStr>>I
       <<libGlobal.useContractions == never ? 'cannot'
         : 'can' + custMsgObj.rsquoPlainStr + 't'>>
       do that to zero of
       something.<<custMsgObj.rdquoStr>> ";
   }
   insufficientQuantity(actor, txt, matchList, requiredNum) {
       "\^<<actor.nameSays>>,
       <<custMsgObj.ldquoStr>>I
       <<libGlobal.useContractions == never ? 'do not'
         : 'don' + custMsgObj.rsquoPlainStr + 't'>>
       see that many <<txt>> here.<<custMsgObj.rdquoStr>> ";
   }
   uniqueObjectRequired(actor, txt, matchList) {
       "\^<<actor.nameSays>>,
       <<custMsgObj.ldquoStr>>I
       <<libGlobal.useContractions == never ? 'cannot'
         : 'can' + custMsgObj.rsquoPlainStr + 't'>>
       use multiple objects like that.<<custMsgObj.rdquoStr>> ";
   }
   singleObjectRequired(actor, txt) {
       "\^<<actor.nameSays>>,
       <<custMsgObj.ldquoStr>>I
       <<libGlobal.useContractions == never ? 'cannot'
         : 'can' + custMsgObj.rsquoPlainStr + 't'>>
       use multiple objects like that.<<custMsgObj.rdquoStr>> ";
   }
   noMatchDisambig(actor, origPhrase, disambigResponse) {
       "\^<<actor.nameSays>>,
       <<custMsgObj.ldquoStr>>That was<<custMsgObj._not>>
       one of the choices. ";
   }
   disambigOrdinalOutOfRange(actor, ordinalWord, originalText) {
       "\^<<actor.nameSays>>,
       <<custMsgObj.ldquoStr>>There
       <<libGlobal.useContractions == never ? 'were not'
         : 'weren' + custMsgObj.rsquoPlainStr + 't'>>
       that many choices. ";
   }
   askDisambig(actor, originalText, matchList, fullMatchList,
               requiredNum, askingAgain, dist)
   {
       reportQuestion('');
       if (requiredNum == 1) {
           if (!askingAgain)
               "\^<<actor.nameVerb('ask')>>, <<custMsgObj.ldquoStr>>";
           "Which <<originalText>> do you mean, <<
           askDisambigList(matchList, fullMatchList, nil, dist)>>?<<custMsgObj.rdquoStr>> ";
       }
       else {
           if (!askingAgain)
               "\^<<actor.nameVerb('ask')>>, <<custMsgObj.ldquoStr>>";
           "Which <<spellInt(requiredNum)>> (of <<
           askDisambigList(matchList, fullMatchList, true, dist)>>)
           do you mean?<<custMsgObj.rdquoStr>> ";
       }
   }
   ambiguousNounPhrase(actor, originalText, matchList, fullMatchList) {
       "\^<<actor.nameSays>>,
       <<custMsgObj.ldquoStr>>I
       <<libGlobal.useContractions == never ? 'do not'
         : 'don' + custMsgObj.rsquoPlainStr + 't'>>
       know which
       <<originalText>> you mean.<<custMsgObj.rdquoStr>> ";
   }
   askMissingObject(actor, action, which) {
       reportQuestion('\^' + actor.nameSays
                      + ', ' + custMsgObj.ldquoStr + '\^'
                      + action.whatObj(which)
                      + ' do you want me to '
                      + action.getQuestionInf(which)
                      + '?' + custMsgObj.rdquoStr + ' ');
   }
   missingObject(actor, action, which) {
       "\^<<actor.nameSays>>,
       <<custMsgObj.ldquoStr>>I
       <<libGlobal.useContractions == never ? 'do not'
         : 'don' + custMsgObj.rsquoPlainStr + 't'>>
       know <<action.whatObj(which)>> you want me to
       <<action.getQuestionInf(which)>>.<<custMsgObj.rdquoStr>> ";
   }
   missingLiteral(actor, action, which) {
       missingObject(actor, action, which);
   }
   askUnknownWord(actor, txt) {
       "\^<<actor.nameSays>>,
       <<custMsgObj.ldquoStr>>I
       <<libGlobal.useContractions == never ? 'do not'
         : 'don' + custMsgObj.rsquoPlainStr + 't'>>
       know the word
       <<custMsgObj.lsquoPlainStr>><<txt>><<custMsgObj.rsquoPlainStr
       >>.<<custMsgObj.rdquoStr>> ";
   }
   wordIsUnknown(actor, txt) {
       "\^<<actor.nameSays>>,
       <<custMsgObj.ldquoStr>>You used a word I
       <<libGlobal.useContractions == never ? 'do not'
         : 'don' + custMsgObj.rsquoPlainStr + 't'>>
       know.<<custMsgObj.rdquoStr>> ";
   }
;

modify npcDeferredMessagesDirect// superclass = npcDeferredMessages
   commandNotUnderstood(actor) {
       "\^<<actor.nameSays>>,
       <<custMsgObj.ldquoStr>>I
       <<libGlobal.useContractions == never ? 'did not'
         : 'didn' + custMsgObj.rsquoPlainStr + 't'>>
       understand what you
       meant.<<custMsgObj.rdquoStr>> ";
   }
   noMatchCannotSee(actor, txt) {
       "\^<<actor.nameSays>>, <<custMsgObj.ldquoStr>>I
       <<libGlobal.useContractions == never ? 'did not'
         : 'didn' + custMsgObj.rsquoPlainStr + 't'>>
       see any <<txt>>.<<custMsgObj.rdquoStr>> ";
   }
   noMatchNotAware(actor, txt) {
       "\^<<actor.nameSays>>,
       <<custMsgObj.ldquoStr>><<libGlobal.useContractions == never
         ? 'I am' : 'I' + custMsgObj.rsquoPlainStr + 'm'>>
       not aware of any <<txt>>.<<custMsgObj.rdquoStr>> ";
   }
   noMatchForAll(actor) {
       "\^<<actor.nameSays>>, <<custMsgObj.ldquoStr>>I
       <<libGlobal.useContractions == never ? 'did not'
         : 'didn' + custMsgObj.rsquoPlainStr + 't'>>
       see anything suitable.<<custMsgObj.rdquoStr>> ";
   }
   noMatchForAllBut(actor) {
       "\^<<actor.nameSays>>,
       <<custMsgObj.ldquoStr>>I
       <<libGlobal.useContractions == never ? 'did not'
         : 'didn' + custMsgObj.rsquoPlainStr + 't'>>
       see what you
       meant.<<custMsgObj.rdquoStr>> ";
   }
   emptyNounPhrase(actor) {
       "\^<<actor.nameSays>>,
       <<custMsgObj.ldquoStr>>You left some words
       out.<<custMsgObj.rdquoStr>> ";
   }
   zeroQuantity(actor, txt) {
       "\^<<actor.nameSays>>,
       <<custMsgObj.ldquoStr>>I
       <<libGlobal.useContractions == never ? 'did not'
         : 'didn' + custMsgObj.rsquoPlainStr + 't'>>
       understand what you
       meant.<<custMsgObj.rdquoStr>> ";
   }
   insufficientQuantity(actor, txt, matchList, requiredNum) {
       "\^<<actor.nameSays>>,
       <<custMsgObj.ldquoStr>>I
       <<libGlobal.useContractions == never ? 'did not'
         : 'didn' + custMsgObj.rsquoPlainStr + 't'>>
       see enough
       <<txt>>.<<custMsgObj.rdquoStr>> ";
   }
   uniqueObjectRequired(actor, txt, matchList) {
       "\^<<actor.nameSays>>,
       <<custMsgObj.ldquoStr>>I
       <<libGlobal.useContractions == never ? 'did not'
         : 'didn' + custMsgObj.rsquoPlainStr + 't'>>
       understand what you
       meant.<<custMsgObj.rdquoStr>> ";
   }
   singleObjectRequired(actor, txt) {
       "\^<<actor.nameSays>>,
       <<custMsgObj.ldquoStr>>I
       <<libGlobal.useContractions == never ? 'did not'
         : 'didn' + custMsgObj.rsquoPlainStr + 't'>>
       understand what you
       meant.<<custMsgObj.rdquoStr>> ";
   }
   ambiguousNounPhrase(actor, originalText, matchList, fullMatchList) {
       "\^<<actor.nameSays>>,
       <<custMsgObj.ldquoStr>>I
       <<libGlobal.useContractions == never ? 'could not'
         : 'couldn' + custMsgObj.rsquoPlainStr + 't'>>
       tell which <<originalText>>
       you meant.<<custMsgObj.rdquoStr>> ";
   }
   askMissingObject(actor, action, which) {
       local didntStr;
       if (libGlobal.useContractions == never)
         didntStr = 'did not';
       else
         didntStr = 'didn' + custMsgObj.rsquoPlainStr + 't';
       reportQuestion('\^' + actor.nameSays
                      + ', ' + custMsgObj.ldquoStr
                      + 'I ' + didntStr + ' know '
                      + action.whatObj(which) + ' you wanted me to '
                      + action.getQuestionInf(which)
                      + '.' + custMsgObj.rdquoStr + ' ');
   }
   wordIsUnknown(actor, txt) {
       "\^<<actor.nameSays>>,
       <<custMsgObj.ldquoStr>>You used a word I
       <<libGlobal.useContractions == never ? 'do not'
         : 'don' + custMsgObj.rsquoPlainStr + 't'>>
       know.<<custMsgObj.rdquoStr>> ";
   }
;

modify playerActionMessages // superclass = MessageHelper
   cannotDoThatMsg = '{You/he} {can\'t} do that. '
   mustBeHoldingMsg(obj) {
       gMessageParams(obj);
       return '{You_would_have_to} be holding {the obj/him}
           to do that. ';
   }
   tooDarkMsg = 'It' + custMsgObj.sOrWasStr + ' too dark to do that. '
   mustBeVisibleMsg(obj) {
       gMessageParams(obj);
       return '{You/he} {cannot} see {that obj/him}. ';
   }
   heardButNotSeenMsg(obj) {
       gMessageParams(obj);
       return '{You/he} {can} hear {an obj/him}, but {you/he}
                {can\'t} see {it obj/him}. ';
   }
   smelledButNotSeenMsg(obj) {
       gMessageParams(obj);
       return '{You/he} {can} smell {an obj/him}, but {you/he}
               {can\'t} see {it obj/him}. ';
   }
   cannotHearMsg(obj) {
       gMessageParams(obj);
       return '{You/he} {cannot} hear {that obj/him}. ';
   }
   cannotSmellMsg(obj) {
       gMessageParams(obj);
       return '{You/he} {cannot} smell {that obj/him}. ';
   }
   cannotTasteMsg(obj) {
       gMessageParams(obj);
       return '{You/he} {cannot} taste {that obj/him}. ';
   }
   cannotBeWearingMsg(obj) {
       gMessageParams(obj);
       return '{You_would_have_to} take off {the obj/him} before
           {you_could} do that. ';
   }
   mustBeEmptyMsg(obj) {
       gMessageParams(obj);
       return '{You_would_have_to} take everything out of
           {the obj/him} before {you_could} do that. ';
   }
   mustBeOpenMsg(obj) {
       gMessageParams(obj);
       return '{You_would_have_to} open {the obj/him} before
           {you_could} do that. ';
   }
   mustBeClosedMsg(obj) {
       gMessageParams(obj);
       return '{You_would_have_to} close {the obj/him} before
           {you_could} do that. ';
   }
   mustBeUnlockedMsg(obj) {
       gMessageParams(obj);
       return '{You_would_have_to} unlock {the obj/him} before
           {you_could} do that. ';
   }
   noKeyNeededMsg = '{The dobj/he} {does}{_not} ' +
           custMsgObj.appearStr + ' to take a key. '
   mustBeStandingMsg =
           '{You_would_have_to} stand up before
           {you_could} do that. '
   mustSitOnMsg(obj) {
       gMessageParams(obj);
       return '{You_would_have_to} sit {in obj} first. ';
   }
   mustLieOnMsg(obj) {
       gMessageParams(obj);
       return '{You_would_have_to} lie {in obj} first. ';
   }
   mustGetOnMsg(obj) {
       gMessageParams(obj);
       return '{You_would_have_to} get {in obj} first. ';
   }
   mustBeInMsg(obj, loc) {
       gMessageParams(obj, loc);
       return '{You_would_have_to} be {in loc} before
           {you_could} do that. ';
   }
   mustBeCarryingMsg(obj, actor) {
       // Note that gActor.itCould actually fixes a bug in TADS 3.0.9
       // whereby a third-person Actor's name could be mentioned in both
       // the subject and predicate.
       gMessageParams(obj, actor);
       return '{You_would_have_to} be holding {the obj/him} before
           {you_could} do that. ';
   }
   decorationNotImportantMsg(obj) {
       gMessageParams(obj);
       return '{The obj/he} {is}{n\'t} important. ';
   }
   unthingNotHereMsg(obj) {
       gMessageParams(obj);
       return '{You/he} {does}{n\'t} see {that obj/him} {|t}here. ';
   }
   tooDistantMsg(obj) {
       gMessageParams(obj);
       return '{The obj/he} {is} too far away. ';
   }
   notWithIntangibleMsg(obj) {
       gMessageParams(obj);
       return '{You/he} {can\'t} do that to {an obj/him}. ';
   }
   notWithVaporousMsg(obj) {
       gMessageParams(obj);
       return '{You/he} {can\'t} do that to {an obj/him}. ';
   }
   lookInVaporousMsg(obj) {
       gMessageParams(obj);
       return '{You/he} just {sees} {the obj/him}. ';
   }
   cannotReachObjectMsg(obj) {
       gMessageParams(obj);
       return '{You/he} {cannot} reach {the obj/him}. ';
   }
   cannotReachThroughMsg(obj, loc) {
       gMessageParams(obj, loc);
       return '{You/he} {cannot} reach {the obj/him} through '
              + '{the loc/him}. ';
   }
   thingDescMsg(obj) {
       gMessageParams(obj);
       return '{You_see_no}thing unusual about '
              + '{it obj/him}. ';
   }
   thingSoundDescMsg(obj) {
       local hearNo;
       // As a fail-safe, if gActor is nil, return an empty string.
       // This will prevent the game from crashing in this unlikely
       // scenario.
       if (!gActor)
         return '';
       if (!libGlobal.preferCasual)
           hearNo = 'hear' + gActor.verbEndingSD + ' no';
       else
           hearNo = gActor.verbToDo + custMsgObj.ntAbbr + ' hear any';
       return '{You/he} ' + hearNo + 'thing out of the ordinary. ';
   }
   thingSmellDescMsg(obj) {
       local smellNo;
       // As a fail-safe, if gActor is nil, return an empty string.
       // This will prevent the game from crashing in this unlikely
       // scenario.
       if (!gActor)
         return '';
       if (!libGlobal.preferCasual)
           smellNo = 'smell' + gActor.verbEndingSEd + ' no';
       else
           smellNo = gActor.verbToDo + custMsgObj.ntAbbr + ' smell any';
       return '{You/he} ' + smellNo + 'thing out of the ordinary. ';
   }
   npcDescMsg(npc) {
       gMessageParams(npc);
       return '{You_see_no}thing unusual about '
              + '{the npc/him}. ';
   }
   nothingInsideMsg =
       'There' + custMsgObj.sOrWasStr + ' nothing unusual in {the dobj/him}. '
   nothingUnderMsg =
       '{You_see_no}thing unusual under {the dobj/him}. '
   nothingBehindMsg =
       '{You_see_no}thing unusual behind {the dobj/him}. '
   nothingThroughMsg {
       if (!libGlobal.preferCasual)
           return '{You/he} {can} see nothing through {the dobj/him}. ';
       else
           return '{You/he} {can\'t} see anything through {the dobj/him}. ';
   }
   cannotLookBehindMsg = '{You/he} {can\'t} look behind {the dobj/him}. '
   cannotLookUnderMsg = '{You/he} {can\'t} look under {the dobj/him}. '
   cannotLookThroughMsg = '{You/he} {can\'t} see through {the dobj/him}. '
   nothingThroughPassageMsg = '{You/he} {can\'t} see much through
       {the dobj/him} from {|t}here. '
   nothingBeyondDoorMsg = 'Opening {the dobj/him} reveal{s|ed} nothing
       unusual. '
   nothingToSmellMsg {
       local smellNo;
       // As a fail-safe, if gActor is nil, return an empty string.
       // This will prevent the game from crashing in this unlikely
       // scenario.
       if (!gActor)
         return '';
       if (!libGlobal.preferCasual)
           smellNo = 'smell' + gActor.verbEndingSEd + ' no';
       else
           smellNo = gActor.verbToDo + custMsgObj.ntAbbr + ' smell any';
       return '{You/he} ' + smellNo + 'thing out of the ordinary. ';
   }
   nothingToHearMsg {
       local hearNo;
       // As a fail-safe, if gActor is nil, return an empty string.
       // This will prevent the game from crashing in this unlikely
       // scenario.
       if (!gActor)
         return '';
       if (!libGlobal.preferCasual)
           hearNo = 'hear' + gActor.verbEndingSD + ' no';
       else
           hearNo = gActor.verbToDo + custMsgObj.ntAbbr + ' hear any';
       return '{You/he} ' + hearNo + 'thing out of the ordinary. ';
   }
   noiseSourceMsg(src) {
       return '{The dobj/he} seem{s/ed} to be coming from '
           + src.theNameObj + '. ';
   }
   odorSourceMsg(src) {
       return '{The dobj/he} seem{s/ed} to be coming from '
           + src.theNameObj + '. ';
   }
   notWearableMsg {
       return '{That_isn\'t dobj} something {you/he} {can} wear. ';
   }
   notDoffableMsg {
       return '{That_isn\'t dobj} something {you/he} {can} remove. ';
   }
   alreadyWearingMsg = '{You\'re} already wearing {it dobj/him}. '
   notWearingMsg = '{You\'re} not wearing {that dobj/him}. '
   okayWearMsg = 'Okay, {you\'re} now wearing {the dobj/him}. '
   okayDoffMsg = 'Okay, {you\'re} no longer wearing {the dobj/him}. '
   okayOpenMsg = 'Opened. '
   okayCloseMsg = 'Closed. '
   okayLockMsg = 'Locked. '
   okayUnlockMsg = 'Unlocked. '
   cannotDigMsg = '{You/he} {have} no reason to dig in {that dobj/him}. '
   cannotDigWithMsg =
       '{You_see_no} way to use {that iobj/him} as a shovel. '
   alreadyHoldingMsg () {
       return '{You_are} already carrying {the dobj/him}. ';
   }
   takingSelfMsg = '{You/he} {can\'t} take {yourself}. '
   notCarryingMsg = '{You\'re} not carrying {that dobj/him}. '
   droppingSelfMsg = '{You/he} {can\'t} drop {yourself}. '
   puttingSelfMsg = '{You/he} {can\'t} do that to {yourself}. '
   throwingSelfMsg = '{You/he} {can\'t} throw {yourself}. '
   alreadyPutInMsg = '{The dobj/he} {is} already in {the iobj/him}. '
   alreadyPutOnMsg = '{The dobj/he} {is} already on {the iobj/him}. '
   alreadyPutUnderMsg = '{The dobj/he} {is} already under {the iobj/him}. '
   alreadyPutBehindMsg = '{The dobj/he} {is} already behind {the iobj/him}. '
   cannotMoveFixtureMsg = '{The dobj/he} {cannot} be moved. '
   cannotTakeFixtureMsg = '{You/he} {can\'t} take {that dobj/him}. '
   cannotPutFixtureMsg = '{You/he} {can\'t} put {the dobj/him} anywhere. '
   cannotTakeImmovableMsg = '{You/he} {can\'t} take {that dobj/him}. '
   cannotMoveImmovableMsg = '{The dobj/he} {cannot} be moved. '
   cannotPutImmovableMsg = '{You/he} {can\'t} put {the dobj/him} anywhere. '
   cannotTakeHeavyMsg = '{The dobj/he} {is} too heavy. '
   cannotMoveHeavyMsg = '{The dobj/he} {is} too heavy. '
   cannotPutHeavyMsg = '{The dobj/he} {is} too heavy. '
   cannotMoveComponentMsg(loc) {
       return '{The dobj/he} {is} part of ' + loc.theNameObj + '. ';
   }
   cannotTakeComponentMsg(loc) {
       return '{You/he} {can\'t} have {that/him dobj}; '
           + '{it\'s dobj} part of ' + loc.theNameObj + '. ';
   }
   cannotPutComponentMsg(loc) {
       return '{You/he} {can\'t} put {that/him dobj} anywhere; '
           + '{it\'s dobj} part of ' + loc.theNameObj + '. ';
   }
   cannotTakePushableMsg = '{You/he} {can\'t} take {that/him dobj}, but
       {it actor/he} might {be|have been} able to push it somewhere. '
   cannotMovePushableMsg = 'It would'
       + custMsgObj.ntAbbr + ' {|have} accomplish{|ed} anything
       to move {the dobj/him} around aimlessly, but {it actor/he}
       might {be|have been} able to push {it dobj/him} in a specific
       direction. '
   cannotPutPushableMsg = '{You/he} {can\'t} put {that/him dobj} anywhere,
       but {it actor/he} might {be|have been} able to push it somewhere. '
   cannotTakeLocationMsg = '{You/he} {can\'t} take {that/him dobj}
       while {you\'re} occupying {it/him dobj}. '
   okayTakeMsg = 'Taken. '
   okayDropMsg = 'Dropped. '
   droppingObjMsg(dropobj) {
       gMessageParams(dropobj);
       return '{You/he} drop{s/ped} {the dropobj/him}. ';
   }
   floorlessDropMsg(dropobj) {
       gMessageParams(dropobj);
       return '{It dropobj/he} {fall[s]|fell} out of sight below. ';
   }
   okayPutInMsg = 'Done. '
   okayPutOnMsg = 'Done. '
   okayPutUnderMsg = 'Done. '
   okayPutBehindMsg = 'Done. '
   cannotTakeActorMsg = '{The dobj/he} {won\'t} let {you/him} do that. '
   cannotMoveActorMsg = '{The dobj/he} {won\'t} let {you/him} do that. '
   cannotPutActorMsg = '{The dobj/he} {won\'t} let {you/him} do that. '
   cannotTasteActorMsg = '{The dobj/he} {won\'t} let {you/him} do that. '
   cannotTakePersonMsg =
       '{The dobj/he} probably would{n\'t} {|have} like{|d} that. '
   cannotMovePersonMsg =
       '{The dobj/he} probably would{n\'t} {|have} like{|d} that. '
   cannotPutPersonMsg =
       '{The dobj/he} probably would{n\'t} {|have} like{|d} that. '
   cannotTastePersonMsg =
       '{The dobj/he} probably would{n\'t} {|have} like{|d} that. '
   cannotMoveThroughMsg(obj, obs) {
       gMessageParams(obj, obs);
       return '{You/he} {can\'t} move {that obj/him} through '
              + '{the obs/him}. ';
   }
   cannotMoveThroughContainerMsg(obj, cont) {
       gMessageParams(obj, cont);
       return '{You/he} {can\'t} move {that obj/him} through '
              + '{the cont/him}. ';
   }
   cannotMoveThroughClosedMsg(obj, cont) {
       gMessageParams(cont);
       return '{You/he} {can\'t} do that because {the cont/he} {is} '
              + 'closed. ';
   }
   cannotFitIntoOpeningMsg(obj, cont) {
       gMessageParams(obj, cont);
       return '{You/he} {can\'t} do that because {the obj/he} {is}
               too big to put into {the cont/him}. ';
   }
   cannotFitOutOfOpeningMsg(obj, cont) {
       gMessageParams(obj, cont);
       return '{You/he} {can\'t} do that because {the obj/he} {is}
               too big to take out of {the cont/him}. ';
   }
   cannotTouchThroughContainerMsg(obj, cont) {
       gMessageParams(obj, cont);
       return '{The obj/he} {can\'t} reach anything through '
              + '{the cont/him}. ';
   }
   cannotTouchThroughClosedMsg(obj, cont) {
       gMessageParams(obj, cont);
       return '{The obj/he} {can\'t} do that because
              {the cont/he} {is} closed. ';
   }
   cannotReachIntoOpeningMsg(obj, cont) {
       gMessageParams(obj, cont);
       return '{The obj/he} {can\'t} fit {its/her} hand into '
              + '{the cont/him}. ';
   }
   cannotReachOutOfOpeningMsg(obj, cont) {
       gMessageParams(obj, cont);
       return '{The obj/he} {can\'t} fit {its/her} hand through
              {the cont/him}. ';
   }
   tooLargeForActorMsg(obj) {
       gMessageParams(obj);
       return '{The obj/he} {is} too large for {you/him} to hold. ';
   }
   handsTooFullForMsg(obj) {
       return '{Your} hands {are|were} too full to hold '
              + obj.theNameObj + '. ';
   }
   becomingTooLargeForActorMsg(obj) {
       gMessageParams(obj);
       return '{You/he} {cannot} do that because {the obj/he}
               would {|have} become too large for {you/him} to hold. ';
   }
   handsBecomingTooFullForMsg(obj) {
       gMessageParams(obj);
       return '{You/he} {cannot} do that because {its/her} hands
           would {|have} become too full to hold {the obj/him}. ';
   }
   tooHeavyForActorMsg(obj) {
       gMessageParams(obj);
       return '{The obj/he} {is} too heavy for {you/him} to pick up. ';
   }
   totalTooHeavyForMsg(obj) {
       local youWill;
       // As a fail-safe, if gActor is nil, return an empty string.
       // This will prevent the game from crashing in this unlikely
       // scenario.
       if (!gActor)
         return '';
       gMessageParams(obj);
       if (  (libGlobal.useContractions == usually ||
              libGlobal.useContractions == always)
           && gActor.referralPerson != ThirdPerson) {
         // "I'll", "you'll", "we'll"
         youWill = gActor.theName + custMsgObj.rsquoPlainStr + 'll';
       }
       else
         youWill = gActor.theName + ' ' + gActor.verbWill;
       return '{The obj/he} {is} too heavy; ' + youWill + ' have to put
           something else down first. ';
   }
   tooLargeForContainerMsg(obj, cont) {
       gMessageParams(obj, cont);
       return '{The obj/he} {is} too large for {the cont/him}. ';
   }
   tooLargeForUndersideMsg(obj, cont) {
       gMessageParams(obj, cont);
       return '{The obj/he} {is} too large to put under {the cont/him}. ';
   }
   tooLargeForRearMsg(obj, cont) {
       gMessageParams(obj, cont);
       return '{The obj/he} {is} too large to put behind {the cont/him}. ';
   }
   containerTooFullMsg(obj, cont) {
       gMessageParams(obj, cont);
       return '{The cont/he} {is} already too full to hold {the obj/him}. ';
   }
   surfaceTooFullMsg(obj, cont) {
       gMessageParams(obj, cont);
       return 'There' + custMsgObj.sOrWasStr + ' no room for {the obj/him} on '
              + '{the cont/him}. ';
   }
   undersideTooFullMsg(obj, cont) {
       gMessageParams(obj, cont);
       return 'There' + custMsgObj.sOrWasStr + ' no room for {the obj/him} under '
              + '{the cont/him}. ';
   }
   rearTooFullMsg(obj, cont) {
       gMessageParams(obj, cont);
       return 'There' + custMsgObj.sOrWasStr + ' no room for {the obj/him} behind '
              + '{the cont/him}. ';
   }
   becomingTooLargeForContainerMsg(obj, cont) {
       gMessageParams(obj, cont);
       return '{You/he} {cannot} do that because it would {make|have made}
           {the obj/him} too large for {the cont/him}. ';
   }
   containerBecomingTooFullMsg(obj, cont) {
       gMessageParams(obj, cont);
       return '{You/he} {cannot} do that because {the obj/he}
           would no longer {|have} fit{|ted} in {the cont/him}. ';
   }
   notAContainerMsg = '{You/he} {can\'t} put anything in {the iobj/him}. '
   notASurfaceMsg = 'There' + custMsgObj.sOrWasStr + ' no good surface on {the iobj/him}. '
   cannotPutUnderMsg =
       '{You/he} {can\'t} put anything under {that iobj/him}. '
   cannotPutBehindMsg = '{You/he} {can\'t} put anything
       behind {the iobj/him}. '
   cannotPutInSelfMsg = '{You/he} {can\'t} put {the dobj/him} in {itself}. '
   cannotPutOnSelfMsg = '{You/he} {can\'t} put {the dobj/him} on {itself}. '
   cannotPutUnderSelfMsg = '{You/he} {can\'t} put {the dobj/him} under
       {itself}. '
   cannotPutBehindSelfMsg = '{You/he} {can\'t} put {the dobj/him} behind
       {itself}. '
   cannotPutInRestrictedMsg =
       '{You/he} {can\'t} put {that dobj/him} in {the iobj/him}. '
   cannotPutOnRestrictedMsg =
       '{You/he} {can\'t} put {that dobj/him} on {the iobj/him}. '
   cannotPutUnderRestrictedMsg =
       '{You/he} {can\'t} put {that dobj/him} under {the iobj/him}. '
   cannotPutBehindRestrictedMsg =
       '{You/he} {can\'t} put {that dobj/him} behind {the iobj/him}. '
   cannotReturnToDispenserMsg =
       '{You/he} {can\'t} put {a dobj/him} back in {the iobj/him}. '
   cannotPutInDispenserMsg =
       '{You/he} {can\'t} put {a dobj/him} in {the iobj/him}. '
   objNotForKeyringMsg = '{The dobj/he} {does}{n\'t} fit on {the iobj/him}. '
   keyNotOnKeyringMsg = '{The dobj/he} {is}{_not} attached to {the iobj/him}. '
   keyNotDetachableMsg = '{The dobj/he} {is}{n\'t} attached to anything. '
   takenAndMovedToKeyringMsg(keyring) {
       gMessageParams(keyring);
       return '{You/he} pick{s/ed} up {the dobj/him} and
           attach{es/ed actor} {it dobj/him} to {the keyring/him}. ';
   }
   movedKeyToKeyringMsg(keyring) {
       gMessageParams(keyring);
       return '{You/he} attach{es/ed} {the dobj/him} to {the keyring/him}. ';
   }
   movedKeysToKeyringMsg(keyring, keys) {
       gMessageParams(keyring);
       return '{You/he} attach{es/ed} {your/his} loose key'
           + (keys.length() > 1 ? 's' : '')
           + ' to {the keyring/him}. ';
   }
   circularlyInMsg(x, y) {
       gMessageParams(x, y);
       return '{You/he} {can\'t} do that while {the x/he} {is}
           in {the y/him}. ';
   }
   circularlyOnMsg(x, y) {
       gMessageParams(x, y);
       return '{You/he} {can\'t} do that while {the x/he} {is}
           on {the y/him}. ';
   }
   circularlyUnderMsg(x, y) {
       gMessageParams(x, y);
       return '{You/he} {can\'t} do that while {the x/he} {is}
           under {the y/him}. ';
   }
   circularlyBehindMsg(x, y) {
       gMessageParams(x, y);
       return '{You/he} {can\'t} do that while {the x/he} {is}
           behind {the y/him}. ';
   }
   takeFromNotInMsg = '{The dobj/he} {is}{n\'t} in {that iobj/him}. '
   takeFromNotOnMsg = '{The dobj/he} {is}{n\'t} on {that iobj/him}. '
   takeFromNotUnderMsg = '{The dobj/he} {is}{n\'t} under {that iobj/him}. '
   takeFromNotBehindMsg = '{The dobj/he} {is}{n\'t} behind {that iobj/him}. '
   takeFromNotInActorMsg = '{The iobj/he} {does}{n\'t} have {that dobj/him}. '
   willNotLetGoMsg(holder, obj) {
       gMessageParams(holder, obj);
       return '{The holder/he} {won\'t} let {you/him} have {that obj/him}. ';
   }
   whereToGoMsg () {
       return '\^' + custMsgObj.youllStr + ' have to say which way to go. ';
   }
   cannotGoThatWayMsg = '{You/he} {can\'t} go that way. '
   cannotGoThatWayInDarkMsg = 'It' + custMsgObj.sOrWasStr + ' too dark; {you/he} {can\'t} see
                            where {you\'re} going. '
   cannotGoBackMsg = '{You/he} {does}{n\'t} know how to return from {|t}here. '
   cannotDoFromHereMsg = '{You/he} {can\'t} do that from {|t}here. '
   cannotGoThroughClosedDoorMsg(door) {
       gMessageParams(door);
       return '{You/he} {can\'t} do that, because {the door/he} {is} '
              + 'closed. ';
   }
   invalidStagingContainerMsg(cont, dest) {
       gMessageParams(cont, dest);
       return '{You/he} {can\'t} do that while {the dest/he} {is}
               {in cont}. ';
   }
   invalidStagingContainerActorMsg(cont, dest) {
       gMessageParams(cont, dest);
       return '{You/he} {can\'t} do that while {the cont/he} {is}
           holding {the dest/him}. ';
   }
   invalidStagingLocationMsg(dest) {
       gMessageParams(dest);
       return '{You/he} {can\'t} get {in dest}. ';
   }
   nestedRoomTooHighMsg(obj) {
       gMessageParams(obj);
       return '{The obj/he} {is} too high to reach from {|t}here. ';
   }
   nestedRoomTooHighToExitMsg(obj) {
       return 'It' + custMsgObj.sOrWasStr + ' too long a drop to do that from {|t}here. ';
   }
   cannotDoFromMsg(obj) {
       gMessageParams(obj);
       return '{You/he} {can\'t} do that from {the obj/him}. ';
   }
   vehicleCannotDoFromMsg(obj) {
       local loc = obj.location;
       gMessageParams(obj, loc);
       return '{You/he} {can\'t} do that while {the obj/he} {is} {in loc}. ';
   }
   cannotGoThatWayInVehicleMsg(traveler) {
       gMessageParams(traveler);
       return '{You/he} {can\'t} do that {in traveler}. ';
   }
   cannotPushObjectThatWayMsg(obj) {
       gMessageParams(obj);
       return '{You/he} {can\'t} go that way pushing {the obj/him}. ';
   }
   cannotPushObjectNestedMsg(obj) {
       gMessageParams(obj);
       return '{You/he} {can\'t} push {the obj/him} there. ';
   }
   cannotEnterExitOnlyMsg(obj) {
       gMessageParams(obj);
       return '{You/he} {can\'t} enter {the obj/him} from {|t}here. ';
   }
   mustOpenDoorMsg(obj) {
       gMessageParams(obj);
       return '{You_would_have_to} open {the obj/him} first. ';
   }
   doorClosesBehindMsg(obj) {
       gMessageParams(obj);
       return '<.p>After {you/he} {goes} through {the obj/him}, {it/he}
               close{s/d} behind {it actor/him}. ';
   }
   stairwayNotUpMsg = '{The dobj/he} only {goes} down from {|t}here. '
   stairwayNotDownMsg = '{The dobj/he} only {goes} up from {|t}here. '
   timePassesMsg = 'Time pass{es|ed}... '
   sayHelloMsg = (addressingNoOneMsg)
   sayGoodbyeMsg = (addressingNoOneMsg)
   sayYesMsg = (addressingNoOneMsg)
   sayNoMsg = (addressingNoOneMsg)
   addressingNoOneMsg {
       // I am taking the liberty of fixing a bug in TADS 3.0.9, changing
       // {you/he} in the predicate to {it actor/he}, so that a third-person
       // actor's name will not be mentioned in both the subject and predicate.
       return '\^' + custMsgObj.youWillStr + ' have to be more specific about '
           + libMessages.whomPronoun + ' {it actor/he} want{s/ed} to talk to. ';
   }
   okayYellMsg = '{You/he} scream{s/ed} as loud as {it actor/he} {can}. '
   okayJumpMsg = '{You/he} jump{s/ed} a little, and land{s/ed} back where
       {it actor/he} {|had} started. '
   cannotJumpOverMsg = '{You/he} {can\'t} jump over {that dobj/him}. '
   cannotJumpOffMsg = '{You/he} {can\'t} jump off {that dobj/him}. '
   cannotJumpOffHereMsg = 'There' + custMsgObj.sOrWasStr + ' nowhere to jump from {|t}here. '
   cannotFindTopicMsg =
       '{You/he} {can\'t} seem to find that in {the dobj/him}. '
   refuseCommand(targetActor, issuingActor) {
       gMessageParams(targetActor, issuingActor);
       return '{The targetActor/he} refuse{s/ed} {your/his} request. ';
   }
   notAddressableMsg(obj) {
       gMessageParams(obj);
       return '{You/he} {cannot} talk to {that obj/him}. ';
   }
   noResponseFromMsg(other) {
       gMessageParams(other);
       return '{The other/he} {does}{_not} respond. ';
   }
   giveAlreadyHasMsg = '{The iobj/he} already {has} {that/him dobj}. '
   cannotTalkToSelf = 'Talking to {yourself/himself}
       {won\'t} accomplish anything. '
   cannotTalkToSelfMsg = 'Talking to {yourself/himself}
       {won\'t} accomplish anything. '
   cannotAskSelfMsg = 'Talking to {yourself/himself}
       {won\'t} accomplish anything. '
   cannotAskSelfForMsg = 'Talking to {yourself/himself}
       {won\'t} accomplish anything. '
   cannotTellSelfMsg = 'Talking to {yourself/himself}
       {won\'t} accomplish anything. '
   cannotGiveToSelfMsg = 'Giving {the dobj/him} to {yourself/himself}
       {won\'t} accomplish anything. '
   cannotGiveToItselfMsg = 'Giving {the dobj/him} to {itself}
       {won\'t} accomplish anything. '
   cannotShowToSelfMsg = 'Showing {the dobj/him} to {yourself/himself}
       {won\'t} accomplish anything. '
   cannotShowToItselfMsg = 'Showing {the dobj/him} to {itself}
       {won\'t} accomplish anything. '
   cannotGiveToMsg = '{You/he} {cannot} give anything to {an iobj/him}. '
   cannotShowToMsg = '{You/he} {cannot} show anything to {an iobj/him}. '
   notInterestedMsg(actor) {
       return '\^' + actor.nameDoes + custMsgObj._not + ' '
           + custMsgObj.appearStr + ' interested. ';
   }
   askVagueMsg = '<.parser>The story doesn' + custMsgObj.rsquoStr + 't
       understand that command. Please use ASK ACTOR ABOUT TOPIC
       (or just A TOPIC).<./parser> '
   tellVagueMsg = '<.parser>The story doesn' + custMsgObj.rsquoStr + 't
       understand that command. Please use TELL ACTOR ABOUT TOPIC
       (or just T TOPIC).<./parser> '
   objCannotHearActorMsg(obj) {
       return '\^' + obj.nameDoes
           + custMsgObj._not + ' ' + custMsgObj.appearStr
           + ' to hear {you/him}. ';
   }
   actorCannotSeeMsg(actor, obj) {
       return '\^' + actor.nameDoes + custMsgObj._not
           + ' ' + custMsgObj.appearStr
           + ' to be able to see ' + obj.theNameObj + '. ';
   }
   notFollowableMsg = '{You/he} {cannot} follow {that dobj/him}. '
   cannotFollowSelfMsg = '{You/he} {cannot} follow {yourself}. '
   followAlreadyHereMsg = '{The dobj/he} {is} right {|t}here. '
   followAlreadyHereInDarkMsg = '{The dobj/he} should {be|have been} right
       {|t}here, but {you/he} {can\'t} see {it dobj/him}. '
   followUnknownMsg = '{You\'re} not sure where {the dobj/he}
       {went|had gone} from {|t}here. '
   cannotFollowFromHereMsg(srcLoc) {
       return 'The last place {you/he} {saw|had seen} {the dobj/him} was '
           + srcLoc.getDestName(gActor, gActor.location) + '. ';
   }
   okayFollowInSightMsg(loc) {
       return '{You/he} follow{s/ed} {the dobj/him} '
           + loc.actorIntoName + '. ';
   }
   notAWeaponMsg = '{You/he} {can\'t} attack anything with {the iobj/him}. '
   uselessToAttackMsg = '{You/he} {cannot} attack {that dobj/him}. '
   pushNoEffectMsg = 'Pushing {the dobj/him} {has|had} no effect. '
   okayPushButtonMsg = '<q>Click.</q> '
   alreadyPushedMsg =
       '{It\'s dobj} already pushed as far as {it dobj/he} {will} go. '
   okayPushLeverMsg = '{You/he} push{es/ed} {the dobj/him} to
                    {its/her dobj} stop. '
   pullNoEffectMsg = 'Pulling {the dobj/him} {has|had} no effect. '
   alreadyPulledMsg =
       '{It\'s dobj} already pulled as far as {it dobj/he} {will} go. '
   okayPullLeverMsg = '{You/he} pull{s/ed} {the dobj/him} to
                    {its/her dobj} stop. '
   okayPullSpringLeverMsg = '{You/he} pull{s/ed} {the dobj/him}, which
       spr{ing[s]|ung} back to {its/her} starting position as soon as
       {you/he} let{[s]|} go of {it dobj/him}. '
   moveNoEffectMsg = 'Moving {the dobj/him} {has|had} no effect. '
   moveToNoEffectMsg = 'This would {|have} accomplish{|ed} nothing. '
   cannotPushTravelMsg = 'This would {|have} accomplish{|ed} nothing. '
   okayPushTravelMsg(obj) {
       return '<.p>{You/he} push{es/ed} ' + obj.theNameObj
           + ' into the area. ';
   }
   cannotMoveWithMsg =
       '{You/he} {cannot} move anything with {the iobj/him}. '
   cannotSetToMsg = '{You/he} {cannot} set {that dobj/him} to anything. '
   setToInvalidMsg {
       return '{The dobj/he} {has} no such setting. ';
       // I was going to do the following, but I think I prefer the
       // message as it originally stood.
       //return '{The dobj/he} ' + gDobj.hasNo + ' such setting. ';
   }
   okaySetToMsg(val)
       { return 'Okay, {the dobj/he} {is} now set to ' + val + '. '; }
   cannotTurnMsg = '{You/he} {cannot} turn {that dobj/him}. '
   mustSpecifyTurnToMsg() {
       return '\^' + custMsgObj.youWillStr + ' have to specify the setting to
              turn {it dobj/him} to. ';
   }
   cannotTurnWithMsg =
       '{You/he} {cannot} turn anything with {that iobj/him}. '
   turnToInvalidMsg {
       return '{The dobj/he} {has} no such setting. ';
       // I was going to do the following, but I think I prefer the
       // message as it originally stood.
       //return '{The dobj/he} ' + gDobj.hasNo + ' such setting. ';
   }
   okayTurnToMsg(val)
       { return 'Okay, {the dobj/he} {is} now set to ' + val + '. '; }
   alreadySwitchedOnMsg = '{The dobj/he} {is} already on. '
   alreadySwitchedOffMsg = '{The dobj/he} {is} already off. '
   okayTurnOnMsg = 'Okay, {the dobj/he} {is} now on. '
   okayTurnOffMsg = 'Okay, {the dobj/he} {is} now off. '
   flashlightOnButDarkMsg = '{You/he} turn{s/ed} on {the dobj/him}, but
       nothing seem{s|ed} to happen. '
   okayEatMsg = '{You/he} {eat[s]|ate} {the dobj/him}. '
   mustBeBurningMsg(obj) {
       return '{You_would_have_to} light ' + obj.theNameObj
           + ' before {you_could} do that. ';
   }
   matchNotLitMsg = '{The dobj/he} {is}{n\'t} lit. '
   okayBurnMatchMsg =
       '{You/he} str{ike[s]|uck} {the dobj/him}, igniting a small flame. '
   okayExtinguishMatchMsg = '{You/he} put{[s]|} out {the dobj/him}, which
       disappear{s/ed} into a cloud of ash. '
   candleOutOfFuelMsg =
       '{The dobj/he} {is} too burned down; {it/he} {cannot} be lit. '
   okayBurnCandleMsg = '{You/he} {light[s]|lit} {the dobj/him}. '
   candleNotLitMsg = '{The dobj/he} {is}{_not} lit. '
   okayExtinguishCandleMsg = 'Done. '
   cannotConsultMsg {
       return '{That_is_not dobj} something {you/he} {can} consult. ';
   }
   cannotTypeOnMsg = '{You/he} {cannot} type anything on {that dobj/him}. '
   cannotEnterOnMsg = '{You/he} {cannot} enter anything on {that dobj/him}. '
   cannotSwitchMsg = '{You/he} {cannot} switch {that dobj/him}. '
   cannotFlipMsg = '{You/he} {cannot} flip {that dobj/him}. '
   cannotTurnOnMsg {
       return '{That_isn\'t dobj} something {you/he} {can} turn on. ';
   }
   cannotTurnOffMsg {
       return '{That_isn\'t dobj} something {you/he} {can} turn off. ';
   }
   cannotLightMsg = '{You/he} {cannot} light {that dobj/him}. '
   cannotBurnMsg {
       return '{That_is_not dobj} something {you/he} {can} burn. ';
   }
   cannotBurnWithMsg =
       '{You/he} {cannot} burn anything with {that iobj/him}. '
   cannotBurnDobjWithMsg = '{You/he} {cannot} light {the dobj/him}
                         with {the iobj/him}. '
   alreadyBurningMsg = '{The dobj/he} {is} already burning. '
   cannotExtinguishMsg = '{You/he} {cannot} extinguish {that dobj/him}. '
   cannotPourMsg {
       return '{That_is_not dobj} something {you/he} {can} pour. ';
   }
   cannotPourIntoMsg =
       '{You/he} {cannot} pour anything into {that iobj/him}. '
   cannotPourOntoMsg =
       '{You/he} {cannot} pour anything onto {that iobj/him}. '
   cannotAttachMsg =
       '{You/he} {cannot} attach {that dobj/him} to anything. '
   cannotAttachToMsg =
       '{You/he} {cannot} attach anything to {that iobj/him}. '
   cannotAttachToSelfMsg =
       '{You/he} {cannot} attach {the dobj/him} to {itself}. '
   alreadyAttachedMsg =
       '{The dobj/he} {is} already attached to {the iobj/him}. '
   wrongAttachmentMsg =
       '{You/he} {can\'t} attach {that dobj/him} to {the iobj/him}. '
   wrongDetachmentMsg =
       '{You/he} {can\'t} detach {that dobj/him} from {the iobj/him}. '
   mustDetachMsg(obj) {
       // Note that gActor.itCould actually fixes a bug in TADS 3.0.9
       // whereby a third-person Actor's name could be mentioned in both
       // the subject and predicate.
       gMessageParams(obj);
       return '{You_would_have_to} detach {the obj/him} before
          {you_could} do that. ';
   }
   okayAttachToMsg = 'Done. '
   okayDetachFromMsg = 'Done. '
   cannotDetachMsg = '{You/he} {cannot} detach {that dobj/him}. '
   cannotDetachFromMsg =
       '{You/he} {cannot} detach anything from {that iobj/him}. '
   cannotDetachPermanentMsg =
       'There' + custMsgObj.sOrWasStr + ' no obvious way to detach {that dobj/him}. '
   notAttachedToMsg = '{The dobj/he} {is}{n\'t} attached to {that iobj/him}. '
   shouldNotBreakMsg =
       'Breaking {that dobj/him} would {|have} serve{|ed} no purpose. '
   cutNoEffectMsg = '{The iobj/he} {can\'t} seem to cut {the dobj/him}. '
   cannotCutWithMsg = '{You/he} {can\'t} cut anything with {the iobj/him}. '
   cannotClimbMsg {
       return '{That_is_not dobj} something {you/he} {can} climb. ';
   }
   cannotOpenMsg {
       return '{That_is_not dobj} something {you/he} {can} open. ';
   }
   cannotCloseMsg {
       return '{That_is_not dobj} something {you/he} {can} close. ';
   }
   alreadyOpenMsg = '{The dobj/he} {is} already open. '
   alreadyClosedMsg = '{The dobj/he} {is} already closed. '
   alreadyLockedMsg = '{The dobj/he} {is} already locked. '
   alreadyUnlockedMsg = '{The dobj/he} {is} already unlocked. '
   cannotLookInClosedMsg = '{The dobj/he} {is} closed. '
   cannotLockMsg {
       return '{That_is_not dobj} something {you/he} {can} lock. ';
   }
   cannotUnlockMsg {
       return '{That_is_not dobj} something {you/he} {can} unlock. ';
   }
   cannotOpenLockedMsg = '{The dobj/he} seem{s/ed} to be locked. '
   unlockRequiresKeyMsg =
       '{You/he} seem{s/ed} to need a key to unlock {the dobj/him}. '
   cannotLockWithMsg =
       '{The iobj/he} {does}{n\'t} look suitable for locking that. '
   cannotUnlockWithMsg =
       '{The iobj/he} {does}{n\'t} look suitable for unlocking that. '
   unknownHowToLockMsg =
       'It' + custMsgObj.sOrWasStr + ' not clear how to lock {the dobj/him}. '
   unknownHowToUnlockMsg =
       'It' + custMsgObj.sOrWasStr + ' not clear how to unlock {the dobj/him}. '
   keyDoesNotFitLockMsg = '{The iobj/he} {does}{n\'t} fit the lock. '
   foundKeyOnKeyringMsg(ring, key) {
       gMessageParams(ring, key);
       return '{You/he} tr{ies/ied} each key on {the ring/him}, and
           {find[s actor]|found} that {the key/he} fit{s/ted} the lock. ';
   }
   foundNoKeyOnKeyringMsg(ring) {
       gMessageParams(ring);
       return '{You/he} tr{ies/ied} each key on {the ring/him},
           but {you/he} {can\'t} find anything that fit{s|ted} the lock. ';
   }
   cannotEatMsg = '{The dobj/he} {does}{_not} ' + custMsgObj.appearStr +
       ' to be edible. '
   cannotDrinkMsg = '{That dobj/he} {does}{_not} ' + custMsgObj.appearStr +
       ' to be something
       {you/he} {can} drink. '
   cannotCleanMsg =
       '{You/he} would{n\'t} {|have} know{|n} how to clean {that dobj/him}. '
   cannotCleanWithMsg =
       '{You/he} {can\'t} clean anything with {that iobj/him}. '
   cannotAttachKeyToMsg =
       '{You/he} {cannot} attach {the dobj/him} to {that iobj/him}. '
   cannotSleepMsg = '{You/he} {does}{n\'t} need to sleep right now. '
   cannotSitOnMsg {
       return '{That_isn\'t dobj} something {you/he} {can} sit on. ';
   }
   cannotLieOnMsg {
       return '{That_isn\'t dobj} something {you/he} {can} lie on. ';
   }
   cannotStandOnMsg = '{You/he} {can\'t} stand on {that dobj/him}. '
   cannotBoardMsg = '{You/he} {can\'t} board {that dobj/him}. '
   cannotUnboardMsg = '{You/he} {can\'t} get out of {that dobj/him}. '
   cannotGetOffOfMsg = '{You/he} {can\'t} get off of {that dobj/him}. '
   cannotStandOnPathMsg = 'If {you/he} want{s/ed} to follow {the dobj/him},
       just say so. '
   cannotEnterHeldMsg =
       '{You/he} {can\'t} do that while {you\'re} holding {the dobj/him}. '
   cannotGetOutMsg = '{You\'re} not in anything {you/he} {can} disembark. '
   alreadyInLocMsg = '{You\'re} already {in dobj}. '
   alreadyStandingMsg = '{You\'re} already standing. '
   alreadyStandingOnMsg = '{You\'re} already standing {on dobj}. '
   alreadySittingMsg = '{You\'re} already sitting down. '
   alreadySittingOnMsg = '{You\'re} already sitting {on dobj}. '
   alreadyLyingMsg = '{You\'re} already lying down. '
   alreadyLyingOnMsg = '{You\'re} already lying {on dobj}. '
   notOnPlatformMsg = '{You\'re} not {on dobj}. '
   noRoomToStandMsg =
       'There' + custMsgObj.sOrWasStr + ' no room for {you/him} to stand {on dobj}. '
   noRoomToSitMsg =
       'There' + custMsgObj.sOrWasStr + ' no room for {you/him} to sit {on dobj}. '
   noRoomToLieMsg =
       'There' + custMsgObj.sOrWasStr + ' no room for {you/him} to lie {on dobj}. '
   okayPostureChangeMsg(posture)
       { return 'Okay, {you\'re} now ' + posture.participle + '. '; }
   roomOkayPostureChangeMsg(posture, obj) {
       gMessageParams(obj);
       return 'Okay, {you\'re} now ' + posture.participle + ' {on obj}. ';
   }
   okayNotStandingOnMsg = 'Okay, {you\'re} no longer {on dobj}. '
   cannotFastenMsg = '{You/he} {cannot} fasten {the dobj/him}. '
   cannotFastenToMsg =
       '{You/he} {cannot} fasten anything to {the iobj/him}. '
   cannotUnfastenMsg = '{You/he} {cannot} unfasten {the dobj/him}. '
   cannotUnfastenFromMsg =
       '{You/he} {cannot} unfasten anything from {the iobj/him}. '
   cannotPlugInMsg = '{You_see_no} way to plug in {the dobj/him}. '
   cannotPlugInToMsg =
       '{You_see_no} way to plug anything into {the iobj/him}. '
   cannotUnplugMsg = '{You_see_no} way to unplug {the dobj/him}. '
   cannotUnplugFromMsg =
       '{You_see_no} way to unplug anything from {the iobj/him}. '
   cannotScrewMsg = '{You_see_no} way to screw {the dobj/him}. '
   cannotScrewWithMsg =
       '{You/he} {cannot} screw anything with {the iobj/him}. '
   cannotUnscrewMsg = '{You_see_no} way to unscrew {the dobj/him}. '
   cannotUnscrewWithMsg =
       '{You/he} {cannot} unscrew anything with {the iobj/him}. '
   cannotEnterMsg {
       return '{That_is_not dobj} something {you/he} {can} enter. ';
   }
   cannotGoThroughMsg {
       return '{That_is_not dobj} something {you/he} {can} go through. ';
   }
   cannotThrowAtSelfMsg =
       '{You/he} {can\'t} throw {that dobj/him} at {itself}. '
   cannotThrowAtContentsMsg() {
       return '{You_would_have_to} remove {the iobj/him}
           from {the dobj/him} before {you_could} do that. ';
   }
   shouldNotThrowAtFloorMsg =
       '{You/he} should just {|have} put {it dobj/him} down instead. '
   dontThrowDirMsg =
       ('<.parser>You need to be more specific about
           what ' + (gActor.referralPerson == ThirdPerson
                     ? 'you want {the actor/him}' : '')
        + ' to throw {the dobj/him} at.<./parser> ')
   throwHitMsg(projectile, target) {
       gMessageParams(projectile, target);
       return '{The projectile/he} hit{[s]|} {the target/him} without any
           obvious effect. ';
   }
   throwFallMsg(projectile, target) {
       gMessageParams(projectile, target);
       return '{The projectile/he} land{s/ed} on {the target/him}. ';
   }
   throwHitFallMsg(projectile, target, dest) {
       gMessageParams(projectile, target);
       return '{The projectile/he} hit{[s]|} {the target/him}
           without any obvious effect, and {fall[s projectile]|fell} '
           + dest.putInName + '. ';
   }
   throwShortMsg(projectile, target) {
       gMessageParams(projectile, target);
       return '{The projectile/he} {fall[s]|fell} well short of '
              + '{the target/him}. ';
   }
   throwFallShortMsg(projectile, target, dest) {
       gMessageParams(projectile, target);
       return '{The projectile/he} {fall[s]|fell} ' + dest.putInName
           + ' well short of {the target/him}. ';
   }
   throwCatchMsg(obj, target) {
       return '\^' + target.theName + ' '
           + tSel('catch' + target.verbEndingEs, 'caught')
           + ' ' + obj.theNameObj + '. ';
   }
   cannotThrowToMsg = '{You/he} {cannot} throw anything to {an iobj/him}. '
   willNotCatchMsg(catcher) {
       return '\^' + catcher.nameDoes + custMsgObj.ntAbbr
           + ' look like ' + catcher.itNom + ' want'
           + catcher.verbEndingSEd + ' to catch anything. ';
   }
   cannotKissMsg = 'Kissing {the dobj/him} {has|had} no obvious effect. '
   cannotKissActorMsg
       = '{The dobj/he} probably would{n\'t} {|have} like{|d} that. '
   cannotKissSelfMsg = '{You/he} {cannot} kiss {yourself}. '
   newlyDarkMsg() {
       local isOrWas;
       if (gameMain.usePastTense)
           isOrWas = ' was';
       else if (libGlobal.useContractions == usually ||
                libGlobal.useContractions == always)
           isOrWas = custMsgObj.rsquoPlainStr + 's';
       else
           isOrWas = ' is';
       return 'It' + isOrWas + ' now pitch black. ';
   }
;

modify npcActionMessages // superclass = playerActionMessages
   timePassesMsg = '{You/he} wait{s/ed}... '
   cannotMoveFixtureMsg = '{You/he} {cannot} move {that dobj/him}. '
   cannotMoveImmovableMsg = '{You/he} {cannot} move {that dobj/him}. '
   cannotTakeHeavyMsg =
       '{That dobj/he} {is} too heavy for {you/him} to take. '
   cannotMoveHeavyMsg =
       '{That dobj/he} {is} too heavy for {you/him} to move. '
   cannotPutHeavyMsg =
       '{That dobj/he} {is} too heavy for {you/him} to move. '
   cannotMoveComponentMsg(loc) {
       return '{You/he} {cannot} do that because {the dobj/he} {is} part
           of ' + loc.theNameObj + '. ';
   }
   cannotRemoveHeldMsg = 'There' + custMsgObj.sOrWasStr
       + ' nothing to remove {the dobj/him} from. '
   okayTakeMsg = '{You/he} {take[s]|took} {the dobj/him}. '
   okayDropMsg = '{You/he} put{[s]|} down {the dobj/him}. '
   okayPutInMsg = '{You/he} put{[s]|} {the dobj/him} in {the iobj/him}. '
   okayPutOnMsg = '{You/he} put{[s]|} {the dobj/him} on {the iobj/him}. '
   okayPutUnderMsg =
       '{You/he} put{[s]|} {the dobj/him} under {the iobj/him}. '
   okayPutBehindMsg =
       '{You/he} put{[s]|} {the dobj/him} behind {the iobj/him}. '
   okayWearMsg =
       '{You/he} put{[s]|} on {the dobj/him}. '
   okayDoffMsg = '{You/he} {take[s]|took} off {the dobj/him}. '
   okayOpenMsg = '{You/he} open{s/ed} {the dobj/him}. '
   okayCloseMsg = '{You/he} close{s/d} {the dobj/him}. '
   okayLockMsg = '{You/he} lock{s/ed} {the dobj/him}. '
   okayUnlockMsg = '{You/he} unlock{s/ed} {the dobj/him}. '
   pushNoEffectMsg = '{You/he} tr{ies/ied} to push {the dobj/him}, with no '
                     + 'obvious effect. '
   pullNoEffectMsg = '{You/he} tr{ies/ied} to pull {the dobj/him}, with no '
                     + 'obvious effect. '
   moveNoEffectMsg = '{You/he} tr{ies/ied} to move {the dobj/him}, with no '
                     + 'obvious effect. '
   moveToNoEffectMsg = '{You/he} {leaves} {the dobj/he} where {it/he} {is}. '
   whereToGoMsg () {
       return '\^' + custMsgObj.youllStr
           + ' have to say which way {you/he} should {|have} go{|ne}. ';
   }
   tooLargeForContainerMsg(obj, cont) {
       gMessageParams(obj, cont);
       return '{You/he} {cannot} do that because {the obj/he} {is}
           too large for {the cont/him}. ';
   }
   tooLargeForUndersideMsg(obj, cont) {
       gMessageParams(obj, cont);
       return '{You/he} {cannot} do that because {the obj/he}
           {won\'t} fit under {the cont/him}. ';
   }
   tooLargeForRearMsg(obj, cont) {
       gMessageParams(obj, cont);
       return '{You/he} {cannot} do that because {the obj/he}
           {won\'t} fit behind {the cont/him}. ';
   }
   containerTooFullMsg(obj, cont) {
       gMessageParams(obj, cont);
       return '{You/he} {cannot} do that because {the cont/he} {is}
           already too full to hold {the obj/him}. ';
   }
   surfaceTooFullMsg(obj, cont) {
       gMessageParams(obj, cont);
       return '{You/he} {cannot} do that because there' + custMsgObj.sOrWasStr + '
           no room for {the obj/him} on {the cont/him}. ';
   }
   objNotForKeyringMsg = '{You/he} {cannot} do that because
           {that dobj/he} {does}{n\'t} fit on {the iobj/him}. '
   takeFromNotInMsg = '{You/he} {cannot} do that because
       {the dobj/he} {is}{n\'t} in {that iobj/him}. '
   takeFromNotOnMsg = '{You/he} {cannot} do that because
       {the dobj/he} {is}{n\'t} on {that iobj/him}. '
   takeFromNotUnderMsg = '{You/he} {cannot} do that because
       {the dobj/he} {is}{n\'t} under {that iobj/him}. '
   takeFromNotBehindMsg = '{You/he} {cannot} do that because
       {the dobj/he} {is}{n\'t} behind {that iobj/him}. '
   cannotJumpOffHereMsg = 'There' + custMsgObj.sOrWasStr + ' nowhere for {you/him} to jump. '
   shouldNotBreakMsg = '{You/he} {does}{n\'t} want to break {that dobj/him}. '
   okayPostureChangeMsg(posture)
       { return '{You/he} ' + posture.msgVerbI + '. '; }
   roomOkayPostureChangeMsg(posture, obj) {
       gMessageParams(obj);
       return '{You/he} ' + posture.msgVerbT + ' {on obj}. ';
   }
   okayNotStandingOnMsg = '{You/he} {get[s]|got} {offof dobj}. '
   okayTurnToMsg(val)
       { return '{You/he} turn{s/ed} {the dobj/him} to ' + val + '. '; }
   okayPushButtonMsg = '{You/he} push{es/ed} {the dobj/him}. '
   okayTurnOnMsg = '{You/he} turn{s/ed} {the dobj/him} on. '
   okayTurnOffMsg = '{You/he} turn{s/ed} {the dobj/him} off. '
   keyDoesNotFitLockMsg = '{You/he} tr{ies/ied} {the iobj/he}, but
       {it iobj/he} {does}{n\'t} fit the lock. '
   okayFollowModeMsg() {
       local iWill;
       if (libGlobal.useContractions == usually ||
           libGlobal.useContractions == always)
           iWill = 'I' + custMsgObj.rsquoPlainStr + 'll';
       else
           iWill = 'I will';
       return custMsgObj.ldquoPlainStr + 'Okay, ' + iWill
           + ' follow {the dobj/him}.'
           + custMsgObj.rdquoPlainStr + ' ';
   }
   alreadyFollowModeMsg = custMsgObj.ldquoStr
       + 'I' + custMsgObj.rsquoPlainStr + 'm already following
       {the dobj/him}.' + custMsgObj.rdquoStr + ' '
   okayExtinguishCandleMsg = '{You/he} extinguish{es/ed} {the dobj/him}. '
   okayAttachToMsg =
       '{You/he} attach{es/ed} {the dobj/him} to {the iobj/him}. '
   okayDetachFromMsg =
       '{You/he} detach{es/ed} {the dobj/him} from {the iobj/him}. '
   cannotTalkToSelfMsg = '{You/he} {won\'t} accomplish anything talking
       to {yourself/himself}. '
   cannotAskSelfMsg = '{You/he} {won\'t} accomplish anything talking
       to {yourself/himself}. '
   cannotAskSelfForMsg = '{You/he} {won\'t} accomplish anything talking
       to {yourself/himself}. '
   cannotTellSelfMsg = '{You/he} {won\'t} accomplish anything talking
       to {yourself/himself}. '
   cannotGiveToSelfMsg = '{You/he} {won\'t} accomplish anything
       giving {the dobj/him} to {yourself/himself}. '
   cannotShowToSelfMsg = '{You/he} {won\'t} accomplish anything
       showing {the dobj/him} to {yourself/himself}. '
;

// Only a few of msg_neu.t's listers had to be modified.

modify actorInventoryLister // superclass = DividedInventoryLister
   showInventoryWearingOnly(parent, wearing) {
       //if (libGlobal.preferCasual)
       //    "\^<<parent.nameIsnt>> carrying anything,
       //    and <<parent.verbToBe>> wearing <<wearing>>. ";
       //else
       //    "<<buildSynthParam('The/he', parent)>> {is} carrying
       //    nothing, and {is} wearing <<wearing>>. ";
       if (libGlobal.preferCasual)
           "\^<<parent.nameIsnt>> carrying anything, and ";
       else
           "\^<<parent.nameIs>> carrying nothing, and ";
       // "You're carrying nothing, and you're wearing a hat", rather than
       // "You're carrying nothing, and are wearing a hat."
       if ((libGlobal.useContractions == usually ||
            libGlobal.useContractions == always)
        && (parent.referralPerson == FirstPerson ||
            parent.referralPerson == SecondPerson))
         "<<parent.itIsContraction>> ";
       else
         "<<parent.verbToBe>> ";
       "wearing <<wearing>>. ";
   }
;
modify thingLookInLister // superclass = DescContentsLister, BaseThingContentsLister
   showListEmpty(pov, parent) {
       gMessageParams(parent);
       defaultDescReport('\^' + gActor.nameSeesNo
           + 'thing unusual in {the parent/him}. ');
   }
;
modify surfaceLookInLister // superclass = DescContentsLister, BaseSurfaceContentsLister
   showListEmpty(pov, parent) {
       gMessageParams(parent);
       defaultDescReport('\^' + gActor.nameSeesNo
           + 'thing on {the parent/him}. ');
   }
;
modify undersideLookUnderLister // superclass = DescContentsLister, BaseUndersideContentsLister
   showListEmpty(pov, parent) {
       gMessageParams(parent);
       defaultDescReport('\^' + gActor.nameSeesNo
           + 'thing under {the parent/him}. ');
   }
;
modify rearLookBehindLister // superclass = DescContentsLister, BaseRearContentsLister
   showListEmpty(pov, parent) {

       gMessageParams(parent);
       defaultDescReport('\^' + gActor.nameSeesNo
           + 'thing behind {the parent/him}. ');
   }
;
modify SuggestedTopicLister
   showListEmpty(pov, parent) {
       if (isExplicit) {
           gMessageParams(askingActor, targetActor);
           "<<isExplicit ? '' : '('>>\^<<libGlobal.preferCasual
             ? askingActor.theName + ' ' + askingActor.verbToDo
               + custMsgObj.ntAbbr + ' have any'
             : askingActor.theName + ' ' + askingActor.verbToHave + ' no'
             >>thing
           specific in mind right now to discuss with
           {the targetActor/him}.<<isExplicit ? '' : ')'>> ";
       }
   }
;