cfad47cfa3/t3compiler/tads3/lib/adv3/en_us/msg_neu.t

4b825dc642cb6eb9a060e54bf8d69288fbee4904cfad47cfa334b206c65f22086bcc5d63e6f70944
1
#charset "us-ascii"
2
3
/* 
4
 *   Copyright (c) 2000, 2006 Michael J. Roberts.  All Rights Reserved. 
5
 *
6
 *   TADS 3 Library - "neutral" messages for US English
7
 *
8
 *   This module provides standard library messages with a parser/narrator 
9
 *   that's as invisible (neutral) as possible.  These messages are designed 
10
 *   to reduce the presence of the computer as mediator in the story, to 
11
 *   give the player the most direct contact that we can with the scenario.
12
 *
13
 *   The parser almost always refers to itself in the third person (by 
14
 *   calling itself something like "this story") rather than in the first 
15
 *   person, and, whenever possible, avoids referring to itself in the first 
16
 *   place.  Our ideal phrasing is either second-person, describing things 
17
 *   directly in terms of the player character's experience, or "no-person," 
18
 *   simply describing things without mentioning the speaker or listener at 
19
 *   all.  For example, rather than saying "I don't see that here," we say 
20
 *   "you don't see that here," or "that's not here."  We occasionally stray 
21
 *   from this ideal where achieving it would be too awkward.
22
 *
23
 *   In the earliest days of adventure games, the parser was usually a 
24
 *   visible presence: the early parsers frequently reported things in the 
25
 *   first person, and some even had specific personalities.  This 
26
 *   conspicuous parser style has become less prevalent in modern games, 
27
 *   though, and authors now usually prefer to treat the parser as just 
28
 *   another part of the user interface, which like all good UI's is best 
29
 *   when the user doesn't notice it.  
30
 */
31
32
#include "adv3.h"
33
#include "en_us.h"
34
35
/* ------------------------------------------------------------------------ */
36
/*
37
 *   Build a message parameter string with the given parameter type and
38
 *   name.
39
 *   
40
 *   This is useful when we have a name from a variable, and we need to
41
 *   build the message substitution string for embedding in a larger
42
 *   string.  We can't just embed the name variable using <<var>>, because
43
 *   that would process the output piecewise - the output filter needs to
44
 *   see the whole {typ var} expression in one go.  So, instead of writing
45
 *   this:
46
 *   
47
 *.     {The/he <<var>>} {is} ...
48
 *   
49
 *   write this:
50
 *   
51
 *.     <<buildParam('The/he', var)>> {is} ...
52
 */
53
buildParam(typeString, nm)
54
{
55
    return '{' + typeString + ' ' + nm + '}';
56
}
57
58
/*
59
 *   Synthesize a message parameter, and build it into a parameter string
60
 *   with the given substitution type.
61
 *   
62
 *   For example, buildSynthParam('abc', obj) returns '{abc xxx}', where
63
 *   'xxx' is a synthesized message parameter name (created using
64
 *   gSynthMessageParam) for the object obj.  
65
 */
66
buildSynthParam(typeString, obj)
67
{
68
    return '{' + typeString + ' ' + gSynthMessageParam(obj) + '}';
69
}
70
71
72
/* ------------------------------------------------------------------------ */
73
/*
74
 *   Library Messages 
75
 */
76
libMessages: MessageHelper
77
    /*
78
     *   The pronoun to use for the objective form of the personal
79
     *   interrogative pronoun.  Strictly speaking, the right word for
80
     *   this usage is "whom"; but regardless of what the grammar books
81
     *   say, most American English speakers these days use "who" for both
82
     *   the subjective and objective cases; to many ears, "whom" sounds
83
     *   old-fashioned, overly formal, or even pretentious.  (Case in
84
     *   point: a recent television ad tried to make a little kid look
85
     *   ultra-sophisticated by having him answer the phone by asking
86
     *   "*whom* may I ask is calling?", with elaborate emphasis on the
87
     *   "whom."  Of course, the correct usage in this case is "who," so
88
     *   the ad only made the kid look pretentious.  It goes to show that,
89
     *   at least in the mind of the writer of the ad, "whom" is just the
90
     *   snooty, formal version of "who" that serves only to signal the
91
     *   speaker's sophistication.)
92
     *   
93
     *   By default, we distinguish "who" and "whom."  Authors who prefer
94
     *   to use "who" everywhere can do so by changing this property's
95
     *   value to 'who'.  
96
     */
97
    whomPronoun = 'whom'
98
99
    /*
100
     *   Flag: offer an explanation of the "OOPS" command when it first
101
     *   comes up.  We'll only show this the first time the player enters
102
     *   an unknown word.  If you never want to offer this message at all,
103
     *   simply set this flag to nil initially.
104
     *   
105
     *   See also oopsNote() below.  
106
     */
107
    offerOopsNote = true
108
109
    /*
110
     *   some standard commands for insertion into <a> tags - these are in
111
     *   the messages so they can translated along with the command set
112
     */
113
    commandLookAround = 'look around'
114
    commandFullScore = 'full score'
115
    
116
    /* announce a completely remapped action */
117
    announceRemappedAction(action)
118
    {
119
        return '<./p0>\n<.assume>' + action.getParticiplePhrase()
120
            + '<./assume>\n';
121
    }
122
123
    /*
124
     *   Get a string to announce an implicit action.  This announces the
125
     *   current global action.  'ctx' is an ImplicitAnnouncementContext
126
     *   object describing the context in which the message is being
127
     *   displayed.  
128
     */
129
    announceImplicitAction(action, ctx)
130
    {
131
        /* build the announcement from the basic verb phrase */
132
        return ctx.buildImplicitAnnouncement(action.getImplicitPhrase(ctx));
133
    }
134
135
    /*
136
     *   Announce a silent implied action.  This allows an implied action
137
     *   to work exactly as normal (including the suppression of a default
138
     *   response message), but without any announcement of the implied
139
     *   action. 
140
     */
141
    silentImplicitAction(action, ctx) { return ''; }
142
143
    /*
144
     *   Get a string to announce that we're implicitly moving an object to
145
     *   a bag of holding to make room for taking something new.  If
146
     *   'trying' is true, it means we want to phrase the message as merely
147
     *   trying the action, not actually performing it.  
148
     */
149
    announceMoveToBag(action, ctx)
150
    {
151
        /* build the announcement, adding an explanation */
152
        return ctx.buildImplicitAnnouncement(
153
            action.getImplicitPhrase(ctx) + ' to make room');
154
    }
155
156
    /* show a library credit (for a CREDITS listing) */
157
    showCredit(name, byline) { "<<name>> <<byline>>"; }
158
159
    /* show a library version number (for a VERSION listing) */
160
    showVersion(name, version) { "<<name>> version <<version>>"; }
161
162
    /* there's no "about" information in this game */
163
    noAboutInfo = "<.parser>This story has no ABOUT information.<./parser> "
164
165
    /*
166
     *   Show a list state name - this is extra state information that we
167
     *   show for an object in a listing involving the object.  For
168
     *   example, a light source might add a state like "(providing
169
     *   light)".  We simply show the list state name in parentheses.  
170
     */
171
    showListState(state) { " (<<state>>)"; }
172
173
    /* a set of equivalents are all in a given state */
174
    allInSameListState(lst, stateName)
175
        { " (<<lst.length() == 2 ? 'both' : 'all'>> <<stateName>>)"; }
176
177
    /* generic long description of a Thing from a distance */
178
    distantThingDesc(obj)
179
    {
180
        gMessageParams(obj);
181
        "{It's obj} too far away to make out any detail. ";
182
    }
183
184
    /* generic long description of a Thing under obscured conditions */
185
    obscuredThingDesc(obj, obs)
186
    {
187
        gMessageParams(obj, obs);
188
        "{You/he} {can\'t} make out any detail through {the obs/him}. ";
189
    }
190
191
    /* generic "listen" description of a Thing at a distance */
192
    distantThingSoundDesc(obj)
193
        { "{You/he} {can\'t} hear any detail from this distance. "; }
194
195
    /* generic obscured "listen" description */
196
    obscuredThingSoundDesc(obj, obs)
197
    {
198
        gMessageParams(obj, obs);
199
        "{You/he} {can\'t} hear any detail through {the obs/him}. ";
200
    }
201
202
    /* generic "smell" description of a Thing at a distance */
203
    distantThingSmellDesc(obj)
204
        { "{You/he} {can\'t} smell much at this distance. "; }
205
206
    /* generic obscured "smell" description */
207
    obscuredThingSmellDesc(obj, obs)
208
    {
209
        gMessageParams(obj, obs);
210
        "{You/he} {can\'t} smell much through {the obs/him}. ";
211
    }
212
213
    /* generic "taste" description of a Thing */
214
    thingTasteDesc(obj)
215
    {
216
        gMessageParams(obj);
217
        "{It/he obj} taste{s/d} much as {you/he} would {|have}
218
        expect{|ed}. ";
219
    }
220
221
    /* generic "feel" description of a Thing */
222
    thingFeelDesc(obj)
223
        { "{You/he} {feel[s]|felt} nothing out of the ordinary. "; }
224
225
    /* obscured "read" description */
226
    obscuredReadDesc(obj)
227
    {
228
        gMessageParams(obj);
229
        "{You/he} {can\'t} see {that obj/him} well enough to read
230
        {it/him}. ";
231
    }
232
233
    /* dim light "read" description */
234
    dimReadDesc(obj)
235
    {
236
        gMessageParams(obj);
237
        "There{&rsquo;s| was} not enough light to read {that obj/him}. ";
238
    }
239
240
    /* lit/unlit match description */
241
    litMatchDesc(obj) { "\^<<obj.nameIs>> lit. "; }
242
    unlitMatchDesc(obj) { "\^<<obj.nameIs>> an ordinary match. "; }
243
244
    /* lit candle description */
245
    litCandleDesc(obj) { "\^<<obj.nameIs>> lit. "; }
246
247
    /*
248
     *   Prepositional phrases for putting objects into different types of
249
     *   objects. 
250
     */
251
    putDestContainer(obj) { return 'into ' + obj.theNameObj; }
252
    putDestSurface(obj) { return 'onto ' + obj.theNameObj; }
253
    putDestUnder(obj) { return 'under ' + obj.theNameObj; }
254
    putDestBehind(obj) { return 'behind ' + obj.theNameObj; }
255
    putDestFloor(obj) { return 'to ' + obj.theNameObj; }
256
257
    /* the list separator character in the middle of a list */
258
    listSepMiddle = ", "
259
260
    /* the list separator character for a two-element list */
261
    listSepTwo = " and "
262
263
    /* the list separator for the end of a list of at least three elements */
264
    listSepEnd = ", and "
265
266
    /*
267
     *   the list separator for the middle of a long list (a list with
268
     *   embedded lists not otherwise set off, such as by parentheses) 
269
     */
270
    longListSepMiddle = "; "
271
272
    /* the list separator for a two-element list of sublists */
273
    longListSepTwo = ", and "
274
275
    /* the list separator for the end of a long list */
276
    longListSepEnd = "; and "
277
278
    /* show the basic score message */
279
    showScoreMessage(points, maxPoints, turns)
280
    {
281
        "In <<turns>> move<<turns == 1 ? '' : 's'>>, you have
282
        scored <<points>> of a possible <<maxPoints>> point<<
283
          maxPoints == 1 ? '' : 's'>>. ";
284
    }
285
286
    /* show the basic score message with no maximum */
287
    showScoreNoMaxMessage(points, turns)
288
    {
289
        "In <<turns>> move<<turns == 1 ? '' : 's'>>, you have
290
        scored <<points>> point<<points == 1 ? '' : 's'>>. ";
291
    }
292
293
    /* show the full message for a given score rank string */
294
    showScoreRankMessage(msg) { "This makes you <<msg>>. "; }
295
296
    /*
297
     *   show the list prefix for the full score listing; this is shown on
298
     *   a line by itself before the list of full score items, shown
299
     *   indented and one item per line 
300
     */
301
    showFullScorePrefix = "Your score consists of:"
302
303
    /*
304
     *   show the item prefix, with the number of points, for a full score
305
     *   item - immediately after this is displayed, we'll display the
306
     *   description message for the achievement 
307
     */
308
    fullScoreItemPoints(points)
309
    {
310
        "<<points>> point<<points == 1 ? '' : 's'>> for ";
311
    }
312
313
    /* score change - first notification */
314
    firstScoreChange(delta)
315
    {
316
        scoreChange(delta);
317
        scoreChangeTip.showTip();
318
    }
319
320
    /* score change - notification other than the first time */
321
    scoreChange(delta)
322
    {
323
        "<.commandsep><.notification><<
324
        basicScoreChange(delta)>><./notification> ";
325
    }
326
327
    /*
328
     *   basic score change notification message - this is an internal
329
     *   service routine for scoreChange and firstScoreChange 
330
     */
331
    basicScoreChange(delta)
332
    {
333
        "Your <<aHref(commandFullScore, 'score', 'Show full score')>>
334
        has just <<delta > 0 ? 'in' : 'de'>>creased by
335
        <<spellInt(delta > 0 ? delta : -delta)>>
336
        point<<delta is in (1, -1) ? '' : 's'>>.";
337
    }
338
339
    /* acknowledge turning tips on or off */
340
    acknowledgeTipStatus(stat)
341
    {
342
        "<.parser>Tips are now turned <<stat ? 'on' : 'off'>>.<./parser> ";
343
    }
344
345
    /* describe the tip mode setting */
346
    tipStatusShort(stat)
347
    {
348
        "TIPS <<stat ? 'ON' : 'OFF'>>";
349
    }
350
351
    /* get the string to display for a footnote reference */
352
    footnoteRef(num)
353
    {
354
        local str;
355
356
        /* set up a hyperlink for the note that enters the "note n" command */
357
        str = '<sup>[<a href="footnote ' + num + '"><.a>';
358
359
        /* show the footnote number in square brackets */
360
        str += num;
361
        
362
        /* end the hyperlink */
363
        str += '<./a></a>]</sup>';
364
365
        /* return the text */
366
        return str;
367
    }
368
369
    /* first footnote notification */
370
    firstFootnote()
371
    {
372
        footnotesTip.showTip();
373
    }
374
375
    /* there is no such footnote as the given number */
376
    noSuchFootnote(num)
377
    {
378
        "<.parser>The story has never referred to any such
379
        footnote.<./parser> ";
380
    }
381
382
    /* show the current footnote status */
383
    showFootnoteStatus(stat)
384
    {
385
        "The current setting is FOOTNOTES ";
386
        switch(stat)
387
        {
388
        case FootnotesOff:
389
            "OFF, which hides all footnote references.
390
            Type <<aHref('footnotes medium', 'FOOTNOTES MEDIUM',
391
                         'Set footnotes to Medium')>> to
392
            show references to footnotes except those you&rsquo;ve
393
            already seen, or <<aHref('footnotes full', 'FOOTNOTES FULL',
394
                                     'Set footnotes to Full')>>
395
            to show all footnote references. ";
396
            break;
397
398
        case FootnotesMedium:
399
            "MEDIUM, which shows references to unread footnotes, but
400
            hides references to those you&rsquo;ve already read.  Type
401
            <<aHref('footnotes off', 'FOOTNOTES OFF',
402
                    'Turn off footnotes')>> to hide
403
            footnote references entirely, or <<aHref(
404
                'footnotes full', 'FOOTNOTES FULL',
405
                'Set footnotes to Full')>> to show every reference, even to
406
            notes you&rsquo;ve already read. ";
407
            break;
408
409
        case FootnotesFull:
410
            "FULL, which shows every footnote reference, even to
411
            notes you&rsquo;ve already read.  Type <<aHref('footnotes medium',
412
            'FOOTNOTES MEDIUM', 'Set footnotes to Medium')>> to show
413
            only references to notes you
414
            haven&rsquo;t yet read, or <<
415
              aHref('footnotes off', 'FOOTNOTES OFF', 'Turn off footnotes')>>
416
            to hide footnote references entirely. ";
417
            break;
418
        }
419
    }
420
421
    /* acknowledge a change in the footnote status */
422
    acknowledgeFootnoteStatus(stat)
423
    {
424
        "<.parser>The setting is now
425
        <<shortFootnoteStatus(stat)>>.<./parser> ";
426
    }
427
428
    /* show the footnote status, in short form */
429
    shortFootnoteStatus(stat)
430
    {
431
        "FOOTNOTES <<
432
          stat == FootnotesOff ? 'OFF'
433
          : stat == FootnotesMedium ? 'MEDIUM'
434
          : 'FULL' >>";
435
    }
436
437
    /*
438
     *   Show the main command prompt.
439
     *   
440
     *   'which' is one of the rmcXxx phase codes indicating what kind of
441
     *   command we're reading.  This default implementation shows the
442
     *   same prompt for every type of input, but games can use the
443
     *   'which' value to show different prompts for different types of
444
     *   queries, if desired.  
445
     */
446
    mainCommandPrompt(which) { "\b&gt;"; }
447
448
    /*
449
     *   Show a pre-resolved error message string.  This simply displays
450
     *   the given string.  
451
     */
452
    parserErrorString(actor, msg) { say(msg); }
453
454
    /* show the response to an empty command line */
455
    emptyCommandResponse = "<.parser>I beg your pardon?<./parser> "
456
457
    /* invalid token (i.e., punctuation) in command line */
458
    invalidCommandToken(ch)
459
    {
460
        "<.parser>The story doesn&rsquo;t know how to use the character
461
        &lsquo;<<ch>>&rsquo; in a command.<./parser> ";
462
    }
463
464
    /*
465
     *   Command group prefix - this is displayed after a command line and
466
     *   before the first command results shown after the command line.
467
     *   
468
     *   By default, we'll show the "zero-space paragraph" marker, which
469
     *   acts like a paragraph break in that it swallows up immediately
470
     *   following paragraph breaks, but doesn't actually add any space.
471
     *   This will ensure that we don't add any space between the command
472
     *   input line and the next text.  
473
     */
474
    commandResultsPrefix = '<.p0>'
475
476
    /*
477
     *   Command "interruption" group prefix.  This is displayed after an
478
     *   interrupted command line - a command line editing session that
479
     *   was interrupted by a timeout event - just before the text that
480
     *   interrupted the command line.
481
     *   
482
     *   By default, we'll show a paragraph break here, to set off the
483
     *   interrupting text from the command line under construction.  
484
     */
485
    commandInterruptionPrefix = '<.p>'
486
487
    /*
488
     *   Command separator - this is displayed after the results from a
489
     *   command when another command is about to be executed without any
490
     *   more user input.  That is, when a command line contains more than
491
     *   one command, this message is displayed between each successive
492
     *   command, to separate the results visually.
493
     *   
494
     *   This is not shown before the first command results after a
495
     *   command input line, and is not shown after the last results
496
     *   before a new input line.  Furthermore, this is shown only between
497
     *   adjacent commands for which output actually occurs; if a series
498
     *   of commands executes without any output, we won't show any
499
     *   separators between the silent commands.
500
     *   
501
     *   By default, we'll just start a new paragraph.  
502
     */
503
    commandResultsSeparator = '<.p>'
504
505
    /*
506
     *   "Complex" result separator - this is displayed between a group of
507
     *   messages for a "complex" result set and adjoining messages.  A
508
     *   command result list is "complex" when it's built up out of
509
     *   several generated items, such as object identification prefixes
510
     *   or implied command prefixes.  We use additional visual separation
511
     *   to set off these groups of messages from adjoining messages,
512
     *   which is especially important for commands on multiple objects,
513
     *   where we would otherwise have several results shown together.  By
514
     *   default, we use a paragraph break.  
515
     */
516
    complexResultsSeparator = '<.p>'
517
518
    /*
519
     *   Internal results separator - this is displayed to visually
520
     *   separate the results of an implied command from the results for
521
     *   the initiating command, which are shown after the results from
522
     *   the implied command.  By default, we show a paragraph break.
523
     */
524
    internalResultsSeparator = '<.p>'
525
526
    /*
527
     *   Command results suffix - this is displayed just before a new
528
     *   command line is about to be read if any command results have been
529
     *   shown since the last command line.
530
     *   
531
     *   By default, we'll show nothing extra.  
532
     */
533
    commandResultsSuffix = ''
534
535
    /*
536
     *   Empty command results - this is shown when we read a command line
537
     *   and then go back and read another without having displaying
538
     *   anything.
539
     *   
540
     *   By default, we'll return a message indicating that nothing
541
     *   happened.  
542
     */
543
    commandResultsEmpty =
544
        ('Nothing obvious happen' + tSel('s', 'ed') + '.<.p>')
545
546
    /*
547
     *   Intra-command report separator.  This is used to separate report
548
     *   messages within a single command's results.  By default, we show
549
     *   a paragraph break.  
550
     */
551
    intraCommandSeparator = '<.p>'
552
553
    /*
554
     *   separator for "smell" results - we ordinarily show each item's
555
     *   odor description as a separate paragraph 
556
     */
557
    smellDescSeparator()
558
    {
559
        "<.p>";
560
    }
561
562
    /*
563
     *   separator for "listen" results 
564
     */
565
    soundDescSeparator()
566
    {
567
        "<.p>";
568
    }
569
570
    /* a command was issued to a non-actor */
571
    cannotTalkTo(targetActor, issuingActor)
572
    {
573
        "\^<<targetActor.nameIs>> not something <<issuingActor.itNom>>
574
        <<issuingActor.verbCan>> talk to. ";
575
    }
576
577
    /* greeting actor while actor is already talking to us */
578
    alreadyTalkingTo(actor, greeter)
579
    {
580
        "\^<<greeter.theName>> already <<greeter.verbToHave>>
581
        <<actor.theNamePossAdj>> attention. ";
582
    }
583
584
    /* no topics to suggest when we're not talking to anyone */
585
    noTopicsNotTalking = "<.parser>{You're} not currently talking
586
                          to anyone.<./parser> "
587
588
    /*
589
     *   Show a note about the OOPS command.  This is, by default, added
590
     *   to the "I don't know that word" error the first time that error
591
     *   occurs.  
592
     */
593
    oopsNote()
594
    {
595
        oopsTip.showTip();
596
    }
597
598
    /* can't use OOPS right now */
599
    oopsOutOfContext = "<.parser>You can only use OOPS to correct
600
        a misspelling immediately after the story points out a word
601
        it doesn&rsquo;t know.<./parser> "
602
603
    /* OOPS in context, but without the word to correct */
604
    oopsMissingWord = "<.parser>To use OOPS to correct a misspelling,
605
        put the corrected word after OOPS, as in OOPS BOOK.<./parser> "
606
607
    /* acknowledge setting VERBOSE mode (true) or TERSE mode (nil) */
608
    acknowledgeVerboseMode(verbose)
609
    {
610
        if (verbose)
611
            "<.parser>VERBOSE mode is now selected.<./parser> ";
612
        else
613
            "<.parser>TERSE mode is now selected.<./parser> ";
614
    }
615
616
    /* show the current VERBOSE setting, in short form */
617
    shortVerboseStatus(stat) { "<<stat ? 'VERBOSE' : 'TERSE'>> mode"; }
618
619
    /* show the current score notify status */
620
    showNotifyStatus(stat)
621
    {
622
        "<.parser>Score notifications are
623
        currently <<stat ? 'on' : 'off'>>.<./parser> ";
624
    }
625
626
    /* show the current score notify status, in short form */
627
    shortNotifyStatus(stat) { "NOTIFY <<stat ? 'ON' : 'OFF'>>"; }
628
629
    /* acknowledge a change in the score notification status */
630
    acknowledgeNotifyStatus(stat)
631
    {
632
        "<.parser>Score notifications are now
633
        <<stat ? 'on' : 'off'>>.<./parser> ";
634
    }
635
636
    /*
637
     *   Announce the current object of a set of multiple objects on which
638
     *   we're performing an action.  This is used to tell the player
639
     *   which object we're acting upon when we're iterating through a set
640
     *   of objects specified in a command targeting multiple objects.  
641
     */
642
    announceMultiActionObject(obj, whichObj, action)
643
    {
644
        return '<./p0>\n<.announceObj>'
645
            + obj.getAnnouncementDistinguisher().name(obj)
646
            + ':<./announceObj> <.p0>';
647
    }
648
649
    /*
650
     *   Announce a singleton object that we selected from a set of
651
     *   ambiguous objects.  This is used when we disambiguate a command
652
     *   and choose an object over other objects that are also logical but
653
     *   are less likely.  In such cases, it's courteous to tell the
654
     *   player what we chose, because it's possible that the user meant
655
     *   one of the other logical objects - announcing this type of choice
656
     *   helps reduce confusion by making it immediately plain to the
657
     *   player when we make a choice other than what they were thinking.  
658
     */
659
    announceAmbigActionObject(obj, whichObj, action)
660
    {
661
        /* announce the object in "assume" style, ending with a newline */
662
        return '<.assume>'
663
            + obj.getAnnouncementDistinguisher().theName(obj)
664
            + '<./assume>\n';
665
    }
666
667
    /*
668
     *   Announce a singleton object we selected as a default for a
669
     *   missing noun phrase.
670
     *   
671
     *   'resolvedAllObjects' indicates where we are in the command
672
     *   processing: this is true if we've already resolved all of the
673
     *   other objects in the command, nil if not.  We use this
674
     *   information to get the phrasing right according to the situation.
675
     */
676
    announceDefaultObject(obj, whichObj, action, resolvedAllObjects)
677
    {
678
        /*
679
         *   put the action's default-object message in "assume" style,
680
         *   and start a new line after it 
681
         */
682
        return '<.assume>'
683
            + action.announceDefaultObject(obj, whichObj, resolvedAllObjects)
684
            + '<./assume>\n';
685
    }
686
687
    /* 'again' used with no prior command */
688
    noCommandForAgain()
689
    {
690
        "<.parser>There&rsquo;s nothing to repeat.<./parser> ";
691
    }
692
693
    /* 'again' cannot be directed to a different actor */
694
    againCannotChangeActor()
695
    {
696
        "<.parser>To repeat a command like <q>turtle, go north,</q>
697
        just say <q>again,</q> not <q>turtle, again.</q><./parser> ";
698
    }
699
700
    /* 'again': can no longer talk to target actor */
701
    againCannotTalkToTarget(issuer, target)
702
    {
703
        "\^<<issuer.theName>> <<issuer.verbCannot>> repeat that command. ";
704
    }
705
706
    /* the last command cannot be repeated in the present context */
707
    againNotPossible(issuer)
708
    {
709
        "That command cannot be repeated now. ";
710
    }
711
712
    /* system actions cannot be directed to non-player characters */
713
    systemActionToNPC()
714
    {
715
        "<.parser>This command cannot be directed to another
716
        character in the story.<./parser> ";
717
    }
718
719
    /* confirm that we really want to quit */
720
    confirmQuit()
721
    {
722
        "Do you really want to quit?\ (<<aHref('y', 'Y', 'Confirm quitting')
723
        >> is affirmative) >\ ";
724
    }
725
726
    /*
727
     *   QUIT message.  We display this to acknowledge an explicit player
728
     *   command to quit the game.  This is the last message the game
729
     *   displays on the way out; there is no need to offer any options at
730
     *   this point, because the player has decided to exit the game.
731
     *   
732
     *   By default, we show nothing; games can override this to display an
733
     *   acknowledgment if desired.  Note that this isn't a general
734
     *   end-of-game 'goodbye' message; the library only shows this to
735
     *   acknowledge an explicit QUIT command from the player.  
736
     */
737
    okayQuitting() { }
738
739
    /*
740
     *   "not terminating" confirmation - this is displayed when the
741
     *   player doesn't acknowledge a 'quit' command with an affirmative
742
     *   response to our confirmation question 
743
     */
744
    notTerminating()
745
    {
746
        "<.parser>Continuing the story.<./parser> ";
747
    }
748
749
    /* confirm that they really want to restart */
750
    confirmRestart()
751
    {
752
        "Do you really want to start over?\ (<<aHref('Y', 'Y',
753
        'Confirm restart')>> is affirmative) >\ ";
754
    }
755
756
    /* "not restarting" confirmation */
757
    notRestarting() { "<.parser>Continuing the story.<./parser> "; }
758
759
    /*
760
     *   Show a game-finishing message - we use the conventional "*** You
761
     *   have won! ***" format that text games have been using since the
762
     *   dawn of time. 
763
     */
764
    showFinishMsg(msg) { "<.p>*** <<msg>>\ ***<.p>"; }
765
766
    /* standard game-ending messages for the common outcomes */
767
    finishDeathMsg = '{YOU/HE pc} {[HAVE]|} DIED'
768
    finishVictoryMsg = ('YOU ' + tSel('HAVE ', '') + 'WON')
769
    finishFailureMsg = ('YOU ' + tSel('HAVE ', '') + 'FAILED')
770
    finishGameOverMsg = 'GAME OVER'
771
772
    /*
773
     *   Get the save-game file prompt.  Note that this must return a
774
     *   single-quoted string value, not display a value itself, because
775
     *   this prompt is passed to inputFile(). 
776
     */
777
    getSavePrompt =
778
        'Please select a file in which to save the current position'
779
780
    /* get the restore-game prompt */
781
    getRestorePrompt = 'Please select the saved position file to restore'
782
783
    /* successfully saved */
784
    saveOkay() { "<.parser>Saved.<./parser> "; }
785
786
    /* save canceled */
787
    saveCanceled() { "<.parser>Canceled.<./parser> "; }
788
789
    /* saved failed due to a file write or similar error */
790
    saveFailed(exc)
791
    {
792
        "<.parser>Failed; your computer might be running low
793
        on disk space, or you might not have the necessary permissions
794
        to write this file.<./parser> ";
795
    }
796
797
    /* note that we're restoring at startup via a saved-position launch */
798
    noteMainRestore() { "<.parser>Restoring saved game...<./parser>\n"; }
799
800
    /* successfully restored */
801
    restoreOkay() { "<.parser>Restored.<./parser> "; }
802
803
    /* restore canceled */
804
    restoreCanceled() { "<.parser>Canceled.<./parser> "; }
805
806
    /* restore failed because the file was not a valid saved game file */
807
    restoreInvalidFile()
808
    {
809
        "<.parser>Failed: this is not a valid saved
810
        position file.<./parser> ";
811
    }
812
813
    /* restore failed because the file was corrupted */
814
    restoreCorruptedFile()
815
    {
816
        "<.parser>Failed: this saved state file appears to be
817
        corrupted.  This can occur if the file was modified by another
818
        program, or the file was copied between computers in a non-binary
819
        transfer mode, or the physical media storing the file were
820
        damaged.<./parser> ";
821
    }
822
823
    /* restore failed because the file was for the wrong game or version */
824
    restoreInvalidMatch()
825
    {
826
        "<.parser>Failed: the file was not saved by this
827
        story (or was saved by an incompatible version of
828
        the story).<./parser> ";
829
    }
830
831
    /* restore failed for some reason other than those distinguished above */
832
    restoreFailed(exc)
833
    {
834
        "<.parser>Failed: the position could not be
835
        restored.<./parser> ";
836
    }
837
838
    /* error showing the input file dialog (or whatever) */
839
    filePromptFailed()
840
    {
841
        "<.parser>A system error occurred asking for a filename.
842
        Your computer might be running low on memory, or might have a
843
        configuration problem.<./parser> ";
844
    }
845
846
    /* PAUSE prompt */
847
    pausePrompt()
848
    {
849
        "<.parser>The story is now paused.  Please press
850
        the space bar when you are ready to resume the story, or
851
        press the &lsquo;S&rsquo; key to save the current
852
        position.<./parser><.p>";
853
    }
854
855
    /* saving from within a pause */
856
    pauseSaving()
857
    {
858
        "<.parser>Saving the story...<./parser><.p>";
859
    }
860
861
    /* PAUSE ended */
862
    pauseEnded()
863
    {
864
        "<.parser>Resuming the story.<./parser> ";
865
    }
866
867
    /* acknowledge starting an input script */
868
    inputScriptOkay(fname)
869
    {
870
        "<.parser>Reading commands from <q><<fname.htmlify()
871
         >></q>...<./parser>\n ";
872
    }
873
874
    /* get the scripting inputFile prompt message */
875
    getScriptingPrompt = 'Please select a name for the new script file'
876
877
    /* acknowledge scripting on */
878
    scriptingOkay()
879
    {
880
        "<.parser>Text will now be saved to the script file.
881
        Type <<aHref('script off', 'SCRIPT OFF', 'Turn off scripting')>> to
882
        discontinue scripting.<./parser> ";
883
    }
884
885
    /* acknowledge cancellation of script file dialog */
886
    scriptingCanceled = "<.parser>Canceled.<./parser> "
887
888
    /* acknowledge scripting off */
889
    scriptOffOkay = "<.parser>Scripting ended.<./parser> "
890
891
    /* SCRIPT OFF ignored because we're not in a script file */
892
    scriptOffIgnored = "<.parser>No script is currently being
893
                        recorded.<./parser> "
894
895
    /* get the RECORD prompt */
896
    getRecordingPrompt = 'Please select a name for the new command log file'
897
898
    /* acknowledge recording on */
899
    recordingOkay = "<.parser>Commands will now be recorded.  Type
900
                     <<aHref('record off', 'RECORD OFF',
901
                             'Turn off recording')>>
902
                     to stop recording commands.<.parser> "
903
904
    /* acknowledge cancellation */
905
    recordingCanceled = "<.parser>Canceled.<./parser> "
906
907
    /* recording turned off */
908
    recordOffOkay = "<.parser>Command recording ended.<./parser> "
909
910
    /* RECORD OFF ignored because we're not recording commands */
911
    recordOffIgnored = "<.parser>No command recording is currently being
912
                        made.<./parser> "
913
914
    /* REPLAY prompt */
915
    getReplayPrompt = 'Please select the command log file to replay'
916
917
    /* REPLAY file selection canceled */
918
    replayCanceled = "<.parser>Canceled.<./parser> "
919
920
    /* undo command succeeded */
921
    undoOkay(actor, cmd)
922
    {
923
        "<.parser>Taking back one turn: <q>";
924
925
        /* show the target actor prefix, if an actor was specified */
926
        if (actor != nil)
927
            "<<actor>>, ";
928
929
        /* show the command */
930
        "<<cmd>></q>.<./parser><.p>";
931
    }
932
933
    /* undo command failed */
934
    undoFailed()
935
    {
936
        "<.parser>No more undo information is
937
        available.<./parser> ";
938
    }
939
940
    /* comment accepted, with or without transcript recording in effect */
941
    noteWithScript = "<.parser>Comment recorded.<./parser> "
942
    noteWithoutScript = "<.parser>Comment <b>not</b> recorded.<./parser> "
943
944
    /* on the first comment without transcript recording, warn about it */
945
    noteWithoutScriptWarning = "<.parser>Comment <b>not</b> recorded.
946
        Use <<aHref('script', 'SCRIPT', 'Begin saving the transcript')
947
          >> if you want to start recording the transcript.<./parser> "
948
949
    /* invalid finishGame response */
950
    invalidFinishOption(resp)
951
    {
952
        "\bThat isn&rsquo;t one of the options. ";
953
    }
954
955
    /* acknowledge new "exits on/off" status */
956
    exitsOnOffOkay(stat, look)
957
    {
958
        if (stat && look)
959
            "<.parser>The list of exits will now be shown in both
960
            the status line and in each room description.<./parser> ";
961
        else if (!stat && !look)
962
            "<.parser>The list of exits will no longer be shown in
963
            either the status line or room description.<./parser> ";
964
        else
965
            "<.parser>The list of exits <<stat ? 'will' : 'will not'>> be
966
            shown in the status line, and <<look ? 'will' : 'won&rsquo;t'>>
967
            be included in room descriptions.<./parser> ";
968
    }
969
970
    /* explain how to turn exit display on and off */
971
    explainExitsOnOff()
972
    {
973
        exitsTip.showTip();
974
    }
975
976
    /* describe the current EXITS settings */
977
    currentExitsSettings(statusLine, roomDesc)
978
    {
979
        "EXITS ";
980
        if (statusLine && roomDesc)
981
            "ON";
982
        else if (statusLine)
983
            "STATUSLINE";
984
        else if (roomDesc)
985
            "LOOK";
986
        else
987
            "OFF";
988
    }
989
990
    /* acknowledge HINTS OFF */
991
    hintsDisabled = '<.parser>Hints are now disabled.<./parser> '
992
993
    /* rebuff a request for hints when they've been previously disabled */
994
    sorryHintsDisabled = '<.parser>Sorry, but hints have been disabled
995
        for this session, as you requested.  If you&rsquo;ve changed your
996
        mind, you&rsquo;ll have to save your current position, exit the TADS
997
        interpreter, and start a new interpreter session.<./parser> '
998
999
    /* this game has no hints */
1000
    hintsNotPresent = '<.parser>Sorry, this story doesn&rsquo;t
1001
                       have any built-in hints.<./parser> '
1002
1003
    /* there are currently no hints available (but there might be later) */
1004
    currentlyNoHints = '<.parser>Sorry, no hints are currently available.
1005
                        Please check back later.<./parser> '
1006
1007
    /* show the hint system warning */
1008
    showHintWarning =
1009
       "<.notification>Warning: Some people don&rsquo;t like built-in hints,
1010
       since the temptation to ask for help prematurely can become
1011
       overwhelming when hints are so close at hand.  If you&rsquo;re worried
1012
       that your willpower won&rsquo;t hold up, you can disable hints for the
1013
       rest of this session by typing <<aHref('hints off', 'HINTS OFF')
1014
       >>.  If you still want to see the hints now, type
1015
       <<aHref('hint', 'HINT')>>.<./notification> "
1016
1017
    /* done with hints */
1018
    hintsDone = '<.parser>Done.<./parser> '
1019
1020
    /* optional command is not supported in this game */
1021
    commandNotPresent = "<.parser>That command isn&rsquo;t needed
1022
                         in this story.<./parser> "
1023
1024
    /* this game doesn't use scoring */
1025
    scoreNotPresent = "<.parser>This story doesn&rsquo;t use
1026
                       scoring.<./parser> "
1027
1028
    /* mention the FULL SCORE command */
1029
    mentionFullScore()
1030
    {
1031
        fullScoreTip.showTip();
1032
    }
1033
1034
    /* SAVE DEFAULTS successful */
1035
    savedDefaults()
1036
    {
1037
        "<.parser>Your current settings have been stored as the
1038
        default settings for new games.  The saved settings are: ";
1039
1040
        /* show all of the settings */
1041
        settingsUI.showAll();
1042
1043
        ".  Most newer games will apply these settings automatically
1044
        whenever you start (or RESTART) the game, but note that older
1045
        games will not.<./parser> ";
1046
    }
1047
1048
    /* RESTORE DEFAULTS successful */
1049
    restoredDefaults()
1050
    {
1051
        "<.parser>The saved default settings have been put into
1052
        effect.  The new settings are: ";
1053
1054
        /* show all of the settings */
1055
        settingsUI.showAll();
1056
1057
        ".<./parser> ";
1058
    }
1059
1060
    /* show a separator for the settingsUI.showAll() list */
1061
    settingsItemSeparator = "; "
1062
1063
    /* SAVE/RESTORE DEFAULTS not supported (old interpreter version) */
1064
    defaultsFileNotSupported = "<.parser>Sorry, but the version of the
1065
        TADS interpreter you&rsquo;re using doesn&rsquo;t support saving
1066
        or restoring defaults.  You must install a more recent version
1067
        in order to use this feature.<./parser> "
1068
1069
    /* SAVE DEFAULTS file creation error */
1070
    defaultsFileWriteError = "<.parser>An error occurred writing
1071
        the default settings file.  The defaults have not been
1072
        saved.  You might be out of disk space, or you might not
1073
        have the necessary permissions to write the file.<./parser> "
1074
1075
    /*
1076
     *   Command key list for the menu system.  This uses the format
1077
     *   defined for MenuItem.keyList in the menu system.  Keys must be
1078
     *   given as lower-case in order to match input, since the menu
1079
     *   system converts input keys to lower case before matching keys to
1080
     *   this list.  
1081
     *   
1082
     *   Note that the first item in each list is what will be given in
1083
     *   the navigation menu, which is why the fifth list contains 'ENTER'
1084
     *   as its first item, even though this will never match a key press.
1085
     */
1086
    menuKeyList = [
1087
                   ['q'],
1088
                   ['p', '[left]', '[bksp]', '[esc]'],
1089
                   ['u', '[up]'],
1090
                   ['d', '[down]'],
1091
                   ['ENTER', '\n', '[right]', ' ']
1092
                  ]
1093
1094
    /* link title for 'previous menu' navigation link */
1095
    prevMenuLink = '<font size=-1>Previous</font>'
1096
1097
    /* link title for 'next topic' navigation link in topic lists */
1098
    nextMenuTopicLink = '<font size=-1>Next</font>'
1099
1100
    /*
1101
     *   main prompt text for text-mode menus - this is displayed each
1102
     *   time we ask for a keystroke to navigate a menu in text-only mode 
1103
     */
1104
    textMenuMainPrompt(keylist)
1105
    {
1106
        "\bSelect a topic number, or press &lsquo;<<
1107
        keylist[M_PREV][1]>>&rsquo; for the previous
1108
        menu or &lsquo;<<keylist[M_QUIT][1]>>&rsquo; to quit:\ ";
1109
    }
1110
1111
    /* prompt text for topic lists in text-mode menus */
1112
    textMenuTopicPrompt()
1113
    {
1114
        "\bPress the space bar to display the next line,
1115
        &lsquo;<b>P</b>&rsquo; to go to the previous menu, or
1116
        &lsquo;<b>Q</b>&rsquo; to quit.\b";
1117
    }
1118
1119
    /*
1120
     *   Position indicator for topic list items - this is displayed after
1121
     *   a topic list item to show the current item number and the total
1122
     *   number of items in the list, to give the user an idea of where
1123
     *   they are in the overall list.  
1124
     */
1125
    menuTopicProgress(cur, tot) { " [<<cur>>/<<tot>>]"; }
1126
1127
    /*
1128
     *   Message to display at the end of a topic list.  We'll display
1129
     *   this after we've displayed all available items from a
1130
     *   MenuTopicItem's list of items, to let the user know that there
1131
     *   are no more items available.  
1132
     */
1133
    menuTopicListEnd = '[The End]'
1134
1135
    /*
1136
     *   Message to display at the end of a "long topic" in the menu
1137
     *   system.  We'll display this at the end of the long topic's
1138
     *   contents.  
1139
     */
1140
    menuLongTopicEnd = '[The End]'
1141
1142
    /*
1143
     *   instructions text for banner-mode menus - this is displayed in
1144
     *   the instructions bar at the top of the screen, above the menu
1145
     *   banner area 
1146
     */
1147
    menuInstructions(keylist, prevLink)
1148
    {
1149
        "<tab align=right ><b>\^<<keylist[M_QUIT][1]>></b>=Quit <b>\^<<
1150
        keylist[M_PREV][1]>></b>=Previous Menu<br>
1151
        <<prevLink != nil ? aHrefAlt('previous', prevLink, '') : ''>>
1152
        <tab align=right ><b>\^<<keylist[M_UP][1]>></b>=Up <b>\^<<
1153
        keylist[M_DOWN][1]>></b>=Down <b>\^<<
1154
        keylist[M_SEL][1]>></b>=Select<br>";
1155
    }
1156
1157
    /* show a 'next chapter' link */
1158
    menuNextChapter(keylist, title, hrefNext, hrefUp)
1159
    {
1160
        "Next: <a href='<<hrefNext>>'><<title>></a>;
1161
        <b>\^<<keylist[M_PREV][1]>></b>=<a href='<<hrefUp>>'>Menu</a>";
1162
    }
1163
1164
    /*
1165
     *   cannot reach (i.e., touch) an object that is to be manipulated in
1166
     *   a command - this is a generic message used when we cannot
1167
     *   identify the specific reason that the object is in scope but
1168
     *   cannot be touched 
1169
     */
1170
    cannotReachObject(obj)
1171
    {
1172
        "{You/he} {cannot} reach <<obj.theNameObj>>. ";
1173
    }
1174
1175
    /*
1176
     *   cannot reach an object, because the object is inside the given
1177
     *   container 
1178
     */
1179
    cannotReachContents(obj, loc)
1180
    {
1181
        gMessageParams(obj, loc);
1182
        return '{You/he} {cannot} reach {the obj/him} through '
1183
               + '{the loc/him}. ';
1184
    }
1185
1186
    /* cannot reach an object because it's outisde the given container */
1187
    cannotReachOutside(obj, loc)
1188
    {
1189
        gMessageParams(obj, loc);
1190
        return '{You/he} {cannot} reach {the obj/him} through '
1191
               + '{the loc/him}. ';
1192
    }
1193
1194
    /* sound is coming from inside/outside a container */
1195
    soundIsFromWithin(obj, loc)
1196
    {
1197
        "\^<<obj.theName>> appear<<obj.verbEndingSEd>> to be
1198
        coming from inside <<loc.theNameObj>>. ";
1199
    }
1200
    soundIsFromWithout(obj, loc)
1201
    {
1202
        "\^<<obj.theName>> appear<<obj.verbEndingSEd>> to be
1203
        coming from outside <<loc.theNameObj>>. ";
1204
    }
1205
1206
    /* odor is coming from inside/outside a container */
1207
    smellIsFromWithin(obj, loc)
1208
    {
1209
        "\^<<obj.theName>> appear<<obj.verbEndingSEd>> to be
1210
        coming from inside <<loc.theNameObj>>. ";
1211
    }
1212
    smellIsFromWithout(obj, loc)
1213
    {
1214
        "\^<<obj.theName>> appear<<obj.verbEndingSEd>> to be
1215
        coming from outside <<loc.theNameObj>>. ";
1216
    }
1217
1218
    /* default description of the player character */
1219
    pcDesc(actor)
1220
    {
1221
        "\^<<actor.theName>> look<<actor.verbEndingSEd>> the same
1222
        as usual. ";
1223
    }
1224
1225
    /*
1226
     *   Show a status line addendum for the actor posture, without
1227
     *   mentioning the actor's location.  We won't mention standing, since
1228
     *   this is the default posture.  
1229
     */
1230
    roomActorStatus(actor)
1231
    {
1232
        /* mention any posture other than standing */
1233
        if (actor.posture != standing)
1234
            " (<<actor.posture.participle>>)";
1235
    }
1236
1237
    /* show a status line addendum: standing in/on something */
1238
    actorInRoomStatus(actor, room)
1239
        { " (<<actor.posture.participle>> <<room.actorInName>>)"; }
1240
1241
    /* generic short description of a dark room */
1242
    roomDarkName = 'In the dark'
1243
1244
    /* generic long description of a dark room */
1245
    roomDarkDesc = "It{&rsquo;s| was} pitch black. "
1246
1247
    /*
1248
     *   mention that an actor is here, without mentioning the enclosing
1249
     *   room, as part of a room description 
1250
     */
1251
    roomActorHereDesc(actor)
1252
    {
1253
        "\^<<actor.nameIs>> <<actor.posture.participle>>
1254
        <<tSel('here', 'there')>>. ";
1255
    }
1256
1257
    /*
1258
     *   mention that an actor is visible at a distance or remotely,
1259
     *   without mentioning the enclosing room, as part of a room
1260
     *   description 
1261
     */
1262
    roomActorThereDesc(actor)
1263
    {
1264
        "\^<<actor.nameIs>> <<actor.posture.participle>> nearby. ";
1265
    }
1266
1267
    /*
1268
     *   Mention that an actor is in a given local room, as part of a room
1269
     *   description.  This is used as a default "special description" for
1270
     *   an actor.  
1271
     */
1272
    actorInRoom(actor, cont)
1273
    {
1274
        "\^<<actor.nameIs>> <<actor.posture.participle>>
1275
        <<cont.actorInName>>. ";
1276
    }
1277
1278
    /*
1279
     *   Describe an actor as standing/sitting/lying on something, as part
1280
     *   of the actor's EXAMINE description.  This is additional
1281
     *   information added to the actor's description, so we refer to the
1282
     *   actor with a pronoun ("He's standing here").  
1283
     */
1284
    actorInRoomPosture(actor, room)
1285
    {
1286
        "\^<<actor.itIs>> <<actor.posture.participle>>
1287
        <<room.actorInName>>. ";
1288
    }
1289
1290
    /*
1291
     *   Describe an actor's posture, as part of an actor's "examine"
1292
     *   description.  If the actor is standing, don't bother mentioning
1293
     *   anything, as standing is the trivial default condition.  
1294
     */
1295
    roomActorPostureDesc(actor)
1296
    {
1297
        if (actor.posture != standing)
1298
            "\^<<actor.itIs>> <<actor.posture.participle>>. ";
1299
    }
1300
1301
    /*
1302
     *   mention that the given actor is visible, at a distance or
1303
     *   remotely, in the given location; this is used in room
1304
     *   descriptions when an NPC is visible in a remote or distant
1305
     *   location 
1306
     */
1307
    actorInRemoteRoom(actor, room, pov)
1308
    {
1309
        /* say that the actor is in the room, using its remote in-name */
1310
        "\^<<actor.nameIs>> <<actor.posture.participle>>
1311
        <<room.inRoomName(pov)>>. ";
1312
    }
1313
1314
    /*
1315
     *   mention that the given actor is visible, at a distance or
1316
     *   remotely, in the given nested room within the given outer
1317
     *   location; this is used in room descriptions 
1318
     */
1319
    actorInRemoteNestedRoom(actor, inner, outer, pov)
1320
    {
1321
        /*
1322
         *   say that the actor is in the nested room, in the current
1323
         *   posture, and add then add that we're in the outer room as
1324
         *   well 
1325
         */
1326
        "\^<<actor.nameIs>> <<outer.inRoomName(pov)>>,
1327
        <<actor.posture.participle>> <<inner.actorInName>>. ";
1328
    }
1329
1330
    /*
1331
     *   Prefix/suffix messages for listing actors in a room description,
1332
     *   for cases when the actors are in the local room in a nominal
1333
     *   container that we want to mention: "Bob and Bill are sitting on
1334
     *   the couch."  
1335
     */
1336
    actorInGroupPrefix(posture, cont, lst) { "\^"; }
1337
    actorInGroupSuffix(posture, cont, lst)
1338
    {
1339
        " <<lst.length() == 1 ? tSel('is', 'was') : tSel('are', 'were')>>
1340
        <<posture.participle>> <<cont.actorInName>>. ";
1341
    }
1342
1343
    /*
1344
     *   Prefix/suffix messages for listing actors in a room description,
1345
     *   for cases when the actors are inside a nested room that's inside
1346
     *   a remote location: "Bob and Bill are in the courtyard, sitting on
1347
     *   the bench." 
1348
     */
1349
    actorInRemoteGroupPrefix(pov, posture, cont, remote, lst) { "\^"; }
1350
    actorInRemoteGroupSuffix(pov, posture, cont, remote, lst)
1351
    {
1352
        " <<lst.length() == 1 ? tSel('is', 'was') : tSel('are', 'were')>>
1353
        <<remote.inRoomName(pov)>>, <<posture.participle>>
1354
        <<cont.actorInName>>. ";
1355
    }
1356
1357
    /*
1358
     *   Prefix/suffix messages for listing actors in a room description,
1359
     *   for cases when the actors' nominal container cannot be seen or is
1360
     *   not to be stated: "Bob and Bill are standing here."
1361
     *   
1362
     *   Note that we don't always want to state the nominal container,
1363
     *   even when it's visible.  For example, when actors are standing on
1364
     *   the floor, we don't bother saying that they're on the floor, as
1365
     *   that's stating the obvious.  The container will decide whether or
1366
     *   not it wants to be included in the message; containers that don't
1367
     *   want to be mentioned will use this form of the message.  
1368
     */
1369
    actorHereGroupPrefix(posture, lst) { "\^"; }
1370
    actorHereGroupSuffix(posture, lst)
1371
    {
1372
        " <<lst.length() == 1 ? tSel('is', 'was') : tSel('are', 'were')>>
1373
        <<posture.participle>> <<tSel('here', 'there')>>. ";
1374
    }
1375
1376
    /*
1377
     *   Prefix/suffix messages for listing actors in a room description,
1378
     *   for cases when the actors' immediate container cannot be seen or
1379
     *   is not to be stated, and the actors are in a remote location:
1380
     *   "Bob and Bill are in the courtyard."  
1381
     */
1382
    actorThereGroupPrefix(pov, posture, remote, lst) { "\^"; }
1383
    actorThereGroupSuffix(pov, posture, remote, lst)
1384
    {
1385
        " <<lst.length() == 1 ? tSel('is', 'was') : tSel('are', 'were')>>
1386
        <<posture.participle>> <<remote.inRoomName(pov)>>. ";
1387
    }
1388
1389
    /* a traveler is arriving, but not from a compass direction */
1390
    sayArriving(traveler)
1391
    {
1392
        "\^<<traveler.travelerName(true)>> enter<<traveler.verbEndingSEd>>
1393
        <<traveler.travelerLocName>>. ";
1394
    }
1395
1396
    /* a traveler is departing, but not in a compass direction */
1397
    sayDeparting(traveler)
1398
    {
1399
        "\^<<traveler.travelerName(nil)>> <<traveler.verbToLeave>>
1400
        <<traveler.travelerLocName>>. ";
1401
    }
1402
1403
    /*
1404
     *   a traveler is arriving locally (staying within view throughout the
1405
     *   travel, and coming closer to the PC) 
1406
     */
1407
    sayArrivingLocally(traveler, dest)
1408
    {
1409
        "\^<<traveler.travelerName(true)>> enter<<traveler.verbEndingSEd>>
1410
        <<traveler.travelerLocName>>. ";
1411
    }
1412
1413
    /*
1414
     *   a traveler is departing locally (staying within view throughout
1415
     *   the travel, and moving further away from the PC) 
1416
     */
1417
    sayDepartingLocally(traveler, dest)
1418
    {
1419
        "\^<<traveler.travelerName(true)>> <<traveler.verbToLeave>>
1420
        <<traveler.travelerLocName>>. ";
1421
    }
1422
1423
    /*
1424
     *   a traveler is traveling remotely (staying within view through the
1425
     *   travel, and moving from one remote top-level location to another) 
1426
     */
1427
    sayTravelingRemotely(traveler, dest)
1428
    {
1429
        "\^<<traveler.travelerName(true)>> <<traveler.verbToGo>> to
1430
        <<traveler.travelerLocName>>. ";
1431
    }
1432
1433
    /* a traveler is arriving from a compass direction */
1434
    sayArrivingDir(traveler, dirName)
1435
    {
1436
        "\^<<traveler.travelerName(true)>> enter<<traveler.verbEndingSEd>>
1437
        <<traveler.travelerRemoteLocName>> from the <<dirName>>. ";
1438
    }
1439
1440
    /* a traveler is leaving in a given compass direction */
1441
    sayDepartingDir(traveler, dirName)
1442
    {
1443
        local nm = traveler.travelerRemoteLocName;
1444
        
1445
        "\^<<traveler.travelerName(nil)>> <<traveler.verbToLeave>>
1446
        to the <<dirName>><<nm != '' ? ' from ' + nm : ''>>. ";
1447
    }
1448
    
1449
    /* a traveler is arriving from a shipboard direction */
1450
    sayArrivingShipDir(traveler, dirName)
1451
    {
1452
        "\^<<traveler.travelerName(true)>> enter<<traveler.verbEndingSEd>>
1453
        <<traveler.travelerRemoteLocName>> from <<dirName>>. ";
1454
    }
1455
1456
    /* a traveler is leaving in a given shipboard direction */
1457
    sayDepartingShipDir(traveler, dirName)
1458
    {
1459
        local nm = traveler.travelerRemoteLocName;
1460
        
1461
        "\^<<traveler.travelerName(nil)>> <<traveler.verbToLeave>>
1462
        to <<dirName>><<nm != '' ? ' from ' + nm : ''>>. ";
1463
    }
1464
1465
    /* a traveler is going aft */
1466
    sayDepartingAft(traveler)
1467
    {
1468
        local nm = traveler.travelerRemoteLocName;
1469
        
1470
        "\^<<traveler.travelerName(nil)>> <<traveler.verbToGo>>
1471
        aft<<nm != '' ? ' from ' + nm : ''>>. ";
1472
    }
1473
1474
    /* a traveler is going fore */
1475
    sayDepartingFore(traveler)
1476
    {
1477
        local nm = traveler.travelerRemoteLocName;
1478
1479
        "\^<<traveler.travelerName(nil)>> <<traveler.verbToGo>>
1480
        forward<<nm != '' ? ' from ' + nm : ''>>. ";
1481
    }
1482
1483
    /* a shipboard direction was attempted while not onboard a ship */
1484
    notOnboardShip = "That direction {is|was}n&rsquo;t meaningful {|t}here. "
1485
1486
    /* a traveler is leaving via a passage */
1487
    sayDepartingThroughPassage(traveler, passage)
1488
    {
1489
        "\^<<traveler.travelerName(nil)>> <<traveler.verbToLeave>>
1490
        <<traveler.travelerRemoteLocName>> through <<passage.theNameObj>>. ";
1491
    }
1492
1493
    /* a traveler is arriving via a passage */
1494
    sayArrivingThroughPassage(traveler, passage)
1495
    {
1496
        "\^<<traveler.travelerName(true)>> enter<<traveler.verbEndingSEd>>
1497
        <<traveler.travelerRemoteLocName>> through <<passage.theNameObj>>. ";
1498
    }
1499
1500
    /* a traveler is leaving via a path */
1501
    sayDepartingViaPath(traveler, passage)
1502
    {
1503
        "\^<<traveler.travelerName(nil)>> <<traveler.verbToLeave>>
1504
        <<traveler.travelerRemoteLocName>> via <<passage.theNameObj>>. ";
1505
    }
1506
1507
    /* a traveler is arriving via a path */
1508
    sayArrivingViaPath(traveler, passage)
1509
    {
1510
        "\^<<traveler.travelerName(true)>> enter<<traveler.verbEndingSEd>>
1511
        <<traveler.travelerRemoteLocName>> via <<passage.theNameObj>>. ";
1512
    }
1513
1514
    /* a traveler is leaving up a stairway */
1515
    sayDepartingUpStairs(traveler, stairs)
1516
    {
1517
        "\^<<traveler.travelerName(nil)>> <<traveler.verbToGo>>
1518
        up <<stairs.theNameObj>>. ";
1519
    }
1520
1521
    /* a traveler is leaving down a stairway */
1522
    sayDepartingDownStairs(traveler, stairs)
1523
    {
1524
        "\^<<traveler.travelerName(nil)>> <<traveler.verbToGo>>
1525
        down <<stairs.theNameObj>>. ";
1526
    }
1527
1528
    /* a traveler is arriving by coming up a stairway */
1529
    sayArrivingUpStairs(traveler, stairs)
1530
    {
1531
        local nm = traveler.travelerRemoteLocName;
1532
1533
        "\^<<traveler.travelerName(true)>> <<traveler.verbToCome>>
1534
        up <<stairs.theNameObj>><<nm != '' ? ' to ' + nm : ''>>. ";
1535
    }
1536
1537
    /* a traveler is arriving by coming down a stairway */
1538
    sayArrivingDownStairs(traveler, stairs)
1539
    {
1540
        local nm = traveler.travelerRemoteLocName;
1541
1542
        "\^<<traveler.travelerName(true)>> <<traveler.verbToCome>>
1543
        down <<stairs.theNameObj>><<nm != '' ? ' to ' + nm : ''>>. ";
1544
    }
1545
1546
    /* acompanying another actor on travel */
1547
    sayDepartingWith(traveler, lead)
1548
    {
1549
        "\^<<traveler.travelerName(nil)>> <<traveler.verbToCome>>
1550
        with <<lead.theNameObj>>. ";
1551
    }
1552
1553
    /*
1554
     *   Accompanying a tour guide.  Note the seemingly reversed roles:
1555
     *   the lead actor is the one initiating the travel, and the tour
1556
     *   guide is the accompanying actor.  So, the lead actor is
1557
     *   effectively following the accompanying actor.  It seems
1558
     *   backwards, but really it's not: the tour guide merely shows the
1559
     *   lead actor where to go, but it's up to the lead actor to actually
1560
     *   initiate the travel.  
1561
     */
1562
    sayDepartingWithGuide(guide, lead)
1563
    {
1564
        "\^<<lead.theName>> let<<tSel(lead.verbEndingS, '')>>
1565
        <<guide.theNameObj>> lead the way. ";
1566
    }
1567
1568
    /* note that a door is being opened/closed remotely */
1569
    sayOpenDoorRemotely(door, stat)
1570
    {
1571
        "Someone <<stat ? 'open' + tSel('s', 'ed')
1572
                        : 'close' + tSel('s', 'd')>>
1573
        <<door.theNameObj>> from the other side. ";
1574
    }
1575
1576
    /*
1577
     *   open/closed status - these are simply adjectives that can be used
1578
     *   to describe the status of an openable object 
1579
     */
1580
    openMsg(obj) { return 'open'; }
1581
    closedMsg(obj) { return 'closed'; }
1582
1583
    /* object is currently open/closed */
1584
    currentlyOpen = '{It\'s dobj} currently open. '
1585
    currentlyClosed = '{It\'s dobj} currently closed. '
1586
1587
    /* stand-alone independent clause describing current open status */
1588
    openStatusMsg(obj) { return obj.itIsContraction + ' ' + obj.openDesc; }
1589
1590
    /* locked/unlocked status - adjectives describing lock states */
1591
    lockedMsg(obj) { return 'locked'; }
1592
    unlockedMsg(obj) { return 'unlocked'; }
1593
1594
    /* object is currently locked/unlocked */
1595
    currentlyLocked = '{It\'s dobj} currently locked. '
1596
    currentlyUnlocked = '{It\'s dobj} currently unlocked. '
1597
1598
    /*
1599
     *   on/off status - these are simply adjectives that can be used to
1600
     *   describe the status of a switchable object 
1601
     */
1602
    onMsg(obj) { return 'on'; }
1603
    offMsg(obj) { return 'off'; }
1604
1605
    /* daemon report for burning out a match */
1606
    matchBurnedOut(obj)
1607
    {
1608
        gMessageParams(obj);
1609
        "{The obj/he} finish{es/ed} burning, and disappear{s/ed} into a
1610
        cloud of ash. ";
1611
    }
1612
1613
    /* daemon report for burning out a candle */
1614
    candleBurnedOut(obj)
1615
    {
1616
        gMessageParams(obj);
1617
        "{The obj/he} burn{s/ed} down too far to stay lit, and {goes}
1618
        out. ";
1619
    }
1620
1621
    /* daemon report for burning out a generic fueled light source */
1622
    objBurnedOut(obj)
1623
    {
1624
        gMessageParams(obj);
1625
        "{The obj/he} {goes} out. ";
1626
    }
1627
;
1628
1629
/* ------------------------------------------------------------------------ */
1630
/*
1631
 *   Player Character messages.  These messages are generated when the
1632
 *   player issues a regular command to the player character (i.e.,
1633
 *   without specifying a target actor).  
1634
 */
1635
playerMessages: libMessages
1636
    /* invalid command syntax */
1637
    commandNotUnderstood(actor)
1638
    {
1639
        "<.parser>The story doesn&rsquo;t understand that
1640
        command.<./parser> ";
1641
    }
1642
1643
    /* a special topic can't be used right now, because it's inactive */
1644
    specialTopicInactive(actor)
1645
    {
1646
        "<.parser>That command can&rsquo;t be used right now.<./parser> ";
1647
    }
1648
1649
    /* no match for a noun phrase */
1650
    noMatch(actor, action, txt) { action.noMatch(self, actor, txt); }
1651
1652
    /*
1653
     *   No match message - we can't see a match for the noun phrase.  This
1654
     *   is the default for most verbs. 
1655
     */
1656
    noMatchCannotSee(actor, txt)
1657
        { "{You/he} {sees} no <<txt>> {|t}here. "; }
1658
1659
    /*
1660
     *   No match message - we're not aware of a match for the noun phrase.
1661
     *   Some sensory actions, such as LISTEN TO and SMELL, use this
1662
     *   variation instead of the normal version; the things these commands
1663
     *   refer to tend to be intangible, so "you can't see that" tends to
1664
     *   be nonsensical. 
1665
     */
1666
    noMatchNotAware(actor, txt)
1667
        { "{You/he} {are} not aware of any <<txt>> {|t}here. "; }
1668
1669
    /* 'all' is not allowed with the attempted action */
1670
    allNotAllowed(actor)
1671
    {
1672
        "<.parser><q>All</q> cannot be used with that verb.<./parser> ";
1673
    }
1674
1675
    /* no match for 'all' */
1676
    noMatchForAll(actor)
1677
    {
1678
        "<.parser>{You/he} {sees} nothing suitable {|t}here.<./parser> ";
1679
    }
1680
1681
    /* nothing left for 'all' after removing 'except' items */
1682
    noMatchForAllBut(actor)
1683
    {
1684
        "<.parser>{You/he} {sees} nothing else
1685
        {|t}here.<./parser> ";
1686
    }
1687
1688
    /* nothing left in a plural phrase after removing 'except' items */
1689
    noMatchForListBut(actor) { noMatchForAllBut(actor); }
1690
1691
    /* no match for a pronoun */
1692
    noMatchForPronoun(actor, typ, pronounWord)
1693
    {
1694
        /* show the message */
1695
        "<.parser>The word <q><<pronounWord>></q> doesn&rsquo;t refer to
1696
        anything right now.<./parser> ";
1697
    }
1698
1699
    /*
1700
     *   Ask for a missing object - this is called when a command is
1701
     *   completely missing a noun phrase for one of its objects.  
1702
     */
1703
    askMissingObject(actor, action, which)
1704
    {
1705
        reportQuestion('<.parser>\^' + action.whatObj(which)
1706
                       + ' do you want '
1707
                       + (actor.referralPerson == ThirdPerson
1708
                          ? actor.theName : '')
1709
                       + ' to '
1710
                       + action.getQuestionInf(which) + '?<./parser> ');
1711
    }
1712
1713
    /*
1714
     *   An object was missing - this is called under essentially the same
1715
     *   circumstances as askMissingObject, but in cases where interactive
1716
     *   resolution is impossible and we simply wish to report the problem
1717
     *   and do not wish to ask for help.
1718
     */
1719
    missingObject(actor, action, which)
1720
    {
1721
        "<.parser>You need to be more specific
1722
        about <<action.whatObj(which)>> you want
1723
        <<actor.referralPerson == ThirdPerson ? actor.theName : ''>>
1724
        to <<action.getQuestionInf(which)>>.<./parser> ";
1725
    }
1726
1727
    /*
1728
     *   Ask for a missing literal phrase. 
1729
     */
1730
    askMissingLiteral(actor, action, which)
1731
    {
1732
        /* use the standard missing-object message */
1733
        askMissingObject(actor, action, which);
1734
    }
1735
1736
    /*
1737
     *   Show the message for a missing literal phrase.
1738
     */
1739
    missingLiteral(actor, action, which)
1740
    {
1741
        "<.parser>Please be more specific
1742
        about <<action.whatObj(which)>> to
1743
        <<action.getQuestionInf(which)>>.  Try, for example,
1744
        <<action.getQuestionInf(which)>> <q>something</q>.<./parser> ";
1745
    }
1746
1747
    /* reflexive pronoun not allowed */
1748
    reflexiveNotAllowed(actor, typ, pronounWord)
1749
    {
1750
        "<.parser>The story doesn&rsquo;t understand how to use the word
1751
        <q><<pronounWord>></q> like that.<./parser> ";
1752
    }
1753
1754
    /*
1755
     *   a reflexive pronoun disagrees in gender, number, or something
1756
     *   else with its referent 
1757
     */
1758
    wrongReflexive(actor, typ, pronounWord)
1759
    {
1760
        "<.parser>The story doesn&rsquo;t understand what the
1761
        word <q><<pronounWord>></q> refers to.<./parser> ";
1762
    }
1763
1764
    /* no match for a possessive phrase */
1765
    noMatchForPossessive(actor, owner, txt)
1766
    {
1767
        "<.parser>\^<<owner.nameDoes>>
1768
        not appear to have any such thing.<./parser> ";
1769
    }
1770
1771
    /* no match for a plural possessive phrase */
1772
    noMatchForPluralPossessive(actor, txt)
1773
    {
1774
        "<.parser>\^They <<tSel('do', 'did')>> not appear to have any such
1775
        thing.<./parser> ";
1776
    }
1777
1778
    /* no match for a containment phrase */
1779
    noMatchForLocation(actor, loc, txt)
1780
    {
1781
        "<.parser>\^<<actor.nameSees>>
1782
        no <<loc.childInName(txt)>>.<./parser> ";
1783
    }
1784
1785
    /* nothing in a container whose contents are specifically requested */
1786
    nothingInLocation(actor, loc)
1787
    {
1788
        "<.parser>\^<<actor.nameSees>>
1789
        <<loc.childInName('nothing unusual')>>.<./parser> ";
1790
    }
1791
1792
    /* no match for the response to a disambiguation question */
1793
    noMatchDisambig(actor, origPhrase, disambigResponse)
1794
    {
1795
        /*
1796
         *   show the message, leaving the <.parser> tag mode open - we
1797
         *   always show another disambiguation prompt after this message,
1798
         *   so we'll let the prompt close the <.parser> mode 
1799
         */
1800
        "<.parser>That was not one of the choices. ";
1801
    }
1802
1803
    /* empty noun phrase ('take the') */
1804
    emptyNounPhrase(actor)
1805
    {
1806
        "<.parser>You seem to have left out some words.<./parser> ";
1807
    }
1808
1809
    /* 'take zero books' */
1810
    zeroQuantity(actor, txt)
1811
    {
1812
        "<.parser>\^<<actor.theName>> <<actor.verbCant>> do that to zero of
1813
        something.<./parser> ";
1814
    }
1815
1816
    /* insufficient quantity to meet a command request ('take five books') */
1817
    insufficientQuantity(actor, txt, matchList, requiredNum)
1818
    {
1819
        "<.parser>\^<<actor.nameDoes>>n&rsquo;t see that many
1820
        <<txt>> <<tSel('here', 'there')>>.<./parser> ";
1821
    }
1822
1823
    /* a unique object is required, but multiple objects were specified */
1824
    uniqueObjectRequired(actor, txt, matchList)
1825
    {
1826
        "<.parser>You can&rsquo;t use multiple objects there.<./parser> ";
1827
    }
1828
1829
    /* a single noun phrase is required, but a noun list was used */
1830
    singleObjectRequired(actor, txt)
1831
    {
1832
        "<.parser>Multiple objects aren&rsquo;t allowed with that
1833
        command.<./parser> ";
1834
    }
1835
1836
    /*
1837
     *   The answer to a disambiguation question specifies an invalid
1838
     *   ordinal ("the fourth one" when only three choices were offered).
1839
     *   
1840
     *   'ordinalWord' is the ordinal word entered ('fourth' or the like).
1841
     *   'originalText' is the text of the noun phrase that caused the
1842
     *   disambiguation question to be asked in the first place.  
1843
     */
1844
    disambigOrdinalOutOfRange(actor, ordinalWord, originalText)
1845
    {
1846
        /* leave the <.parser> tag open, for the re-prompt that will follow */
1847
        "<.parser>There were not that many choices. ";
1848
    }
1849
1850
    /*
1851
     *   Ask the canonical disambiguation question: "Which x do you
1852
     *   mean...?".  'matchList' is the list of ambiguous objects with any
1853
     *   redundant equivalents removed; and 'fullMatchList' is the full
1854
     *   list, including redundant equivalents that were removed from
1855
     *   'matchList'.
1856
     *   
1857
     *   If askingAgain is true, it means that we're asking the question
1858
     *   again because we got an invalid response to the previous attempt
1859
     *   at the same prompt.  We will have explained the problem, and now
1860
     *   we're going to give the user another crack at the same response.
1861
     *   
1862
     *   To prevent interactive disambiguation, do this:
1863
     *   
1864
     *   throw new ParseFailureException(&ambiguousNounPhrase,
1865
     *.  originalText, matchList, fullMatchList); 
1866
     */
1867
    askDisambig(actor, originalText, matchList, fullMatchList,
1868
                requiredNum, askingAgain, dist)
1869
    {
1870
        /* mark this as a question report with a dummy report */
1871
        reportQuestion('');
1872
        
1873
        /*
1874
         *   Open the "<.parser>" tag, if we're not "asking again."  If we
1875
         *   are asking again, we will already have shown a message
1876
         *   explaining why we're asking again, and that message will have
1877
         *   left us in <.parser> tag mode, so we don't need to open the
1878
         *   tag again. 
1879
         */
1880
        if (!askingAgain)
1881
            "<.parser>";
1882
        
1883
        /*
1884
         *   the question varies depending on whether we want just one
1885
         *   object or several objects in the final result 
1886
         */
1887
        if (requiredNum == 1)
1888
        {
1889
            /*
1890
             *   One object needed - use the original text in the query.
1891
             *   
1892
             *   Note that if we're "asking again," we will have shown an
1893
             *   additional message first explaining *why* we're asking
1894
             *   again, and that message will have left us in <.parser>
1895
             *   tag mode; so we need to close the <.parser> tag in this
1896
             *   case, but we don't need to show a new one. 
1897
             */
1898
            if (askingAgain)
1899
                "Which did you mean,
1900
                <<askDisambigList(matchList, fullMatchList, nil, dist)>>?";
1901
            else
1902
                "Which <<originalText>> do you mean,
1903
                <<askDisambigList(matchList, fullMatchList, nil, dist)>>?";
1904
        }
1905
        else
1906
        {
1907
            /*
1908
             *   Multiple objects required - ask by number, since we can't
1909
             *   easily guess what the plural might be given the original
1910
             *   text.
1911
             *   
1912
             *   As above, we only need to *close* the <.parser> tag if
1913
             *   we're asking again, because we will already have shown a
1914
             *   prompt that opened the tag in this case.  
1915
             */
1916
            if (askingAgain)
1917
                "Which <<spellInt(requiredNum)>> (of
1918
                <<askDisambigList(matchList, fullMatchList, true, dist)>>)
1919
                did you mean?";
1920
            else
1921
                "Which <<spellInt(requiredNum)>>
1922
                (of <<askDisambigList(matchList, fullMatchList,
1923
                                      true, dist)>>) do you mean?";
1924
        }
1925
1926
        /* close the <.parser> tag */
1927
        "<./parser> ";
1928
    }
1929
1930
    /*
1931
     *   we found an ambiguous noun phrase, but we were unable to perform
1932
     *   interactive disambiguation 
1933
     */
1934
    ambiguousNounPhrase(actor, originalText, matchList, fullMatchList)
1935
    {
1936
        "<.parser>The story doesn&rsquo;t know which
1937
        <<originalText>> you mean.<./parser> ";
1938
    }
1939
1940
    /* the actor is missing in a command */
1941
    missingActor(actor)
1942
    {
1943
        "<.parser>You must be more specific about <<
1944
        whomPronoun>> you want<<tSel('', 'ed')>> to address.<./parser> ";
1945
    }
1946
1947
    /* only a single actor can be addressed at a time */
1948
    singleActorRequired(actor)
1949
    {
1950
        "<.parser>You can only address one person at a time.<./parser> ";
1951
    }
1952
1953
    /* cannot change actor mid-command */
1954
    cannotChangeActor()
1955
    {
1956
        "<.parser>You cannot address more than one character on
1957
        a single command line in this story.<./parser> ";
1958
    }
1959
1960
    /*
1961
     *   tell the user they entered a word we don't know, offering the
1962
     *   chance to correct it with "oops" 
1963
     */
1964
    askUnknownWord(actor, txt)
1965
    {
1966
        /* start the message */
1967
        "<.parser>The word <q><<txt>></q> is not necessary in this
1968
        story.<./parser> ";
1969
1970
        /* mention the OOPS command, if appropriate */
1971
        oopsNote();
1972
    }
1973
1974
    /*
1975
     *   tell the user they entered a word we don't know, but don't offer
1976
     *   an interactive way to fix it (i.e., we can't use OOPS at this
1977
     *   point) 
1978
     */
1979
    wordIsUnknown(actor, txt)
1980
    {
1981
        "<.parser>The story doesn&rsquo;t understand that
1982
        command.<./parser> ";
1983
    }
1984
1985
    /* the actor refuses the command because it's busy with something else */
1986
    refuseCommandBusy(targetActor, issuingActor)
1987
    {
1988
        "\^<<targetActor.nameIs>> busy. ";
1989
    }
1990
1991
    /* cannot speak to multiple actors */
1992
    cannotAddressMultiple(actor)
1993
    {
1994
        "<.parser>\^<<actor.theName>> <<actor.verbCannot>> address multiple
1995
        people at once.<./parser> ";
1996
    }
1997
1998
    /* 
1999
     *   Remaining actions on the command line were aborted due to the
2000
     *   failure of the current action.  This is just a hook for the game's
2001
     *   use, if it wants to provide an explanation; by default, we do
2002
     *   nothing.  Note that games that override this will probably want to
2003
     *   use a flag property so that they only show this message once -
2004
     *   it's really only desirable to explain the the mechanism, not to
2005
     *   flag it every time it's used.  
2006
     */
2007
    explainCancelCommandLine()
2008
    {
2009
    }
2010
;
2011
2012
/* ------------------------------------------------------------------------ */
2013
/*
2014
 *   Non-Player Character (NPC) messages - parser-mediated format.  These
2015
 *   versions of the NPC messages report errors through the
2016
 *   parser/narrator.
2017
 *   
2018
 *   Note that a separate set of messages can be selected to report
2019
 *   messages in the voice of the NPC - see npcMessagesDirect below.  
2020
 */
2021
2022
/*
2023
 *   Standard Non-Player Character (NPC) messages.  These messages are
2024
 *   generated when the player issues a command to a specific non-player
2025
 *   character. 
2026
 */
2027
npcMessages: playerMessages
2028
    /* the target cannot hear a command we gave */
2029
    commandNotHeard(actor)
2030
    {
2031
        "\^<<actor.nameDoes>> not respond. ";
2032
    }
2033
2034
    /* no match for a noun phrase */
2035
    noMatchCannotSee(actor, txt)
2036
        { "\^<<actor.nameSees>> no <<txt>>. "; }
2037
    noMatchNotAware(actor, txt)
2038
        { "\^<<actor.nameIs>> not aware of any <<txt>>. "; }
2039
2040
    /* no match for 'all' */
2041
    noMatchForAll(actor)
2042
    {
2043
        "<.parser>\^<<actor.nameDoes>>n&rsquo;t see anything
2044
        suitable.<./parser> ";
2045
    }
2046
2047
    /* nothing left for 'all' after removing 'except' items */
2048
    noMatchForAllBut(actor)
2049
    {
2050
        "<.parser>\^<<actor.nameSees>> nothing
2051
        else.<./parser> ";
2052
    }
2053
2054
    /* insufficient quantity to meet a command request ('take five books') */
2055
    insufficientQuantity(actor, txt, matchList, requiredNum)
2056
    {
2057
        "<.parser>\^<<actor.nameDoes>>n&rsquo;t see that many
2058
         <<txt>>.<./parser> ";
2059
    }
2060
2061
    /*
2062
     *   we found an ambiguous noun phrase, but we were unable to perform
2063
     *   interactive disambiguation 
2064
     */
2065
    ambiguousNounPhrase(actor, originalText, matchList, fullMatchList)
2066
    {
2067
        "<.parser>\^<<actor.nameDoes>>n&rsquo;t know which
2068
        <<originalText>> you mean<<tSel('', 't')>>.<./parser> ";
2069
    }
2070
2071
    /*
2072
     *   Missing object query and error message templates 
2073
     */
2074
    askMissingObject(actor, action, which)
2075
    {
2076
        reportQuestion('<.parser>\^' + action.whatObj(which)
2077
                       + ' do you want ' + actor.theNameObj + ' to '
2078
                       + action.getQuestionInf(which) + '?<./parser> ');
2079
    }
2080
    missingObject(actor, action, which)
2081
    {
2082
        "<.parser>You must be more specific
2083
        about <<action.whatObj(which)>> you want <<actor.theNameObj>> to
2084
        <<action.getQuestionInf(which)>>.<./parser> ";
2085
    }
2086
2087
    /* missing literal phrase query and error message templates */
2088
    missingLiteral(actor, action, which)
2089
    {
2090
        "<.parser>You must be more specific about <<action.whatObj(which)>>
2091
        you want <<actor.theNameObj>> to <<action.getQuestionInf(which)>>.
2092
        For example: <<actor.theName>>, <<action.getQuestionInf(which)>>
2093
        <q>something</q>.<./parser> ";
2094
    }
2095
;
2096
2097
/*
2098
 *   Deferred NPC messages.  We use this to report deferred messages from
2099
 *   an NPC to the player.  A message is deferred when a parsing error
2100
 *   occurs, but the NPC can't talk to the player because there's no sense
2101
 *   path to the player.  When this happens, the NPC queues the message
2102
 *   for eventual delivery; when a sense path appears later that lets the
2103
 *   NPC talk to the player, we deliver the message through this object.
2104
 *   Since these messages describe conditions that occurred in the past,
2105
 *   we use the past tense to phrase the messages.
2106
 *   
2107
 *   This default implementation simply doesn't report deferred errors at
2108
 *   all.  The default message voice is the parser/narrator character, and
2109
 *   there is simply no good way for the parser/narrator to say that a
2110
 *   command failed in the past for a given character: "Bob looks like he
2111
 *   didn't know which box you meant" just doesn't work.  So, we'll simply
2112
 *   not report these errors at all.
2113
 *   
2114
 *   To report messages in the NPC's voice directly, modify the NPC's
2115
 *   Actor object, or the Actor base class, to return
2116
 *   npcDeferredMessagesDirect rather than this object from
2117
 *   getParserMessageObj().  
2118
 */
2119
npcDeferredMessages: object
2120
;
2121
2122
/* ------------------------------------------------------------------------ */
2123
/*
2124
 *   NPC messages, reported directly in the voice of the NPC.  These
2125
 *   messages are not selected by default, but a game can use them instead
2126
 *   of the parser-mediated versions by modifying the actor object's
2127
 *   getParserMessageObj() to return these objects.  
2128
 */
2129
2130
/*
2131
 *   Standard Non-Player Character (NPC) messages.  These messages are
2132
 *   generated when the player issues a command to a specific non-player
2133
 *   character. 
2134
 */
2135
npcMessagesDirect: npcMessages
2136
    /* no match for a noun phrase */
2137
    noMatchCannotSee(actor, txt)
2138
    {
2139
        "\^<<actor.nameVerb('look')>> around. <q>I don&rsquo;t
2140
        see any <<txt>>.</q> ";
2141
    }
2142
    noMatchNotAware(actor, txt)
2143
    {
2144
        "<q>I&rsquo;m not aware of any <<txt>>,</q> <<actor.nameSays>>. ";
2145
    }
2146
2147
    /* no match for 'all' */
2148
    noMatchForAll(actor)
2149
    {
2150
        "\^<<actor.nameSays>>, <q>I don&rsquo;t see anything suitable.</q> ";
2151
    }
2152
2153
    /* nothing left for 'all' after removing 'except' items */
2154
    noMatchForAllBut(actor)
2155
    {
2156
        "\^<<actor.nameSays>>, <q>I see nothing else here.</q> ";
2157
    }
2158
2159
    /* 'take zero books' */
2160
    zeroQuantity(actor, txt)
2161
    {
2162
        "\^<<actor.nameSays>>,
2163
        <q>I can&rsquo;t do that to zero of something.</q> ";
2164
    }
2165
2166
    /* insufficient quantity to meet a command request ('take five books') */
2167
    insufficientQuantity(actor, txt, matchList, requiredNum)
2168
    {
2169
        "\^<<actor.nameSays>>,
2170
        <q>I don&rsquo;t see that many <<txt>> here.</q> ";
2171
    }
2172
2173
    /* a unique object is required, but multiple objects were specified */
2174
    uniqueObjectRequired(actor, txt, matchList)
2175
    {
2176
        "\^<<actor.nameSays>>,
2177
        <q>I can&rsquo;t use multiple objects like that.</q> ";
2178
    }
2179
2180
    /* a single noun phrase is required, but a noun list was used */
2181
    singleObjectRequired(actor, txt)
2182
    {
2183
        "\^<<actor.nameSays>>,
2184
        <q>I can&rsquo;t use multiple objects like that.</q> ";
2185
    }
2186
2187
    /* no match for the response to a disambiguation question */
2188
    noMatchDisambig(actor, origPhrase, disambigResponse)
2189
    {
2190
        /* leave the quote open for the re-prompt */
2191
        "\^<<actor.nameSays>>,
2192
        <q>That was not one of the choices. ";
2193
    }
2194
2195
    /*
2196
     *   The answer to a disambiguation question specifies an invalid
2197
     *   ordinal ("the fourth one" when only three choices were offered).
2198
     *   
2199
     *   'ordinalWord' is the ordinal word entered ('fourth' or the like).
2200
     *   'originalText' is the text of the noun phrase that caused the
2201
     *   disambiguation question to be asked in the first place.  
2202
     */
2203
    disambigOrdinalOutOfRange(actor, ordinalWord, originalText)
2204
    {
2205
        /* leave the quote open for the re-prompt */
2206
        "\^<<actor.nameSays>>,
2207
        <q>There weren&rsquo;t that many choices. ";
2208
    }
2209
2210
    /*
2211
     *   Ask the canonical disambiguation question: "Which x do you
2212
     *   mean...?".  'matchList' is the list of ambiguous objects with any
2213
     *   redundant equivalents removed, and 'fullMatchList' is the full
2214
     *   list, including redundant equivalents that were removed from
2215
     *   'matchList'.  
2216
     *   
2217
     *   To prevent interactive disambiguation, do this:
2218
     *   
2219
     *   throw new ParseFailureException(&ambiguousNounPhrase,
2220
     *.  originalText, matchList, fullMatchList); 
2221
     */
2222
    askDisambig(actor, originalText, matchList, fullMatchList,
2223
                requiredNum, askingAgain, dist)
2224
    {
2225
        /* mark this as a question report */
2226
        reportQuestion('');
2227
2228
        /* the question depends on the number needed */
2229
        if (requiredNum == 1)
2230
        {
2231
            /* one required - ask with the original text */
2232
            if (!askingAgain)
2233
                "\^<<actor.nameVerb('ask')>>, <q>";
2234
            
2235
            "Which <<originalText>> do you mean, <<
2236
            askDisambigList(matchList, fullMatchList, nil, dist)>>?</q> ";
2237
        }
2238
        else
2239
        {
2240
            /*
2241
             *   more than one required - we can't guess at the plural
2242
             *   given the original text, so just use the number 
2243
             */
2244
            if (!askingAgain)
2245
                "\^<<actor.nameVerb('ask')>>, <q>";
2246
            
2247
            "Which <<spellInt(requiredNum)>> (of <<
2248
            askDisambigList(matchList, fullMatchList, true, dist)>>)
2249
            do you mean?</q> ";
2250
        }
2251
    }
2252
2253
    /*
2254
     *   we found an ambiguous noun phrase, but we were unable to perform
2255
     *   interactive disambiguation 
2256
     */
2257
    ambiguousNounPhrase(actor, originalText, matchList, fullMatchList)
2258
    {
2259
        "\^<<actor.nameSays>>,
2260
        <q>I don&rsquo;t know which <<originalText>> you mean.</q> ";
2261
    }
2262
2263
    /*
2264
     *   Missing object query and error message templates 
2265
     */
2266
    askMissingObject(actor, action, which)
2267
    {
2268
        reportQuestion('\^' + actor.nameSays
2269
                       + ', <q>\^' + action.whatObj(which)
2270
                       + ' do you want me to '
2271
                       + action.getQuestionInf(which) + '?</q> ');
2272
    }
2273
    missingObject(actor, action, which)
2274
    {
2275
        "\^<<actor.nameSays>>,
2276
        <q>I don&rsquo;t know <<action.whatObj(which)>>
2277
        you want me to <<action.getQuestionInf(which)>>.</q> ";
2278
    }
2279
    missingLiteral(actor, action, which)
2280
    {
2281
        /* use the same message we use for a missing ordinary object */
2282
        missingObject(actor, action, which);
2283
    }
2284
2285
    /* tell the user they entered a word we don't know */
2286
    askUnknownWord(actor, txt)
2287
    {
2288
        "\^<<actor.nameSays>>,
2289
        <q>I don&rsquo;t know the word <q><<txt>></q>.</q> ";
2290
    }
2291
2292
    /* tell the user they entered a word we don't know */
2293
    wordIsUnknown(actor, txt)
2294
    {
2295
        "\^<<actor.nameSays>>,
2296
        <q>You used a word I don&rsquo;t know.</q> ";
2297
    }
2298
;
2299
2300
/*
2301
 *   Deferred NPC messages.  We use this to report deferred messages from
2302
 *   an NPC to the player.  A message is deferred when a parsing error
2303
 *   occurs, but the NPC can't talk to the player because there's no sense
2304
 *   path to the player.  When this happens, the NPC queues the message
2305
 *   for eventual delivery; when a sense path appears later that lets the
2306
 *   NPC talk to the player, we deliver the message through this object.
2307
 *   Since these messages describe conditions that occurred in the past,
2308
 *   we use the past tense to phrase the messages.
2309
 *   
2310
 *   Some messages will never be deferred:
2311
 *   
2312
 *   commandNotHeard - if a command is not heard, it will never enter an
2313
 *   actor's command queue; the error is given immediately in response to
2314
 *   the command entry.
2315
 *   
2316
 *   refuseCommandBusy - same as commandNotHeard
2317
 *   
2318
 *   noMatchDisambig - interactive disambiguation will not happen in a
2319
 *   deferred response situation, so it is impossible to have an
2320
 *   interactive disambiguation failure.  
2321
 *   
2322
 *   disambigOrdinalOutOfRange - for the same reason noMatchDisambig can't
2323
 *   be deferred.
2324
 *   
2325
 *   askDisambig - if we couldn't display a message, we definitely
2326
 *   couldn't perform interactive disambiguation.
2327
 *   
2328
 *   askMissingObject - for the same reason that askDisambig can't be
2329
 *   deferred
2330
 *   
2331
 *   askUnknownWord - for the same reason that askDisambig can't be
2332
 *   deferred.  
2333
 */
2334
npcDeferredMessagesDirect: npcDeferredMessages
2335
    commandNotUnderstood(actor)
2336
    {
2337
        "\^<<actor.nameSays>>,
2338
        <q>I didn&rsquo;t understand what you meant.</q> ";
2339
    }
2340
2341
    /* no match for a noun phrase */
2342
    noMatchCannotSee(actor, txt)
2343
    {
2344
        "\^<<actor.nameSays>>, <q>I didn&rsquo;t see any <<txt>>.</q> ";
2345
    }
2346
    noMatchNotAware(actor, txt)
2347
    {
2348
        "\^<<actor.nameSays>>, <q>I wasn&rsquo;t aware of any <<txt>>.</q> ";
2349
    }
2350
2351
    /* no match for 'all' */
2352
    noMatchForAll(actor)
2353
    {
2354
        "\^<<actor.nameSays>>, <q>I didn&rsquo;t see anything suitable.</q> ";
2355
    }
2356
2357
    /* nothing left for 'all' after removing 'except' items */
2358
    noMatchForAllBut(actor)
2359
    {
2360
        "\^<<actor.nameSays>>,
2361
        <q>I didn&rsquo;t see what you meant.</q> ";
2362
    }
2363
2364
    /* empty noun phrase ('take the') */
2365
    emptyNounPhrase(actor)
2366
    {
2367
        "\^<<actor.nameSays>>,
2368
        <q>You left some words out.</q> ";
2369
    }
2370
2371
    /* 'take zero books' */
2372
    zeroQuantity(actor, txt)
2373
    {
2374
        "\^<<actor.nameSays>>,
2375
        <q>I didn&rsquo;t understand what you meant.</q> ";
2376
    }
2377
2378
    /* insufficient quantity to meet a command request ('take five books') */
2379
    insufficientQuantity(actor, txt, matchList, requiredNum)
2380
    {
2381
        "\^<<actor.nameSays>>,
2382
        <q>I didn&rsquo;t see enough <<txt>>.</q> ";
2383
    }
2384
2385
    /* a unique object is required, but multiple objects were specified */
2386
    uniqueObjectRequired(actor, txt, matchList)
2387
    {
2388
        "\^<<actor.nameSays>>,
2389
        <q>I didn&rsquo;t understand what you meant.</q> ";
2390
    }
2391
2392
    /* a unique object is required, but multiple objects were specified */
2393
    singleObjectRequired(actor, txt)
2394
    {
2395
        "\^<<actor.nameSays>>,
2396
        <q>I didn&rsquo;t understand what you meant.</q> ";
2397
    }
2398
2399
    /*
2400
     *   we found an ambiguous noun phrase, but we were unable to perform
2401
     *   interactive disambiguation 
2402
     */
2403
    ambiguousNounPhrase(actor, originalText, matchList, fullMatchList)
2404
    {
2405
        "\^<<actor.nameSays>>,
2406
        <q>I couldn&rsquo;t tell which <<originalText>> you meant.</q> ";
2407
    }
2408
2409
    /* an object phrase was missing */
2410
    askMissingObject(actor, action, which)
2411
    {
2412
        reportQuestion('\^' + actor.nameSays
2413
                       + ', <q>I didn&rsquo;t know '
2414
                       + action.whatObj(which) + ' you wanted me to '
2415
                       + action.getQuestionInf(which) + '.</q> ');
2416
    }
2417
2418
    /* tell the user they entered a word we don't know */
2419
    wordIsUnknown(actor, txt)
2420
    {
2421
        "\^<<actor.nameSays>>,
2422
        <q>You used a word I don&rsquo;t know.</q> ";
2423
    }
2424
;
2425
2426
/* ------------------------------------------------------------------------ */
2427
/*
2428
 *   Verb messages for standard library verb implementations for actions
2429
 *   performed by the player character.  These return strings suitable for
2430
 *   use in VerifyResult objects as well as for action reports
2431
 *   (defaultReport, mainReport, and so on).
2432
 *   
2433
 *   Most of these messages are generic enough to be used for player and
2434
 *   non-player character alike.  However, some of the messages either are
2435
 *   too terse (such as the default reports) or are phrased awkwardly for
2436
 *   NPC use, so the NPC verb messages override those.  
2437
 */
2438
playerActionMessages: MessageHelper
2439
    /*
2440
     *   generic "can't do that" message - this is used when verification
2441
     *   fails because an object doesn't define the action ("doXxx")
2442
     *   method for the verb 
2443
     */
2444
    cannotDoThatMsg = '{You/he} {can\'t} do that. '
2445
2446
    /* must be holding something before a command */
2447
    mustBeHoldingMsg(obj)
2448
    {
2449
        gMessageParams(obj);
2450
        return '{You/he} {must} be holding {the obj/him} to do that. ';
2451
    }
2452
2453
    /* it's too dark to do that */
2454
    tooDarkMsg = 'It{&rsquo;s| was} too dark to do that. '
2455
2456
    /* object must be visible */
2457
    mustBeVisibleMsg(obj)
2458
    {
2459
        gMessageParams(obj);
2460
        return '{You/he} {cannot} see {that obj/him}. ';
2461
    }
2462
2463
    /* object can be heard but not seen */
2464
    heardButNotSeenMsg(obj)
2465
    {
2466
        gMessageParams(obj);
2467
        return '{You/he} {can} hear {an obj/him}, but {you/he}
2468
                 {can\'t} see {it obj/him}. ';
2469
    }
2470
2471
    /* object can be smelled but not seen */
2472
    smelledButNotSeenMsg(obj)
2473
    {
2474
        gMessageParams(obj);
2475
        return '{You/he} {can} smell {an obj/him}, but {you/he}
2476
                {can\'t} see {it obj/him}. ';
2477
    }
2478
2479
    /* cannot hear object */
2480
    cannotHearMsg(obj)
2481
    {
2482
        gMessageParams(obj);
2483
        return '{You/he} {cannot} hear {that obj/him}. ';
2484
    }
2485
2486
    /* cannot smell object */
2487
    cannotSmellMsg(obj)
2488
    {
2489
        gMessageParams(obj);
2490
        return '{You/he} {cannot} smell {that obj/him}. ';
2491
    }
2492
2493
    /* cannot taste object */
2494
    cannotTasteMsg(obj)
2495
    {
2496
        gMessageParams(obj);
2497
        return '{You/he} {cannot} taste {that obj/him}. ';
2498
    }
2499
2500
    /* must remove an article of clothing before a command */
2501
    cannotBeWearingMsg(obj)
2502
    {
2503
        gMessageParams(obj);
2504
        return '{You/he} {must} take off {the obj/him}
2505
                before {it actor/he} {can} do that. ';
2506
    }
2507
2508
    /* all contents must be removed from object before doing that */
2509
    mustBeEmptyMsg(obj)
2510
    {
2511
        gMessageParams(obj);
2512
        return '{You/he} {must} take everything out of {the obj/him}
2513
                before {it actor/he} {can} do that. ';
2514
    }
2515
2516
    /* object must be opened before doing that */
2517
    mustBeOpenMsg(obj)
2518
    {
2519
        gMessageParams(obj);
2520
        return '{You/he} {must} open {the obj/him}
2521
                before {it actor/he} {can} do that. ';
2522
    }
2523
2524
    /* object must be closed before doing that */
2525
    mustBeClosedMsg(obj)
2526
    {
2527
        gMessageParams(obj);
2528
        return '{You/he} {must} close {the obj/him}
2529
               before {it actor/he} {can} do that. ';
2530
    }
2531
2532
    /* object must be unlocked before doing that */
2533
    mustBeUnlockedMsg(obj)
2534
    {
2535
        gMessageParams(obj);
2536
        return '{You/he} {must} unlock {the obj/him}
2537
                before {it actor/he} {can} do that. ';
2538
    }
2539
2540
    /* no key is needed to lock or unlock this object */
2541
    noKeyNeededMsg = '{The dobj/he} {does} not appear to take a key. '
2542
2543
    /* actor must be standing before doing that */
2544
    mustBeStandingMsg = '{You/he} {must} stand up before {it actor/he}
2545
                      {can} do that. '
2546
2547
    /* must be sitting on/in chair */
2548
    mustSitOnMsg(obj)
2549
    {
2550
        gMessageParams(obj);
2551
        return '{You/he} {must} sit {in obj} first. ';
2552
    }
2553
2554
    /* must be lying on/in object */
2555
    mustLieOnMsg(obj)
2556
    {
2557
        gMessageParams(obj);
2558
        return '{You/he} {must} lie {in obj} first. ';
2559
    }
2560
2561
    /* must get on/in object */
2562
    mustGetOnMsg(obj)
2563
    {
2564
        gMessageParams(obj);
2565
        return '{You/he} {must} get {in obj} first. ';
2566
    }
2567
2568
    /* object must be in loc before doing that */
2569
    mustBeInMsg(obj, loc)
2570
    {
2571
        gMessageParams(obj, loc);
2572
        return '{The obj/he} {must} be {in loc} before {you/he}
2573
            {can} do that. ';
2574
    }
2575
2576
    /* actor must be holding the object before we can do that */
2577
    mustBeCarryingMsg(obj, actor)
2578
    {
2579
        gMessageParams(obj, actor);
2580
        return '{The actor/he} {must} be holding {the obj/him}
2581
            before {it actor/he} {can} do that. ';
2582
    }
2583
2584
    /* generic "that's not important" message for decorations */
2585
    decorationNotImportantMsg(obj)
2586
    {
2587
        gMessageParams(obj);
2588
        return '{The obj/he} {is}n&rsquo;t important. ';
2589
    }
2590
2591
    /* generic "you don't see that" message for "unthings" */
2592
    unthingNotHereMsg(obj)
2593
    {
2594
        gMessageParams(obj);
2595
        return '{You/he} {does}n&rsquo;t see {that obj/him} {|t}here. ';
2596
    }
2597
2598
    /* generic "that's too far away" message for Distant items */
2599
    tooDistantMsg(obj)
2600
    {
2601
        gMessageParams(obj);
2602
        return '{The obj/he} {is} too far away. ';
2603
    }
2604
2605
    /* generic "no can do" message for intangibles */
2606
    notWithIntangibleMsg(obj)
2607
    {
2608
        gMessageParams(obj);
2609
        return '{You/he} {can\'t} do that to {an obj/him}. ';
2610
    }
2611
2612
    /* generic failure message for varporous objects */
2613
    notWithVaporousMsg(obj)
2614
    {
2615
        gMessageParams(obj);
2616
        return '{You/he} {can\'t} do that to {an obj/him}. ';
2617
    }
2618
2619
    /* look in/look under/look through/look behind/search vaporous */
2620
    lookInVaporousMsg(obj)
2621
    {
2622
        gMessageParams(obj);
2623
        return '{You/he} just {sees} {the obj/him}. ';
2624
    }
2625
2626
    /*
2627
     *   cannot reach (i.e., touch) an object that is to be manipulated in
2628
     *   a command - this is a generic message used when we cannot
2629
     *   identify the specific reason that the object is in scope but
2630
     *   cannot be touched 
2631
     */
2632
    cannotReachObjectMsg(obj)
2633
    {
2634
        gMessageParams(obj);
2635
        return '{You/he} {cannot} reach {the obj/him}. ';
2636
    }
2637
2638
    /* cannot reach an object through an obstructor */
2639
    cannotReachThroughMsg(obj, loc)
2640
    {
2641
        gMessageParams(obj, loc);
2642
        return '{You/he} {cannot} reach {the obj/him} through '
2643
               + '{the loc/him}. ';
2644
    }
2645
2646
    /* generic long description of a Thing */
2647
    thingDescMsg(obj)
2648
    {
2649
        gMessageParams(obj);
2650
        return '{You/he} {sees} nothing unusual about '
2651
               + '{it obj/him}. ';
2652
    }
2653
2654
    /* generic LISTEN TO description of a Thing */
2655
    thingSoundDescMsg(obj)
2656
        { return '{You/he} hear{s/d} nothing out of the ordinary. '; }
2657
2658
    /* generic "smell" description of a Thing */
2659
    thingSmellDescMsg(obj)
2660
        { return '{You/he} smell{s/ed} nothing out of the ordinary. '; }
2661
2662
    /* default description of a non-player character */
2663
    npcDescMsg(npc)
2664
    {
2665
        gMessageParams(npc);
2666
        return '{You/he} {sees} nothing unusual about '
2667
               + '{the npc/him}. ';
2668
    }
2669
2670
    /* generic messages for looking prepositionally */
2671
    nothingInsideMsg =
2672
        'There{&rsquo;s| was} nothing unusual in {the dobj/him}. '
2673
    nothingUnderMsg =
2674
        '{You/he} {sees} nothing unusual under {the dobj/him}. '
2675
    nothingBehindMsg =
2676
        '{You/he} {sees} nothing unusual behind {the dobj/him}. '
2677
    nothingThroughMsg =
2678
        '{You/he} {can} see nothing through {the dobj/him}. '
2679
2680
    /* this is an object we can't look behind/through */
2681
    cannotLookBehindMsg = '{You/he} {can\'t} look behind {the dobj/him}. '
2682
    cannotLookUnderMsg = '{You/he} {can\'t} look under {the dobj/him}. '
2683
    cannotLookThroughMsg = '{You/he} {can\'t} see through {the dobj/him}. '
2684
2685
    /* looking through an open passage */
2686
    nothingThroughPassageMsg = '{You/he} {can\'t} see much through
2687
        {the dobj/him} from {|t}here. '
2688
2689
    /* there's nothing on the other side of a door we just opened */
2690
    nothingBeyondDoorMsg = 'Opening {the dobj/him} reveal{s|ed} nothing
2691
        unusual. '
2692
2693
    /* there's nothing here with a specific odor */
2694
    nothingToSmellMsg =
2695
        '{You/he} smell{s/ed} nothing out of the ordinary. '
2696
2697
    /* there's nothing here with a specific noise */
2698
    nothingToHearMsg = '{You/he} hear{s/d} nothing out of the ordinary. '
2699
2700
    /* a sound appears to be coming from a source */
2701
    noiseSourceMsg(src)
2702
    {
2703
        return '{The dobj/he} seem{s/ed} to be coming from '
2704
            + src.theNameObj + '. ';
2705
    }
2706
2707
    /* an odor appears to be coming from a source */
2708
    odorSourceMsg(src)
2709
    {
2710
        return '{The dobj/he} seem{s/ed} to be coming from '
2711
            + src.theNameObj + '. ';
2712
    }
2713
2714
    /* an item is not wearable */
2715
    notWearableMsg =
2716
        '{That dobj/he} {is}n&rsquo;t something {you/he} {can} wear. '
2717
2718
    /* doffing something that isn't wearable */
2719
    notDoffableMsg =
2720
        '{That dobj/he} {is}n&rsquo;t something {you/he} {can} remove. '
2721
2722
    /* already wearing item */
2723
    alreadyWearingMsg = '{You\'re} already wearing {it dobj/him}. '
2724
2725
    /* not wearing (item being doffed) */
2726
    notWearingMsg = '{You\'re} not wearing {that dobj/him}. '
2727
2728
    /* default response to 'wear obj' */
2729
    okayWearMsg = 'Okay, {you\'re} now wearing {the dobj/him}. '
2730
2731
    /* default response to 'doff obj' */
2732
    okayDoffMsg = 'Okay, {you\'re} no longer wearing {the dobj/him}. '
2733
2734
    /* default response to open/close */
2735
    okayOpenMsg = shortTMsg(
2736
        'Opened. ', '{You/he} open{s/ed} {the dobj/him}. ')
2737
    okayCloseMsg = shortTMsg(
2738
        'Closed. ', '{You/he} close{s/d} {the dobj/him}. ')
2739
2740
    /* default response to lock/unlock */
2741
    okayLockMsg = shortTMsg(
2742
        'Locked. ', '{You/he} lock{s/ed} {the dobj/him}. ')
2743
    okayUnlockMsg = shortTMsg(
2744
        'Unlocked. ', '{You/he} unlock{s/ed} {the dobj/him}. ')
2745
2746
    /* cannot dig here */
2747
    cannotDigMsg = '{You/he} {have} no reason to dig in {that dobj/him}. '
2748
2749
    /* not a digging implement */
2750
    cannotDigWithMsg =
2751
        '{You/he} {sees} no way to use {that iobj/him} as a shovel. '
2752
2753
    /* taking something already being held */
2754
    alreadyHoldingMsg = '{You/he} {are} already carrying {the dobj/him}. '
2755
2756
    /* actor taking self ("take me") */
2757
    takingSelfMsg = '{You/he} {can\'t} take {yourself}. '
2758
2759
    /* dropping an object not being carried */
2760
    notCarryingMsg = '{You\'re} not carrying {that dobj/him}. '
2761
2762
    /* actor dropping self */
2763
    droppingSelfMsg = '{You/he} {can\'t} drop {yourself}. '
2764
2765
    /* actor putting self in something */
2766
    puttingSelfMsg = '{You/he} {can\'t} do that to {yourself}. '
2767
2768
    /* actor throwing self */
2769
    throwingSelfMsg = '{You/he} {can\'t} throw {yourself}. '
2770
2771
    /* we can't put the dobj in the iobj because it's already there */
2772
    alreadyPutInMsg = '{The dobj/he} {is} already in {the iobj/him}. '
2773
2774
    /* we can't put the dobj on the iobj because it's already there */
2775
    alreadyPutOnMsg = '{The dobj/he} {is} already on {the iobj/him}. '
2776
2777
    /* we can't put the dobj under the iobj because it's already there */
2778
    alreadyPutUnderMsg = '{The dobj/he} {is} already under {the iobj/him}. '
2779
2780
    /* we can't put the dobj behind the iobj because it's already there */
2781
    alreadyPutBehindMsg = '{The dobj/he} {is} already behind {the iobj/him}. '
2782
2783
    /*
2784
     *   trying to move a Fixture to a new container by some means (take,
2785
     *   drop, put in, put on, etc) 
2786
     */
2787
    cannotMoveFixtureMsg = '{The dobj/he} {cannot} be moved. '
2788
2789
    /* trying to take a Fixture */
2790
    cannotTakeFixtureMsg = '{You/he} {can\'t} take {that dobj/him}. '
2791
2792
    /* trying to put a Fixture in something */
2793
    cannotPutFixtureMsg = '{You/he} {can\'t} put {the dobj/him} anywhere. '
2794
2795
    /* trying to take/move/put an Immovable object */
2796
    cannotTakeImmovableMsg = '{You/he} {can\'t} take {that dobj/him}. '
2797
    cannotMoveImmovableMsg = '{The dobj/he} {cannot} be moved. '
2798
    cannotPutImmovableMsg = '{You/he} {can\'t} put {the dobj/him} anywhere. '
2799
2800
    /* trying to take/move/put a Heavy object */
2801
    cannotTakeHeavyMsg = '{The dobj/he} {is} too heavy. '
2802
    cannotMoveHeavyMsg = '{The dobj/he} {is} too heavy. '
2803
    cannotPutHeavyMsg = '{The dobj/he} {is} too heavy. '
2804
2805
    /* trying to move a component object */
2806
    cannotMoveComponentMsg(loc)
2807
    {
2808
        return '{The dobj/he} {is} part of ' + loc.theNameObj + '. ';
2809
    }
2810
2811
    /* trying to take a component object */
2812
    cannotTakeComponentMsg(loc)
2813
    {
2814
        return '{You/he} {can\'t} have {that/him dobj}; '
2815
            + '{it\'s dobj} part of ' + loc.theNameObj + '. ';
2816
    }
2817
2818
    /* trying to put a component in something */
2819
    cannotPutComponentMsg(loc)
2820
    {
2821
        return '{You/he} {can\'t} put {that/him dobj} anywhere; '
2822
            + '{it\'s dobj} part of ' + loc.theNameObj + '. ';
2823
    }
2824
2825
    /* specialized Immovable messages for TravelPushables */
2826
    cannotTakePushableMsg = '{You/he} {can\'t} take {that/him dobj}, but
2827
        {it actor/he} might {be|have been} able to push it somewhere. '
2828
    cannotMovePushableMsg = 'It wouldn&rsquo;t {|have} accomplish{|ed}
2829
        anything to move {the dobj/him} around aimlessly, but {it actor/he}
2830
        might {be|have been} able to push {it dobj/him} in a specific
2831
        direction. '
2832
    cannotPutPushableMsg = '{You/he} {can\'t} put {that/him dobj} anywhere,
2833
        but {it actor/he} might {be|have been} able to push it somewhere. '
2834
2835
    /* can't take something while occupying it */
2836
    cannotTakeLocationMsg = '{You/he} {can\'t} take {that/him dobj}
2837
        while {you\'re} occupying {it/him dobj}. '
2838
2839
    /* can't REMOVE something that's being held */
2840
    cannotRemoveHeldMsg = 'There{\'s| was} nothing to remove
2841
        {the dobj/him} from. '
2842
2843
    /* default 'take' response */
2844
    okayTakeMsg = shortTMsg(
2845
        'Taken. ', '{You/he} {take[s]|took} {the dobj/him}. ')
2846
2847
    /* default 'drop' response */
2848
    okayDropMsg = shortTMsg(
2849
        'Dropped. ', '{You/he} drop{s/ped} {the dobj/him}. ')
2850
2851
    /* dropping an object */
2852
    droppingObjMsg(dropobj)
2853
    {
2854
        gMessageParams(dropobj);
2855
        return '{You/he} drop{s/ped} {the dropobj/him}. ';
2856
    }
2857
2858
    /* default receiveDrop suffix for floorless rooms */
2859
    floorlessDropMsg(dropobj)
2860
    {
2861
        gMessageParams(dropobj);
2862
        return '{It dropobj/he} {fall[s]|fell} out of sight below. ';
2863
    }
2864
2865
    /* default successful 'put in' response */
2866
    okayPutInMsg = shortTIMsg(
2867
        'Done. ', '{You/he} put{[s]|} {the dobj/him} in {the iobj/him}. ')
2868
2869
    /* default successful 'put on' response */
2870
    okayPutOnMsg = shortTIMsg(
2871
        'Done. ', '{You/he} put{[s]|} {the dobj/him} on {the iobj/him}. ')
2872
2873
    /* default successful 'put under' response */
2874
    okayPutUnderMsg = shortTIMsg(
2875
        'Done. ', '{You/he} put{[s]|} {the dobj/him} under {the iobj/him}. ')
2876
2877
    /* default successful 'put behind' response */
2878
    okayPutBehindMsg = shortTIMsg(
2879
        'Done. ', '{You/he} put{[s]|} {the dobj/him} behind {the iobj/him}. ')
2880
2881
    /* try to take/move/put/taste an untakeable actor */
2882
    cannotTakeActorMsg = '{The dobj/he} {won\'t} let {you/him} do that. '
2883
    cannotMoveActorMsg = '{The dobj/he} {won\'t} let {you/him} do that. '
2884
    cannotPutActorMsg = '{The dobj/he} {won\'t} let {you/him} do that. '
2885
    cannotTasteActorMsg = '{The dobj/he} {won\'t} let {you/him} do that. '
2886
2887
    /* trying to take/move/put/taste a person */
2888
    cannotTakePersonMsg =
2889
        '{The dobj/he} probably wouldn&rsquo;t {|have} like{|d} that. '
2890
    cannotMovePersonMsg =
2891
        '{The dobj/he} probably wouldn&rsquo;t {|have} like{|d} that. '
2892
    cannotPutPersonMsg =
2893
        '{The dobj/he} probably wouldn&rsquo;t {|have} like{|d} that. '
2894
    cannotTastePersonMsg =
2895
        '{The dobj/he} probably wouldn&rsquo;t {|have} like{|d} that. '
2896
2897
    /* cannot move obj through obstructor */
2898
    cannotMoveThroughMsg(obj, obs)
2899
    {
2900
        gMessageParams(obj, obs);
2901
        return '{You/he} {can\'t} move {that obj/him} through '
2902
               + '{the obs/him}. ';
2903
    }
2904
2905
    /* cannot move obj in our out of container cont */
2906
    cannotMoveThroughContainerMsg(obj, cont)
2907
    {
2908
        gMessageParams(obj, cont);
2909
        return '{You/he} {can\'t} move {that obj/him} through '
2910
               + '{the cont/him}. ';
2911
    }
2912
2913
    /* cannot move obj because cont is closed */
2914
    cannotMoveThroughClosedMsg(obj, cont)
2915
    {
2916
        gMessageParams(cont);
2917
        return '{You/he} {can\'t} do that because {the cont/he} {is} '
2918
               + 'closed. ';
2919
    }
2920
2921
    /* cannot fit obj into cont through cont's opening */
2922
    cannotFitIntoOpeningMsg(obj, cont)
2923
    {
2924
        gMessageParams(obj, cont);
2925
        return '{You/he} {can\'t} do that because {the obj/he} {is}
2926
                too big to put into {the cont/him}. ';
2927
    }
2928
2929
    /* cannot fit obj out of cont through cont's opening */
2930
    cannotFitOutOfOpeningMsg(obj, cont)
2931
    {
2932
        gMessageParams(obj, cont);
2933
        return '{You/he} {can\'t} do that because {the obj/he} {is}
2934
                too big to take out of {the cont/him}. ';
2935
    }
2936
2937
    /* actor 'obj' cannot reach in our out of container 'cont' */
2938
    cannotTouchThroughContainerMsg(obj, cont)
2939
    {
2940
        gMessageParams(obj, cont);
2941
        return '{The obj/he} {can\'t} reach anything through '
2942
               + '{the cont/him}. ';
2943
    }
2944
2945
    /* actor 'obj' cannot reach through cont because cont is closed */
2946
    cannotTouchThroughClosedMsg(obj, cont)
2947
    {
2948
        gMessageParams(obj, cont);
2949
        return '{The obj/he} {can\'t} do that because
2950
               {the cont/he} {is} closed. ';
2951
    }
2952
2953
    /* actor cannot fit hand into cont through cont's opening */
2954
    cannotReachIntoOpeningMsg(obj, cont)
2955
    {
2956
        gMessageParams(obj, cont);
2957
        return '{The obj/he} {can\'t} fit {its/her} hand into '
2958
               + '{the cont/him}. ';
2959
    }
2960
2961
    /* actor cannot fit hand into cont through cont's opening */
2962
    cannotReachOutOfOpeningMsg(obj, cont)
2963
    {
2964
        gMessageParams(obj, cont);
2965
        return '{The obj/he} {can\'t} fit {its/her} hand through
2966
               {the cont/him}. ';
2967
    }
2968
2969
    /* the object is too large for the actor to hold */
2970
    tooLargeForActorMsg(obj)
2971
    {
2972
        gMessageParams(obj);
2973
        return '{The obj/he} {is} too large for {you/him} to hold. ';
2974
    }
2975
2976
    /* the actor doesn't have room to hold the object */
2977
    handsTooFullForMsg(obj)
2978
    {
2979
        return '{Your} hands {are|were} too full to hold '
2980
               + obj.theNameObj + '. ';
2981
    }
2982
2983
    /* the object is becoming too large for the actor to hold */
2984
    becomingTooLargeForActorMsg(obj)
2985
    {
2986
        gMessageParams(obj);
2987
        return '{You/he} {cannot} do that because {the obj/he}
2988
                would {|have} become too large for {you/him} to hold. ';
2989
    }
2990
2991
    /* the object is becoming large enough that the actor's hands are full */
2992
    handsBecomingTooFullForMsg(obj)
2993
    {
2994
        gMessageParams(obj);
2995
        return '{You/he} {cannot} do that because {its/her} hands
2996
            would {|have} become too full to hold {the obj/him}. ';
2997
    }
2998
2999
    /* the object is too heavy (all by itself) for the actor to hold */
3000
    tooHeavyForActorMsg(obj)
3001
    {
3002
        gMessageParams(obj);
3003
        return '{The obj/he} {is} too heavy for {you/him} to pick up. ';
3004
    }
3005
3006
    /*
3007
     *   the object is too heavy (in combination with everything else
3008
     *   being carried) for the actor to pick up 
3009
     */
3010
    totalTooHeavyForMsg(obj)
3011
    {
3012
        gMessageParams(obj);
3013
        return '{The obj/he} {is} too heavy; {you/he} {will} have to put
3014
            something else down first. ';
3015
    }
3016
3017
    /* object is too large for container */
3018
    tooLargeForContainerMsg(obj, cont)
3019
    {
3020
        gMessageParams(obj, cont);
3021
        return '{The obj/he} {is} too large for {the cont/him}. ';
3022
    }
3023
3024
    /* object is too large to fit under object */
3025
    tooLargeForUndersideMsg(obj, cont)
3026
    {
3027
        gMessageParams(obj, cont);
3028
        return '{The obj/he} {is} too large to put under {the cont/him}. ';
3029
    }
3030
3031
    /* object is too large to fit behind object */
3032
    tooLargeForRearMsg(obj, cont)
3033
    {
3034
        gMessageParams(obj, cont);
3035
        return '{The obj/he} {is} too large to put behind {the cont/him}. ';
3036
    }
3037
3038
    /* container doesn't have room for object */
3039
    containerTooFullMsg(obj, cont)
3040
    {
3041
        gMessageParams(obj, cont);
3042
        return '{The cont/he} {is} already too full to hold {the obj/him}. ';
3043
    }
3044
3045
    /* surface doesn't have room for object */
3046
    surfaceTooFullMsg(obj, cont)
3047
    {
3048
        gMessageParams(obj, cont);
3049
        return 'There{&rsquo;s| was} no room for {the obj/him} on '
3050
               + '{the cont/him}. ';
3051
    }
3052
3053
    /* underside doesn't have room for object */
3054
    undersideTooFullMsg(obj, cont)
3055
    {
3056
        gMessageParams(obj, cont);
3057
        return 'There{&rsquo;s| was} no room for {the obj/him} under '
3058
               + '{the cont/him}. ';
3059
    }
3060
3061
    /* rear surface/space doesn't have room for object */
3062
    rearTooFullMsg(obj, cont)
3063
    {
3064
        gMessageParams(obj, cont);
3065
        return 'There{&rsquo;s |was} no room for {the obj/him} behind '
3066
               + '{the cont/him}. ';
3067
    }
3068
3069
    /* the current action would make obj too large for its container */
3070
    becomingTooLargeForContainerMsg(obj, cont)
3071
    {
3072
        gMessageParams(obj, cont);
3073
        return '{You/he} {cannot} do that because it would {make|have made}
3074
            {the obj/him} too large for {the cont/him}. ';
3075
    }
3076
3077
    /*
3078
     *   the current action would increase obj's bulk so that container is
3079
     *   too full 
3080
     */
3081
    containerBecomingTooFullMsg(obj, cont)
3082
    {
3083
        gMessageParams(obj, cont);
3084
        return '{You/he} {cannot} do that because {the obj/he}
3085
            would no longer {|have} fit{|ted} in {the cont/him}. ';
3086
    }
3087
3088
    /* trying to put an object in a non-container */
3089
    notAContainerMsg = '{You/he} {can\'t} put anything in {the iobj/him}. '
3090
3091
    /* trying to put an object on a non-surface */
3092
    notASurfaceMsg = 'There{&rsquo;s| was} no good surface on
3093
        {the iobj/him}. '
3094
3095
    /* can't put anything under iobj */
3096
    cannotPutUnderMsg =
3097
        '{You/he} {can\'t} put anything under {that iobj/him}. '
3098
3099
    /* nothing can be put behind the given object */
3100
    cannotPutBehindMsg = '{You/he} {can\'t} put anything
3101
        behind {the iobj/him}. '
3102
3103
    /* trying to put something in itself */
3104
    cannotPutInSelfMsg = '{You/he} {can\'t} put {the dobj/him} in {itself}. '
3105
3106
    /* trying to put something on itself */
3107
    cannotPutOnSelfMsg = '{You/he} {can\'t} put {the dobj/him} on {itself}. '
3108
3109
    /* trying to put something under itself */
3110
    cannotPutUnderSelfMsg = '{You/he} {can\'t} put {the dobj/him} under
3111
        {itself}. '
3112
3113
    /* trying to put something behind itself */
3114
    cannotPutBehindSelfMsg = '{You/he} {can\'t} put {the dobj/him} behind
3115
        {itself}. '
3116
3117
    /* can't put something in/on/etc a restricted container/surface/etc */
3118
    cannotPutInRestrictedMsg =
3119
        '{You/he} {can\'t} put {that dobj/him} in {the iobj/him}. '
3120
    cannotPutOnRestrictedMsg =
3121
        '{You/he} {can\'t} put {that dobj/him} on {the iobj/him}. '
3122
    cannotPutUnderRestrictedMsg =
3123
        '{You/he} {can\'t} put {that dobj/him} under {the iobj/him}. '
3124
    cannotPutBehindRestrictedMsg =
3125
        '{You/he} {can\'t} put {that dobj/him} behind {the iobj/him}. '
3126
3127
    /* trying to return something to a remove-only dispenser */
3128
    cannotReturnToDispenserMsg =
3129
        '{You/he} {can\'t} put {a dobj/him} back in {the iobj/him}. '
3130
3131
    /* wrong item type for dispenser */
3132
    cannotPutInDispenserMsg =
3133
        '{You/he} {can\'t} put {a dobj/him} in {the iobj/him}. '
3134
3135
    /* the dobj doesn't fit on this keyring */
3136
    objNotForKeyringMsg = '{The dobj/he} {does}n&rsquo;t fit
3137
        on {the iobj/him}. '
3138
3139
    /* the dobj isn't on the keyring */
3140
    keyNotOnKeyringMsg = '{The dobj/he} {is} not attached to {the iobj/him}. '
3141
3142
    /* can't detach key (with no iobj specified) because it's not on a ring */
3143
    keyNotDetachableMsg = '{The dobj/he} {is}n&rsquo;t attached to anything. '
3144
3145
    /* we took a key and attached it to a keyring */
3146
    takenAndMovedToKeyringMsg(keyring)
3147
    {
3148
        gMessageParams(keyring);
3149
        return '{You/he} pick{s/ed} up {the dobj/him} and
3150
            attach{es/ed actor} {it dobj/him} to {the keyring/him}. ';
3151
    }
3152
3153
    /* we attached a key to a keyring automatically */
3154
    movedKeyToKeyringMsg(keyring)
3155
    {
3156
        gMessageParams(keyring);
3157
        return '{You/he} attach{es/ed} {the dobj/him} to {the keyring/him}. ';
3158
    }
3159
3160
    /* we moved several keys to a keyring automatically */
3161
    movedKeysToKeyringMsg(keyring, keys)
3162
    {
3163
        gMessageParams(keyring);
3164
        return '{You/he} attach{es/ed} {your/his} loose key'
3165
            + (keys.length() > 1 ? 's' : '')
3166
            + ' to {the keyring/him}. ';
3167
    }
3168
3169
    /* putting y in x when x is already in y */
3170
    circularlyInMsg(x, y)
3171
    {
3172
        gMessageParams(x, y);
3173
        return '{You/he} {can\'t} do that while {the x/he} {is}
3174
            in {the y/him}. ';
3175
    }
3176
3177
    /* putting y in x when x is already on y */
3178
    circularlyOnMsg(x, y)
3179
    {
3180
        gMessageParams(x, y);
3181
        return '{You/he} {can\'t} do that while {the x/he} {is}
3182
            on {the y/him}. ';
3183
    }
3184
3185
    /* putting y in x when x is already under y */
3186
    circularlyUnderMsg(x, y)
3187
    {
3188
        gMessageParams(x, y);
3189
        return '{You/he} {can\'t} do that while {the x/he} {is}
3190
            under {the y/him}. ';
3191
    }
3192
3193
    /* putting y in x when x is already behind y */
3194
    circularlyBehindMsg(x, y)
3195
    {
3196
        gMessageParams(x, y);
3197
        return '{You/he} {can\'t} do that while {the x/he} {is}
3198
            behind {the y/him}. ';
3199
    }
3200
3201
    /* taking dobj from iobj, but dobj isn't in iobj */
3202
    takeFromNotInMsg = '{The dobj/he} {is}n&rsquo;t in {that iobj/him}. '
3203
3204
    /* taking dobj from surface, but dobj isn't on iobj */
3205
    takeFromNotOnMsg = '{The dobj/he} {is}n&rsquo;t on {that iobj/him}. '
3206
3207
    /* taking dobj from under something, but dobj isn't under iobj */
3208
    takeFromNotUnderMsg = '{The dobj/he} {is}n&rsquo;t
3209
        under {that iobj/him}. '
3210
3211
    /* taking dobj from behind something, but dobj isn't behind iobj */
3212
    takeFromNotBehindMsg = '{The dobj/he} {is}n&rsquo;t
3213
        behind {that iobj/him}. '
3214
3215
    /* taking dobj from an actor, but actor doesn't have iobj */
3216
    takeFromNotInActorMsg = '{The iobj/he} {does}n&rsquo;t
3217
        have {that dobj/him}. '
3218
3219
    /* actor won't let go of a possession */
3220
    willNotLetGoMsg(holder, obj)
3221
    {
3222
        gMessageParams(holder, obj);
3223
        return '{The holder/he} {won\'t} let {you/him} have {that obj/him}. ';
3224
    }
3225
3226
    /* must say which way to go */
3227
    whereToGoMsg = 'You&rsquo;ll have to say which way to go. '
3228
3229
    /* travel attempted in a direction with no exit */
3230
    cannotGoThatWayMsg = '{You/he} {can\'t} go that way. '
3231
3232
    /* travel attempted in the dark in a direction with no exit */
3233
    cannotGoThatWayInDarkMsg = 'It{&rsquo;s| was} too dark; {you/he}
3234
        {can\'t} see where {you\'re} going. '
3235
3236
    /* we don't know the way back for a GO BACK */
3237
    cannotGoBackMsg = '{You/he} {does}n&rsquo;t know how to return
3238
        from {|t}here. '
3239
3240
    /* cannot carry out a command from this location */
3241
    cannotDoFromHereMsg = '{You/he} {can\'t} do that from {|t}here. '
3242
3243
    /* can't travel through a close door */
3244
    cannotGoThroughClosedDoorMsg(door)
3245
    {
3246
        gMessageParams(door);
3247
        return '{You/he} {can\'t} do that, because {the door/he} {is} '
3248
               + 'closed. ';
3249
    }
3250
3251
    /* cannot carry out travel while 'dest' is within 'cont' */
3252
    invalidStagingContainerMsg(cont, dest)
3253
    {
3254
        gMessageParams(cont, dest);
3255
        return '{You/he} {can\'t} do that while {the dest/he} {is}
3256
                {in cont}. ';
3257
    }
3258
3259
    /* cannot carry out travel while 'cont' (an actor) is holding 'dest' */
3260
    invalidStagingContainerActorMsg(cont, dest)
3261
    {
3262
        gMessageParams(cont, dest);
3263
        return '{You/he} {can\'t} do that while {the cont/he} {is}
3264
            holding {the dest/him}. ';
3265
    }
3266
    
3267
    /* can't carry out travel because 'dest' isn't a valid staging location */
3268
    invalidStagingLocationMsg(dest)
3269
    {
3270
        gMessageParams(dest);
3271
        return '{You/he} {can\'t} get {in dest}. ';
3272
    }
3273
3274
    /* destination is too high to enter from here */
3275
    nestedRoomTooHighMsg(obj)
3276
    {
3277
        gMessageParams(obj);
3278
        return '{The obj/he} {is} too high to reach from {|t}here. ';
3279
    }
3280
3281
    /* enclosing room is too high to reach by GETTING OUT OF here */
3282
    nestedRoomTooHighToExitMsg(obj)
3283
    {
3284
        return 'It{&rsquo;s| was} too long a drop to do that from {|t}here. ';
3285
    }
3286
3287
    /* cannot carry out a command from a nested room */
3288
    cannotDoFromMsg(obj)
3289
    {
3290
        gMessageParams(obj);
3291
        return '{You/he} {can\'t} do that from {the obj/him}. ';
3292
    }
3293
3294
    /* cannot carry out a command from within a vehicle in a nested room */
3295
    vehicleCannotDoFromMsg(obj)
3296
    {
3297
        local loc = obj.location;
3298
        gMessageParams(obj, loc);
3299
        return '{You/he} {can\'t} do that while {the obj/he} {is} {in loc}. ';
3300
    }
3301
3302
    /* cannot go that way in a vehicle */
3303
    cannotGoThatWayInVehicleMsg(traveler)
3304
    {
3305
        gMessageParams(traveler);
3306
        return '{You/he} {can\'t} do that {in traveler}. ';
3307
    }
3308
3309
    /* cannot push an object that way */
3310
    cannotPushObjectThatWayMsg(obj)
3311
    {
3312
        gMessageParams(obj);
3313
        return '{You/he} {can\'t} go that way pushing {the obj/him}. ';
3314
    }
3315
3316
    /* cannot push an object to a nested room */
3317
    cannotPushObjectNestedMsg(obj)
3318
    {
3319
        gMessageParams(obj);
3320
        return '{You/he} {can\'t} push {the obj/him} there. ';
3321
    }
3322
3323
    /* cannot enter an exit-only passage */
3324
    cannotEnterExitOnlyMsg(obj)
3325
    {
3326
        gMessageParams(obj);
3327
        return '{You/he} {can\'t} enter {the obj/him} from {|t}here. ';
3328
    }
3329
3330
    /* must open door before going that way */
3331
    mustOpenDoorMsg(obj)
3332
    {
3333
        gMessageParams(obj);
3334
        return '{You/he} {must} open {the obj/him} first. ';
3335
    }
3336
3337
    /* door closes behind actor during travel through door */
3338
    doorClosesBehindMsg(obj)
3339
    {
3340
        gMessageParams(obj);
3341
        return '<.p>After {you/he} {goes} through {the obj/him}, {it/he}
3342
                close{s/d} behind {it actor/him}. ';
3343
    }
3344
3345
    /* the stairway does not go up/down */
3346
    stairwayNotUpMsg = '{The dobj/he} only {goes} down from {|t}here. '
3347
    stairwayNotDownMsg = '{The dobj/he} only {goes} up from {|t}here. '
3348
3349
    /* "wait" */
3350
    timePassesMsg = 'Time pass{es|ed}... '
3351
3352
    /* "hello" with no target actor */
3353
    sayHelloMsg = (addressingNoOneMsg)
3354
3355
    /* "goodbye" with no target actor */
3356
    sayGoodbyeMsg = (addressingNoOneMsg)
3357
3358
    /* "yes"/"no" with no target actor */
3359
    sayYesMsg = (addressingNoOneMsg)
3360
    sayNoMsg = (addressingNoOneMsg)
3361
3362
    /* an internal common handler for sayHelloMsg, sayGoodbyeMsg, etc */
3363
    addressingNoOneMsg
3364
    {
3365
        return '{You/he} {must} be more specific about '
3366
            + gLibMessages.whomPronoun
3367
            + ' {it actor/he} want{s/ed} to talk to. ';
3368
    }
3369
3370
    /* "yell" */
3371
    okayYellMsg = '{You/he} scream{s/ed} as loud as {it actor/he} {can}. '
3372
3373
    /* "jump" */
3374
    okayJumpMsg = '{You/he} jump{s/ed} a little, and land{s/ed} back where
3375
        {it actor/he} {|had} started. '
3376
3377
    /* cannot jump over object */
3378
    cannotJumpOverMsg = '{You/he} {can\'t} jump over {that dobj/him}. '
3379
3380
    /* cannot jump off object */
3381
    cannotJumpOffMsg = '{You/he} {can\'t} jump off {that dobj/him}. '
3382
3383
    /* cannot jump off (with no direct object) from here */
3384
    cannotJumpOffHereMsg = 'There{&rsquo;s| was} nowhere to jump
3385
        from {|t}here. '
3386
3387
    /* failed to find a topic in a consultable object */
3388
    cannotFindTopicMsg =
3389
        '{You/he} {can\'t} seem to find that in {the dobj/him}. '
3390
3391
    /* an actor doesn't accept a command from another actor */
3392
    refuseCommand(targetActor, issuingActor)
3393
    {
3394
        gMessageParams(targetActor, issuingActor);
3395
        return '{The targetActor/he} refuse{s/d} {your/his} request. ';
3396
    }
3397
3398
    /* cannot talk to an object (because it makes no sense to do so) */
3399
    notAddressableMsg(obj)
3400
    {
3401
        gMessageParams(obj);
3402
        return '{You/he} {cannot} talk to {that obj/him}. ';
3403
    }
3404
3405
    /* actor won't respond to a request or other communicative gesture */
3406
    noResponseFromMsg(other)
3407
    {
3408
        gMessageParams(other);
3409
        return '{The other/he} {does} not respond. ';
3410
    }
3411
3412
    /* trying to give something to someone who already has the object */
3413
    giveAlreadyHasMsg = '{The iobj/he} already {has} {that/him dobj}. '
3414
3415
    /* can't talk to yourself */
3416
    cannotTalkToSelfMsg = 'Talking to {yourself/himself}
3417
        {won&rsquo;t|wouldn&rsquo;t} accomplish anything. '
3418
3419
    /* can't ask yourself about anything */
3420
    cannotAskSelfMsg = 'Talking to {yourself/himself}
3421
        {won&rsquo;t|wouldn&rsquo;t} accomplish anything. '
3422
3423
    /* can't ask yourself for anything */
3424
    cannotAskSelfForMsg = 'Talking to {yourself/himself}
3425
        {won&rsquo;t|wouldn&rsquo;t} accomplish anything. '
3426
3427
    /* can't tell yourself about anything */
3428
    cannotTellSelfMsg = 'Talking to {yourself/himself}
3429
        {won&rsquo;t|wouldn&rsquo;t} accomplish anything. '
3430
3431
    /* can't give yourself something */
3432
    cannotGiveToSelfMsg = 'Giving {the dobj/him} to {yourself/himself}
3433
        {won&rsquo;t|wouldn&rsquo;t} accomplish anything. '
3434
    
3435
    /* can't give something to itself */
3436
    cannotGiveToItselfMsg = 'Giving {the dobj/him} to {itself}
3437
        {won&rsquo;t|wouldn&rsquo;t} accomplish anything. '
3438
3439
    /* can't show yourself something */
3440
    cannotShowToSelfMsg = 'Showing {the dobj/him} to {yourself/himself}
3441
        {won&rsquo;t|wouldn&rsquo;t} accomplish anything. '
3442
3443
    /* can't show something to itself */
3444
    cannotShowToItselfMsg = 'Showing {the dobj/him} to {itself}
3445
        {won&rsquo;t|wouldn&rsquo;t} accomplish anything. '
3446
3447
    /* can't give/show something to a non-actor */
3448
    cannotGiveToMsg = '{You/he} {cannot} give anything to {an iobj/him}. '
3449
    cannotShowToMsg = '{You/he} {cannot} show anything to {an iobj/him}. '
3450
3451
    /* actor isn't interested in something being given/shown */
3452
    notInterestedMsg(actor)
3453
    {
3454
        return '\^' + actor.nameDoes + ' not appear interested. ';
3455
    }
3456
3457
    /* vague ASK/TELL (for ASK/TELL <actor> <topic> syntax errors) */
3458
    askVagueMsg = '<.parser>The story doesn&rsquo;t understand that command.
3459
        Please use ASK ACTOR ABOUT TOPIC (or just A TOPIC).<./parser> '
3460
    tellVagueMsg = '<.parser>The story doesn&rsquo;t understand that command.
3461
        Please use TELL ACTOR ABOUT TOPIC (or just T TOPIC).<./parser> '
3462
3463
    /* object cannot hear actor */
3464
    objCannotHearActorMsg(obj)
3465
    {
3466
        return '\^' + obj.nameDoes
3467
            + ' not appear to hear {you/him}. ';
3468
    }
3469
3470
    /* actor cannot see object being shown to actor */
3471
    actorCannotSeeMsg(actor, obj)
3472
    {
3473
        return '\^' + actor.nameDoes + ' not appear to be able to see '
3474
            + obj.theNameObj + '. ';
3475
    }
3476
3477
    /* not a followable object */
3478
    notFollowableMsg = '{You/he} {cannot} follow {that dobj/him}. '
3479
3480
    /* cannot follow yourself */
3481
    cannotFollowSelfMsg = '{You/he} {cannot} follow {yourself}. '
3482
3483
    /* following an object that's in the same location as the actor */
3484
    followAlreadyHereMsg = '{The dobj/he} {is} right {|t}here. '
3485
3486
    /*
3487
     *   following an object that we *think* is in our same location (in
3488
     *   other words, we're already in the location where we thought we
3489
     *   last saw the object go), but it's too dark to see if that's
3490
     *   really true 
3491
     */
3492
    followAlreadyHereInDarkMsg = '{The dobj/he} should {be|have been} right
3493
        {|t}here, but {you/he} {can\'t} see {it dobj/him}. '
3494
3495
    /* trying to follow an object, but don't know where it went from here */
3496
    followUnknownMsg = '{You\'re} not sure where {the dobj/he}
3497
        {went|had gone} from {|t}here. '
3498
3499
    /*
3500
     *   we're trying to follow an actor, but we last saw the actor in the
3501
     *   given other location, so we have to go there to follow 
3502
     */
3503
    cannotFollowFromHereMsg(srcLoc)
3504
    {
3505
        return 'The last place {you/he} {saw|had seen} {the dobj/him} was '
3506
            + srcLoc.getDestName(gActor, gActor.location) + '. ';
3507
    }
3508
3509
    /* acknowledge a 'follow' for a target that was in sight */
3510
    okayFollowInSightMsg(loc)
3511
    {
3512
        return '{You/he} follow{s/ed} {the dobj/him} '
3513
            + loc.actorIntoName + '. ';
3514
    }
3515
3516
    /* obj is not a weapon */
3517
    notAWeaponMsg = '{You/he} {can\'t} attack anything with {the iobj/him}. '
3518
3519
    /* no effect attacking obj */
3520
    uselessToAttackMsg = '{You/he} {cannot} attack {that dobj/him}. '
3521
3522
    /* pushing object has no effect */
3523
    pushNoEffectMsg = 'Pushing {the dobj/him} {has|had} no effect. '
3524
3525
    /* default 'push button' acknowledgment */
3526
    okayPushButtonMsg = '<q>Click.</q> '
3527
3528
    /* lever is already in pushed state */
3529
    alreadyPushedMsg =
3530
        '{It\'s dobj} already pushed as far as {it dobj/he} {will} go. '
3531
3532
    /* default acknowledgment to pushing a lever */
3533
    okayPushLeverMsg = '{You/he} push{es/ed} {the dobj/him} to
3534
                     {its/her dobj} stop. '
3535
3536
    /* pulling object has no effect */
3537
    pullNoEffectMsg = 'Pulling {the dobj/him} {has|had} no effect. '
3538
3539
    /* lever is already in pulled state */
3540
    alreadyPulledMsg =
3541
        '{It\'s dobj} already pulled as far as {it dobj/he} {will} go. '
3542
3543
    /* default acknowledgment to pulling a lever */
3544
    okayPullLeverMsg = '{You/he} pull{s/ed} {the dobj/him} to
3545
                     {its/her dobj} stop. '
3546
3547
    /* default acknowledgment to pulling a spring-loaded lever */
3548
    okayPullSpringLeverMsg = '{You/he} pull{s/ed} {the dobj/him}, which
3549
        spr{ing[s]|ung} back to {its/her} starting position as soon as
3550
        {you/he} let{[s]|} go of {it dobj/him}. '
3551
3552
    /* moving object has no effect */
3553
    moveNoEffectMsg = 'Moving {the dobj/him} {has|had} no effect. '
3554
3555
    /* cannot move object to other object */
3556
    moveToNoEffectMsg = 'This would {|have} accomplish{|ed} nothing. '
3557
3558
    /* cannot push an object through travel */
3559
    cannotPushTravelMsg = 'This would {|have} accomplish{|ed} nothing. '
3560
3561
    /* acknowledge pushing an object through travel */
3562
    okayPushTravelMsg(obj)
3563
    {
3564
        return '<.p>{You/he} push{es/ed} ' + obj.theNameObj
3565
            + ' into the area. ';
3566
    }
3567
3568
    /* cannot use object as an implement to move something */
3569
    cannotMoveWithMsg =
3570
        '{You/he} {cannot} move anything with {the iobj/him}. '
3571
3572
    /* cannot set object to setting */
3573
    cannotSetToMsg = '{You/he} {cannot} set {that dobj/him} to anything. '
3574
3575
    /* invalid setting for generic Settable */
3576
    setToInvalidMsg = '{The dobj/he} {has} no such setting. '
3577
3578
    /* default 'set to' acknowledgment */
3579
    okaySetToMsg(val)
3580
        { return 'Okay, {the dobj/he} {is} now set to ' + val + '. '; }
3581
3582
    /* cannot turn object */
3583
    cannotTurnMsg = '{You/he} {cannot} turn {that dobj/him}. '
3584
3585
    /* must specify setting to turn object to */
3586
    mustSpecifyTurnToMsg = '{You/he} {must} specify the setting to
3587
                         turn {it dobj/him} to. '
3588
3589
    /* cannot turn anything with object */
3590
    cannotTurnWithMsg =
3591
        '{You/he} {cannot} turn anything with {that iobj/him}. '
3592
3593
    /* invalid setting for dial */
3594
    turnToInvalidMsg = '{The dobj/he} {has} no such setting. '
3595
3596
    /* default 'turn to' acknowledgment */
3597
    okayTurnToMsg(val)
3598
        { return 'Okay, {the dobj/he} {is} now set to ' + val + '. '; }
3599
3600
    /* switch is already on/off */
3601
    alreadySwitchedOnMsg = '{The dobj/he} {is} already on. '
3602
    alreadySwitchedOffMsg = '{The dobj/he} {is} already off. '
3603
3604
    /* default acknowledgment for switching on/off */
3605
    okayTurnOnMsg = 'Okay, {the dobj/he} {is} now on. '
3606
    okayTurnOffMsg = 'Okay, {the dobj/he} {is} now off. '
3607
3608
    /* flashlight is on but doesn't light up */
3609
    flashlightOnButDarkMsg = '{You/he} turn{s/ed} on {the dobj/him}, but
3610
        nothing seem{s|ed} to happen. '
3611
3612
    /* default acknowledgment for eating something */
3613
    okayEatMsg = '{You/he} {eat[s]|ate} {the dobj/him}. '
3614
3615
    /* object must be burning before doing that */
3616
    mustBeBurningMsg(obj)
3617
    {
3618
        return '{You/he} {must} light ' + obj.theNameObj
3619
            + ' before {it actor/he} {can} do that. ';
3620
    }
3621
3622
    /* match not lit */
3623
    matchNotLitMsg = '{The dobj/he} {is}n&rsquo;t lit. '
3624
3625
    /* lighting a match */
3626
    okayBurnMatchMsg =
3627
        '{You/he} str{ike[s]|uck} {the dobj/him}, igniting a small flame. '
3628
3629
    /* extinguishing a match */
3630
    okayExtinguishMatchMsg = '{You/he} put{[s]|} out {the dobj/him}, which
3631
        disappear{s/ed} into a cloud of ash. '
3632
3633
    /* trying to light a candle with no fuel */
3634
    candleOutOfFuelMsg =
3635
        '{The dobj/he} {is} too burned down; {it/he} {cannot} be lit. '
3636
3637
    /* lighting a candle */
3638
    okayBurnCandleMsg = '{You/he} {light[s]|lit} {the dobj/him}. '
3639
3640
    /* extinguishing a candle that isn't lit */
3641
    candleNotLitMsg = '{The dobj/he} {is} not lit. '
3642
3643
    /* extinguishing a candle */
3644
    okayExtinguishCandleMsg = 'Done. '
3645
3646
    /* cannot consult object */
3647
    cannotConsultMsg =
3648
        '{That dobj/he} {is} not something {you/he} {can} consult. '
3649
3650
    /* cannot type anything on object */
3651
    cannotTypeOnMsg = '{You/he} {cannot} type anything on {that dobj/him}. '
3652
3653
    /* cannot enter anything on object */
3654
    cannotEnterOnMsg = '{You/he} {cannot} enter anything on {that dobj/him}. '
3655
3656
    /* cannot switch object */
3657
    cannotSwitchMsg = '{You/he} {cannot} switch {that dobj/him}. '
3658
3659
    /* cannot flip object */
3660
    cannotFlipMsg = '{You/he} {cannot} flip {that dobj/him}. '
3661
3662
    /* cannot turn object on/off */
3663
    cannotTurnOnMsg =
3664
        '{That dobj/he} {is}n&rsquo;t something {you/he} {can} turn on. '
3665
    cannotTurnOffMsg =
3666
        '{That dobj/he} {is}n&rsquo;t something {you/he} {can} turn off. '
3667
3668
    /* cannot light */
3669
    cannotLightMsg = '{You/he} {cannot} light {that dobj/him}. '
3670
3671
    /* cannot burn */
3672
    cannotBurnMsg = '{That dobj/he} {is} not something {you/he} {can} burn. '
3673
    cannotBurnWithMsg =
3674
        '{You/he} {cannot} burn anything with {that iobj/him}. '
3675
3676
    /* cannot burn this specific direct object with this specific iobj */
3677
    cannotBurnDobjWithMsg = '{You/he} {cannot} light {the dobj/him}
3678
                          with {the iobj/him}. '
3679
3680
    /* object is already burning */
3681
    alreadyBurningMsg = '{The dobj/he} {is} already burning. '
3682
3683
    /* cannot extinguish */
3684
    cannotExtinguishMsg = '{You/he} {cannot} extinguish {that dobj/him}. '
3685
3686
    /* cannot pour/pour in/pour on */
3687
    cannotPourMsg = '{That dobj/he} {is} not something {you/he} {can} pour. '
3688
    cannotPourIntoMsg =
3689
        '{You/he} {cannot} pour anything into {that iobj/him}. '
3690
    cannotPourOntoMsg =
3691
        '{You/he} {cannot} pour anything onto {that iobj/him}. '
3692
3693
    /* cannot attach object to object */
3694
    cannotAttachMsg =
3695
        '{You/he} {cannot} attach {that dobj/him} to anything. '
3696
    cannotAttachToMsg =
3697
        '{You/he} {cannot} attach anything to {that iobj/him}. '
3698
3699
    /* cannot attach to self */
3700
    cannotAttachToSelfMsg =
3701
        '{You/he} {cannot} attach {the dobj/him} to {itself}. '
3702
3703
    /* cannot attach because we're already attached to the given object */
3704
    alreadyAttachedMsg =
3705
        '{The dobj/he} {is} already attached to {the iobj/him}. '
3706
3707
    /*
3708
     *   dobj and/or iobj can be attached to certain things, but not to
3709
     *   each other 
3710
     */
3711
    wrongAttachmentMsg =
3712
        '{You/he} {can\'t} attach {that dobj/him} to {the iobj/him}. '
3713
3714
    /* dobj and iobj are attached, but they can't be taken apart */
3715
    wrongDetachmentMsg =
3716
        '{You/he} {can\'t} detach {that dobj/him} from {the iobj/him}. '
3717
3718
    /* must detach the object before proceeding */
3719
    mustDetachMsg(obj)
3720
    {
3721
        gMessageParams(obj);
3722
        return '{You/he} {must} detach {the obj/him} before {it actor/he}
3723
            {can} do that. ';
3724
    }
3725
3726
    /* default message for successful Attachable attachment */
3727
    okayAttachToMsg = 'Done. '
3728
3729
    /* default message for successful Attachable detachment */
3730
    okayDetachFromMsg = 'Done. '
3731
3732
    /* cannot detach object from object */
3733
    cannotDetachMsg = '{You/he} {cannot} detach {that dobj/him}. '
3734
    cannotDetachFromMsg =
3735
        '{You/he} {cannot} detach anything from {that iobj/him}. '
3736
3737
    /* no obvious way to detach a permanent attachment */
3738
    cannotDetachPermanentMsg =
3739
        'There{&rsquo;s| was} no obvious way to detach {that dobj/him}. '
3740
3741
    /* dobj isn't attached to iobj */
3742
    notAttachedToMsg = '{The dobj/he} {is}n&rsquo;t attached
3743
        to {that iobj/him}. '
3744
3745
    /* breaking object would serve no purpose */
3746
    shouldNotBreakMsg =
3747
        'Breaking {that dobj/him} would {|have} serve{|d} no purpose. '
3748
3749
    /* cannot cut that */
3750
    cutNoEffectMsg = '{The iobj/he} {can\'t} seem to cut {the dobj/him}. '
3751
3752
    /* can't use iobj to cut anything */
3753
    cannotCutWithMsg = '{You/he} {can\'t} cut anything with {the iobj/him}. '
3754
3755
    /* cannot climb object */
3756
    cannotClimbMsg =
3757
        '{That dobj/he} {is} not something {you/he} {can} climb. '
3758
3759
    /* object is not openable/closable */
3760
    cannotOpenMsg = '{That dobj/he} {is} not something {you/he} {can} open. '
3761
    cannotCloseMsg =
3762
        '{That dobj/he} {is} not something {you/he} {can} close. '
3763
3764
    /* already open/closed */
3765
    alreadyOpenMsg = '{The dobj/he} {is} already open. '
3766
    alreadyClosedMsg = '{The dobj/he} {is} already closed. '
3767
3768
    /* already locked/unlocked */
3769
    alreadyLockedMsg = '{The dobj/he} {is} already locked. '
3770
    alreadyUnlockedMsg = '{The dobj/he} {is} already unlocked. '
3771
3772
    /* cannot look in container because it's closed */
3773
    cannotLookInClosedMsg = '{The dobj/he} {is} closed. '
3774
3775
    /* object is not lockable/unlockable */
3776
    cannotLockMsg =
3777
        '{That dobj/he} {is} not something {you/he} {can} lock. '
3778
    cannotUnlockMsg =
3779
        '{That dobj/he} {is} not something {you/he} {can} unlock. '
3780
3781
    /* attempting to open a locked object */
3782
    cannotOpenLockedMsg = '{The dobj/he} seem{s/ed} to be locked. '
3783
3784
    /* object requires a key to unlock */
3785
    unlockRequiresKeyMsg =
3786
        '{You/he} seem{s/ed} to need a key to unlock {the dobj/him}. '
3787
3788
    /* object is not a key */
3789
    cannotLockWithMsg =
3790
        '{The iobj/he} {does}n&rsquo;t look suitable for locking that. '
3791
    cannotUnlockWithMsg =
3792
        '{The iobj/he} {does}n&rsquo;t look suitable for unlocking that. '
3793
3794
    /* we don't know how to lock/unlock this */
3795
    unknownHowToLockMsg =
3796
        'It{&rsquo;s| was} not clear how to lock {the dobj/him}. '
3797
    unknownHowToUnlockMsg =
3798
        'It{&rsquo;s| was} not clear how to unlock {the dobj/him}. '
3799
3800
    /* the key (iobj) does not fit the lock (dobj) */
3801
    keyDoesNotFitLockMsg = '{The iobj/he} {does}n&rsquo;t fit the lock. '
3802
3803
    /* found key on keyring */
3804
    foundKeyOnKeyringMsg(ring, key)
3805
    {
3806
        gMessageParams(ring, key);
3807
        return '{You/he} tr{ies/ied} each key on {the ring/him}, and
3808
            {find[s actor]|found} that {the key/he} fit{s/ted} the lock. ';
3809
    }
3810
3811
    /* failed to find a key on keyring */
3812
    foundNoKeyOnKeyringMsg(ring)
3813
    {
3814
        gMessageParams(ring);
3815
        return '{You/he} tr{ies/ied} each key on {the ring/him},
3816
            but {you/he} {can\'t} find anything that fit{s|ted} the lock. ';
3817
    }
3818
3819
    /* not edible/drinkable */
3820
    cannotEatMsg = '{The dobj/he} {does} not appear to be edible. '
3821
    cannotDrinkMsg = '{That dobj/he} {does} not appear to be something
3822
        {you/he} {can} drink. '
3823
3824
    /* cannot clean object */
3825
    cannotCleanMsg =
3826
        '{You/he} wouldn&rsquo;t {|have} know{|n} how to
3827
        clean {that dobj/him}. '
3828
    cannotCleanWithMsg =
3829
        '{You/he} {can\'t} clean anything with {that iobj/him}. '
3830
3831
    /* cannot attach key (dobj) to (iobj) */
3832
    cannotAttachKeyToMsg =
3833
        '{You/he} {cannot} attach {the dobj/him} to {that iobj/him}. '
3834
3835
    /* actor cannot sleep */
3836
    cannotSleepMsg = '{You/he} {does}n&rsquo;t need to sleep right now. '
3837
3838
    /* cannot sit/lie/stand/get on/get out of */
3839
    cannotSitOnMsg =
3840
        '{That dobj/he} {is}n&rsquo;t something {you/he} {can} sit on. '
3841
    cannotLieOnMsg =
3842
        '{That dobj/he} {is}n&rsquo;t something {you/he} {can} lie on. '
3843
    cannotStandOnMsg = '{You/he} {can\'t} stand on {that dobj/him}. '
3844
    cannotBoardMsg = '{You/he} {can\'t} board {that dobj/him}. '
3845
    cannotUnboardMsg = '{You/he} {can\'t} get out of {that dobj/him}. '
3846
    cannotGetOffOfMsg = '{You/he} {can\'t} get off of {that dobj/him}. '
3847
3848
    /* standing on a PathPassage */
3849
    cannotStandOnPathMsg = 'If {you/he} want{s/ed} to follow {the dobj/him},
3850
        just say so. '
3851
3852
    /* cannot sit/lie/stand on something being held */
3853
    cannotEnterHeldMsg =
3854
        '{You/he} {can\'t} do that while {you\'re} holding {the dobj/him}. '
3855
3856
    /* cannot get out (of current location) */
3857
    cannotGetOutMsg = '{You\'re} not in anything {you/he} {can} disembark. '
3858
3859
    /* actor is already in a location */
3860
    alreadyInLocMsg = '{You\'re} already {in dobj}. '
3861
3862
    /* actor is already standing/sitting on/lying on */
3863
    alreadyStandingMsg = '{You\'re} already standing. '
3864
    alreadyStandingOnMsg = '{You\'re} already standing {on dobj}. '
3865
    alreadySittingMsg = '{You\'re} already sitting down. '
3866
    alreadySittingOnMsg = '{You\'re} already sitting {on dobj}. '
3867
    alreadyLyingMsg = '{You\'re} already lying down. '
3868
    alreadyLyingOnMsg = '{You\'re} already lying {on dobj}. '
3869
3870
    /* getting off something you're not on */
3871
    notOnPlatformMsg = '{You\'re} not {on dobj}. '
3872
3873
    /* no room to stand/sit/lie on dobj */
3874
    noRoomToStandMsg =
3875
        'There{&rsquo;s| was} no room for {you/him} to stand {on dobj}. '
3876
    noRoomToSitMsg =
3877
        'There{&rsquo;s| was} no room for {you/him} to sit {on dobj}. '
3878
    noRoomToLieMsg =
3879
        'There{&rsquo;s| was} no room for {you/him} to lie {on dobj}. '
3880
3881
    /* default report for standing up/sitting down/lying down */
3882
    okayPostureChangeMsg(posture)
3883
        { return 'Okay, {you\'re} now ' + posture.participle + '. '; }
3884
3885
    /* default report for standing/sitting/lying in/on something */
3886
    roomOkayPostureChangeMsg(posture, obj)
3887
    {
3888
        gMessageParams(obj);
3889
        return 'Okay, {you\'re} now ' + posture.participle + ' {on obj}. ';
3890
    }
3891
3892
    /* default report for getting off of a platform */
3893
    okayNotStandingOnMsg = 'Okay, {you\'re} no longer {on dobj}. '
3894
3895
    /* cannot fasten/unfasten */
3896
    cannotFastenMsg = '{You/he} {cannot} fasten {the dobj/him}. '
3897
    cannotFastenToMsg =
3898
        '{You/he} {cannot} fasten anything to {the iobj/him}. '
3899
    cannotUnfastenMsg = '{You/he} {cannot} unfasten {the dobj/him}. '
3900
    cannotUnfastenFromMsg =
3901
        '{You/he} {cannot} unfasten anything from {the iobj/him}. '
3902
3903
    /* cannot plug/unplug */
3904
    cannotPlugInMsg = '{You/he} {sees} no way to plug in {the dobj/him}. '
3905
    cannotPlugInToMsg =
3906
        '{You/he} {sees} no way to plug anything into {the iobj/him}. '
3907
    cannotUnplugMsg = '{You/he} {sees} no way to unplug {the dobj/him}. '
3908
    cannotUnplugFromMsg =
3909
        '{You/he} {sees} no way to unplug anything from {the iobj/him}. '
3910
3911
    /* cannot screw/unscrew */
3912
    cannotScrewMsg = '{You/he} {sees} no way to screw {the dobj/him}. '
3913
    cannotScrewWithMsg =
3914
        '{You/he} {cannot} screw anything with {the iobj/him}. '
3915
    cannotUnscrewMsg = '{You/he} {sees} no way to unscrew {the dobj/him}. '
3916
    cannotUnscrewWithMsg =
3917
        '{You/he} {cannot} unscrew anything with {the iobj/him}. '
3918
3919
    /* cannot enter/go through */
3920
    cannotEnterMsg =
3921
        '{That/he dobj} {is} not something {you/he} {can} enter. '
3922
    cannotGoThroughMsg =
3923
        '{That/he dobj} {is} not something {you/he} {can} go through. '
3924
        
3925
    /* can't throw something at itself */
3926
    cannotThrowAtSelfMsg =
3927
        '{You/he} {can\'t} throw {that dobj/him} at {itself}. '
3928
3929
    /* can't throw something at an object inside itself */
3930
    cannotThrowAtContentsMsg = '{You/he} {must} remove {the iobj/him}
3931
        from {the dobj/him} before {it actor/he} {can} do that. '
3932
3933
    /* shouldn't throw something at the floor */
3934
    shouldNotThrowAtFloorMsg =
3935
        '{You/he} should just {|have} put {it dobj/him} down instead. '
3936
3937
    /* THROW <obj> <direction> isn't supported; use THROW AT instead */
3938
    dontThrowDirMsg =
3939
        ('<.parser>You need to be more specific about
3940
            what ' + (gActor.referralPerson == ThirdPerson
3941
                      ? 'you want {the actor/him}' : '')
3942
         + ' to throw {the dobj/him} at.<./parser> ')
3943
3944
    /* thrown object bounces off target (short report) */
3945
    throwHitMsg(projectile, target)
3946
    {
3947
        gMessageParams(projectile, target);
3948
        return '{The projectile/he} hit{[s]|} {the target/him} without any
3949
            obvious effect. ';
3950
    }
3951
3952
    /* thrown object lands on target */
3953
    throwFallMsg(projectile, target)
3954
    {
3955
        gMessageParams(projectile, target);
3956
        return '{The projectile/he} land{s/ed} on {the target/him}. ';
3957
    }
3958
3959
    /* thrown object bounces off target and falls to destination */
3960
    throwHitFallMsg(projectile, target, dest)
3961
    {
3962
        gMessageParams(projectile, target);
3963
        return '{The projectile/he} hit{[s]|} {the target/him}
3964
            without any obvious effect, and {fall[s projectile]|fell} '
3965
            + dest.putInName + '. ';
3966
    }
3967
3968
    /* thrown object falls short of distant target (sentence prefix only) */
3969
    throwShortMsg(projectile, target)
3970
    {
3971
        gMessageParams(projectile, target);
3972
        return '{The projectile/he} {fall[s]|fell} well short of '
3973
               + '{the target/him}. ';
3974
    }
3975
        
3976
    /* thrown object falls short of distant target */
3977
    throwFallShortMsg(projectile, target, dest)
3978
    {
3979
        gMessageParams(projectile, target);
3980
        return '{The projectile/he} {fall[s]|fell} ' + dest.putInName
3981
            + ' well short of {the target/him}. ';
3982
    }
3983
3984
    /* target catches object */
3985
    throwCatchMsg(obj, target)
3986
    {
3987
        return '\^' + target.theName + ' '
3988
            + tSel('catch' + target.verbEndingEs, 'caught')
3989
            + ' ' + obj.theNameObj + '. ';
3990
    }
3991
3992
    /* we're not a suitable target for THROW TO (because we're not an NPC) */
3993
    cannotThrowToMsg = '{You/he} {cannot} throw anything to {an iobj/him}. '
3994
3995
    /* target does not want to catch anything */
3996
    willNotCatchMsg(catcher)
3997
    {
3998
        return '\^' + catcher.nameDoes
3999
            + 'n&rsquo;t look like ' + catcher.itNom + ' want'
4000
            + catcher.verbEndingSEd + ' to catch anything. ';
4001
    }
4002
4003
    /* cannot kiss something */
4004
    cannotKissMsg = 'Kissing {the dobj/him} {has|had} no obvious effect. '
4005
4006
    /* person uninterested in being kissed */
4007
    cannotKissActorMsg
4008
        = '{The dobj/he} probably wouldn&rsquo;t {|have} like{|d} that. '
4009
4010
    /* cannot kiss yourself */
4011
    cannotKissSelfMsg = '{You/he} {cannot} kiss {yourself}. '
4012
4013
    /* it is now dark at actor's location */
4014
    newlyDarkMsg = 'It {is|was} now pitch black. '
4015
;
4016
4017
/*
4018
 *   Non-player character verb messages.  By default, we inherit all of
4019
 *   the messages defined for the player character, but we override some
4020
 *   that must be rephrased slightly to make sense for NPC's.
4021
 */
4022
npcActionMessages: playerActionMessages
4023
    /* "wait" */
4024
    timePassesMsg = '{You/he} wait{s/ed}... '
4025
4026
    /* trying to move a Fixture/Immovable */
4027
    cannotMoveFixtureMsg = '{You/he} {cannot} move {that dobj/him}. '
4028
    cannotMoveImmovableMsg = '{You/he} {cannot} move {that dobj/him}. '
4029
4030
    /* trying to take/move/put a Heavy object */
4031
    cannotTakeHeavyMsg =
4032
        '{That dobj/he} {is} too heavy for {you/him} to take. '
4033
    cannotMoveHeavyMsg =
4034
        '{That dobj/he} {is} too heavy for {you/him} to move. '
4035
    cannotPutHeavyMsg =
4036
        '{That dobj/he} {is} too heavy for {you/him} to move. '
4037
4038
    /* trying to move a component object */
4039
    cannotMoveComponentMsg(loc)
4040
    {
4041
        return '{You/he} {cannot} do that because {the dobj/he} {is} part
4042
            of ' + loc.theNameObj + '. ';
4043
    }
4044
4045
    /* default successful 'take' response */
4046
    okayTakeMsg = '{You/he} {take[s]|took} {the dobj/him}. '
4047
4048
    /* default successful 'drop' response */
4049
    okayDropMsg = '{You/he} put{[s]|} down {the dobj/him}. '
4050
4051
    /* default successful 'put in' response */
4052
    okayPutInMsg = '{You/he} put{[s]|} {the dobj/him} in {the iobj/him}. '
4053
4054
    /* default successful 'put on' response */
4055
    okayPutOnMsg = '{You/he} put{[s]|} {the dobj/him} on {the iobj/him}. '
4056
4057
    /* default successful 'put under' response */
4058
    okayPutUnderMsg =
4059
        '{You/he} put{[s]|} {the dobj/him} under {the iobj/him}. '
4060
4061
    /* default successful 'put behind' response */
4062
    okayPutBehindMsg =
4063
        '{You/he} put{[s]|} {the dobj/him} behind {the iobj/him}. '
4064
4065
    /* default succesful response to 'wear obj' */
4066
    okayWearMsg =
4067
        '{You/he} put{[s]|} on {the dobj/him}. '
4068
4069
    /* default successful response to 'doff obj' */
4070
    okayDoffMsg = '{You/he} {take[s]|took} off {the dobj/him}. '
4071
4072
    /* default successful responses to open/close */
4073
    okayOpenMsg = '{You/he} open{s/ed} {the dobj/him}. '
4074
    okayCloseMsg = '{You/he} close{s/d} {the dobj/him}. '
4075
4076
    /* default successful responses to lock/unlock */
4077
    okayLockMsg = '{You/he} lock{s/ed} {the dobj/him}. '
4078
    okayUnlockMsg = '{You/he} unlock{s/ed} {the dobj/him}. '
4079
4080
    /* push/pull/move with no effect */
4081
    pushNoEffectMsg = '{You/he} tr{ies/ied} to push {the dobj/him}, with no '
4082
                      + 'obvious effect. '
4083
    pullNoEffectMsg = '{You/he} tr{ies/ied} to pull {the dobj/him}, with no '
4084
                      + 'obvious effect. '
4085
    moveNoEffectMsg = '{You/he} tr{ies/ied} to move {the dobj/him}, with no '
4086
                      + 'obvious effect. '
4087
    moveToNoEffectMsg = '{You/he} {leaves} {the dobj/he} where {it/he} {is}. '
4088
4089
    whereToGoMsg =
4090
        'You&rsquo;ll have to say which way {you/he} should {|have} go{|ne}. '
4091
4092
    /* object is too large for container */
4093
    tooLargeForContainerMsg(obj, cont)
4094
    {
4095
        gMessageParams(obj, cont);
4096
        return '{You/he} {cannot} do that because {the obj/he} {is}
4097
            too large for {the cont/him}. ';
4098
    }
4099
4100
    /* object is too large for underside */
4101
    tooLargeForUndersideMsg(obj, cont)
4102
    {
4103
        gMessageParams(obj, cont);
4104
        return '{You/he} {cannot} do that because {the obj/he}
4105
            {won\'t} fit under {the cont/him}. ';
4106
    }
4107
4108
    /* object is too large to fit behind something */
4109
    tooLargeForRearMsg(obj, cont)
4110
    {
4111
        gMessageParams(obj, cont);
4112
        return '{You/he} {cannot} do that because {the obj/he}
4113
            {won\'t} fit behind {the cont/him}. ';
4114
    }
4115
4116
    /* container doesn't have room for object */
4117
    containerTooFullMsg(obj, cont)
4118
    {
4119
        gMessageParams(obj, cont);
4120
        return '{You/he} {cannot} do that because {the cont/he} {is}
4121
            already too full to hold {the obj/him}. ';
4122
    }
4123
4124
    /* surface doesn't have room for object */
4125
    surfaceTooFullMsg(obj, cont)
4126
    {
4127
        gMessageParams(obj, cont);
4128
        return '{You/he} {cannot} do that because there{\'s| was}
4129
            no room for {the obj/him} on {the cont/him}. ';
4130
    }
4131
4132
    /* the dobj doesn't fit on this keyring */
4133
    objNotForKeyringMsg = '{You/he} {cannot} do that because {that dobj/he}
4134
        {does}n&rsquo;t fit on {the iobj/him}. '
4135
4136
    /* taking dobj from iobj, but dobj isn't in iobj */
4137
    takeFromNotInMsg = '{You/he} {cannot} do that because
4138
        {the dobj/he} {is}n&rsquo;t in {that iobj/him}. '
4139
4140
    /* taking dobj from surface, but dobj isn't on iobj */
4141
    takeFromNotOnMsg = '{You/he} {cannot} do that because
4142
        {the dobj/he} {is}n&rsquo;t on {that iobj/him}. '
4143
4144
    /* taking dobj under something, but dobj isn't under iobj */
4145
    takeFromNotUnderMsg = '{You/he} {cannot} do that because
4146
        {the dobj/he} {is}n&rsquo;t under {that iobj/him}. '
4147
4148
    /* taking dobj from behind something, but dobj isn't behind iobj */
4149
    takeFromNotBehindMsg = '{You/he} {cannot} do that because
4150
        {the dobj/he} {is}n&rsquo;t behind {that iobj/him}. '
4151
4152
    /* cannot jump off (with no direct object) from here */
4153
    cannotJumpOffHereMsg = 'There{&rsquo;s| was} nowhere for
4154
        {you/him} to jump. '
4155
4156
    /* should not break object */
4157
    shouldNotBreakMsg = '{You/he} {does}n&rsquo;t want to
4158
        break {that dobj/him}. '
4159
4160
    /* report for standing up/sitting down/lying down */
4161
    okayPostureChangeMsg(posture)
4162
        { return '{You/he} ' + posture.msgVerbI + '. '; }
4163
4164
    /* report for standing/sitting/lying in/on something */
4165
    roomOkayPostureChangeMsg(posture, obj)
4166
    {
4167
        gMessageParams(obj);
4168
        return '{You/he} ' + posture.msgVerbT + ' {on obj}. ';
4169
    }
4170
4171
    /* report for getting off a platform */
4172
    okayNotStandingOnMsg = '{You/he} {get[s]|got} {offof dobj}. '
4173
4174
    /* default 'turn to' acknowledgment */
4175
    okayTurnToMsg(val)
4176
        { return '{You/he} turn{s/ed} {the dobj/him} to ' + val + '. '; }
4177
4178
    /* default 'push button' acknowledgment */
4179
    okayPushButtonMsg = '{You/he} push{es/ed} {the dobj/him}. '
4180
4181
    /* default acknowledgment for switching on/off */
4182
    okayTurnOnMsg = '{You/he} turn{s/ed} {the dobj/him} on. '
4183
    okayTurnOffMsg = '{You/he} turn{s/ed} {the dobj/him} off. '
4184
4185
    /* the key (iobj) does not fit the lock (dobj) */
4186
    keyDoesNotFitLockMsg = '{You/he} tr{ies/ied} {the iobj/he}, but
4187
                         {it iobj/he} {does}n&rsquo;t fit the lock. '
4188
4189
    /* acknowledge entering "follow" mode */
4190
    okayFollowModeMsg = '<q>Okay, I will follow {the dobj/him}.</q> '
4191
4192
    /* note that we're already in "follow" mode */
4193
    alreadyFollowModeMsg = '<q>I\'m already following {the dobj/him}.</q> '
4194
4195
    /* extinguishing a candle */
4196
    okayExtinguishCandleMsg = '{You/he} extinguish{es/ed} {the dobj/him}. '
4197
4198
    /* acknowledge attachment */
4199
    okayAttachToMsg =
4200
        '{You/he} attach{es/ed} {the dobj/him} to {the iobj/him}. '
4201
4202
    /* acknowledge detachment */
4203
    okayDetachFromMsg =
4204
        '{You/he} detach{es/ed} {the dobj/him} from {the iobj/him}. '
4205
4206
    /*
4207
     *   the PC's responses to conversational actions applied to oneself
4208
     *   need some reworking for NPC's 
4209
     */
4210
    cannotTalkToSelfMsg = '{You/he} {won\'t} accomplish anything talking
4211
        to {yourself/himself}. '
4212
    cannotAskSelfMsg = '{You/he} {won\'t} accomplish anything talking
4213
        to {yourself/himself}. '
4214
    cannotAskSelfForMsg = '{You/he} {won\'t} accomplish anything talking
4215
        to {yourself/himself}. '
4216
    cannotTellSelfMsg = '{You/he} {won\'t} accomplish anything talking
4217
        to {yourself/himself}. '
4218
    cannotGiveToSelfMsg = '{You/he} {won\'t} accomplish anything
4219
        giving {the dobj/him} to {yourself/himself}. '
4220
    cannotShowToSelfMsg = '{You/he} {won\'t} accomplish anything
4221
        showing {the dobj/him} to {yourself/himself}. '
4222
;
4223
4224
/* ------------------------------------------------------------------------ */
4225
/*
4226
 *   Standard tips
4227
 */
4228
4229
scoreChangeTip: Tip
4230
    "If you&rsquo;d prefer not to be notified about score changes in the
4231
    future, type <<aHref('notify off', 'NOTIFY OFF', 'Turn off score
4232
    notificatons')>>."
4233
;
4234
4235
footnotesTip: Tip
4236
    "A number in [square brackets] like the one above refers to a footnote,
4237
    which you can read by typing FOOTNOTE followed by the number:
4238
    <<aHref('footnote 1', 'FOOTNOTE 1', 'Show footnote [1]')>>, for example.
4239
    Footnotes usually contain added background information that might be
4240
    interesting but isn&rsquo;t essential to the story. If you&rsquo;d
4241
    prefer not to see footnotes at all, you can control their appearance by
4242
    typing <<aHref('footnotes', 'FOOTNOTES', 'Control footnote
4243
    appearance')>>."
4244
;
4245
4246
oopsTip: Tip
4247
    "If this was an accidental misspelling, you can correct it by typing
4248
    OOPS followed by the corrected word now. Any time the story points out an
4249
    unknown word, you can correct a misspelling using OOPS as your next
4250
    command."
4251
;
4252
4253
fullScoreTip: Tip
4254
    "To see a detailed accounting of your score, type
4255
    <<aHref('full score', 'FULL SCORE')>>."
4256
;
4257
4258
exitsTip: Tip
4259
    "You can control the exit listings with the EXITS command.
4260
    <<aHref('exits status', 'EXITS STATUS',
4261
            'Turn on status line exit listings')>>
4262
    shows the exit list in the status line,
4263
    <<aHref('exits look', 'EXITS LOOK', 'List exits in room descriptions')>>
4264
    shows a full exit list in each room description,
4265
    <<aHref('exits on', 'EXITS ON', 'Turn on all exit lists')>>
4266
    shows both, and
4267
    <<aHref('exits off', 'EXITS OFF', 'Turn off all exit lists')>>
4268
    turns off both kinds of exit lists."
4269
;
4270
4271
undoTip: Tip
4272
    "If this didn't turn out quite the way you expected, note that you
4273
    can always take back a turn by typing <<aHref('undo', 'UNDO',
4274
        'Take back the most recent command')>>.  You can even use
4275
    UNDO repeatedly to take back several turns in a row. "
4276
;
4277
4278
4279
/* ------------------------------------------------------------------------ */
4280
/*
4281
 *   Listers
4282
 */
4283
4284
/*
4285
 *   The basic "room lister" object - this is the object that we use by
4286
 *   default with showList() to construct the listing of the portable
4287
 *   items in a room when displaying the room's description.  
4288
 */
4289
roomLister: Lister
4290
    /* show the prefix/suffix in wide mode */
4291
    showListPrefixWide(itemCount, pov, parent) { "{You/he} {sees} "; }
4292
    showListSuffixWide(itemCount, pov, parent) { " {|t}here. "; }
4293
4294
    /* show the tall prefix */
4295
    showListPrefixTall(itemCount, pov, parent) { "{You/he} {sees}:"; }
4296
;
4297
4298
/*
4299
 *   The basic room lister for dark rooms 
4300
 */
4301
darkRoomLister: Lister
4302
    showListPrefixWide(itemCount, pov, parent)
4303
        { "In the darkness {you/he} {can} see "; }
4304
4305
    showListSuffixWide(itemCount, pov, parent) { ". "; }
4306
4307
    showListPrefixTall(itemCount, pov, parent)
4308
        { "In the darkness {you/he} {sees}:"; }
4309
;
4310
4311
/*
4312
 *   A "remote room lister".  This is used to describe the contents of an
4313
 *   adjoining room.  For example, if an actor is standing in one room,
4314
 *   and can see into a second top-level room through a window, we'll use
4315
 *   this lister to describe the objects the actor can see through the
4316
 *   window. 
4317
 */
4318
class RemoteRoomLister: Lister
4319
    construct(room) { remoteRoom = room; }
4320
    
4321
    showListPrefixWide(itemCount, pov, parent)
4322
        { "\^<<remoteRoom.inRoomName(pov)>>, {you/he} {sees} "; }
4323
    showListSuffixWide(itemCount, pov, parent)
4324
        { ". "; }
4325
4326
    showListPrefixTall(itemCount, pov, parent)
4327
        { "\^<<remoteRoom.inRoomName(pov)>>, {you/he} {sees}:"; }
4328
4329
    /* the remote room we're viewing */
4330
    remoteRoom = nil
4331
;
4332
4333
/*
4334
 *   A simple customizable room lister.  This can be used to create custom
4335
 *   listers for things like remote room contents listings.  We act just
4336
 *   like any ordinary room lister, but we use custom prefix and suffix
4337
 *   strings provided during construction.  
4338
 */
4339
class CustomRoomLister: Lister
4340
    construct(prefix, suffix)
4341
    {
4342
        prefixStr = prefix;
4343
        suffixStr = suffix;
4344
    }
4345
4346
    showListPrefixWide(itemCount, pov, parent) { "<<prefixStr>> "; }
4347
    showListSuffixWide(itemCount, pov, parent) { "<<suffixStr>> "; }
4348
    showListPrefixTall(itemCount, pov, parent) { "<<prefixStr>>:"; }
4349
4350
    /* our prefix and suffix strings */
4351
    prefixStr = nil
4352
    suffixStr = nil
4353
;
4354
4355
/*
4356
 *   Single-list inventory lister.  This shows the inventory listing as a
4357
 *   single list, with worn items mixed in among the other inventory items
4358
 *   and labeled "(being worn)".  
4359
 */
4360
actorSingleInventoryLister: InventoryLister
4361
    showListPrefixWide(itemCount, pov, parent)
4362
        { "<<buildSynthParam('The/he', parent)>> {is} carrying "; }
4363
    showListSuffixWide(itemCount, pov, parent)
4364
        { ". "; }
4365
4366
    showListPrefixTall(itemCount, pov, parent)
4367
        { "<<buildSynthParam('The/he', parent)>> {is} carrying:"; }
4368
    showListContentsPrefixTall(itemCount, pov, parent)
4369
        { "<<buildSynthParam('A/he', parent)>>, who {is} carrying:"; }
4370
4371
    showListEmpty(pov, parent)
4372
        { "<<buildSynthParam('The/he', parent)>> {is} empty-handed. "; }
4373
;
4374
4375
/*
4376
 *   Standard inventory lister for actors - this will work for the player
4377
 *   character and NPC's as well.  This lister uses a "divided" format,
4378
 *   which segregates the listing into items being carried and items being
4379
 *   worn.  We'll combine the two lists into a single sentence if the
4380
 *   overall list is short, otherwise we'll show two separate sentences for
4381
 *   readability.  
4382
 */
4383
actorInventoryLister: DividedInventoryLister
4384
    /*
4385
     *   Show the combined inventory listing, putting together the raw
4386
     *   lists of the items being carried and the items being worn. 
4387
     */
4388
    showCombinedInventoryList(parent, carrying, wearing)
4389
    {
4390
        /* if one or the other sentence is empty, the format is simple */
4391
        if (carrying == '' && wearing == '')
4392
        {
4393
            /* the parent is completely empty-handed */
4394
            showInventoryEmpty(parent);
4395
        }
4396
        else if (carrying == '')
4397
        {
4398
            /* the whole list is being worn */
4399
            showInventoryWearingOnly(parent, wearing);
4400
        }
4401
        else if (wearing == '')
4402
        {
4403
            /* the whole list is being carried */
4404
            showInventoryCarryingOnly(parent, carrying);
4405
        }
4406
        else
4407
        {
4408
            /*
4409
             *   Both listings are populated.  Count the number of
4410
             *   comma-separated or semicolon-separated phrases in each
4411
             *   list.  This will give us an estimate of the grammatical
4412
             *   complexity of each list.  If we have very short lists, a
4413
             *   single sentence will be easier to read; if the lists are
4414
             *   long, we'll show the lists in separate sentences.  
4415
             */
4416
            if (countPhrases(carrying) + countPhrases(wearing)
4417
                <= singleSentenceMaxNouns)
4418
            {
4419
                /* short enough: use a single-sentence format */
4420
                showInventoryShortLists(parent, carrying, wearing);
4421
            }
4422
            else
4423
            {
4424
                /* long: use a two-sentence format */
4425
                showInventoryLongLists(parent, carrying, wearing);
4426
            }
4427
        }
4428
    }
4429
4430
    /*
4431
     *   Count the noun phrases in a string.  We'll count the number of
4432
     *   elements in the list as indicated by commas and semicolons.  This
4433
     *   might not be a perfect count of the actual number of noun phrases,
4434
     *   since we could have commas setting off some other kind of clauses,
4435
     *   but it nonetheless will give us a good estimate of the overall
4436
     *   complexity of the text, which is what we're really after.  The
4437
     *   point is that we want to break up the listings if they're long,
4438
     *   but combine them into a single sentence if they're short.  
4439
     */
4440
    countPhrases(txt)
4441
    {
4442
        local cnt;
4443
        
4444
        /* if the string is empty, there are no phrases at all */
4445
        if (txt == '')
4446
            return 0;
4447
4448
        /* a non-empty string has at least one phrase */
4449
        cnt = 1;
4450
4451
        /* scan for commas and semicolons */
4452
        for (local startIdx = 1 ;;)
4453
        {
4454
            local idx;
4455
            
4456
            /* find the next phrase separator */
4457
            idx = rexSearch(phraseSepPat, txt, startIdx);
4458
4459
            /* if we didn't find it, we're done */
4460
            if (idx == nil)
4461
                break;
4462
4463
            /* count it */
4464
            ++cnt;
4465
4466
            /* continue scanning after the separator */
4467
            startIdx = idx[1] + idx[2];
4468
        }
4469
4470
        /* return the count */
4471
        return cnt;
4472
    }
4473
4474
    phraseSepPat = static new RexPattern(',(?! and )|;| and |<rparen>')
4475
4476
    /*
4477
     *   Once we've made up our mind about the format, we'll call one of
4478
     *   these methods to show the final sentence.  These are all separate
4479
     *   methods so that the individual formats can be easily tweaked
4480
     *   without overriding the whole combined-inventory-listing method. 
4481
     */
4482
    showInventoryEmpty(parent)
4483
    {
4484
        /* empty inventory */
4485
        "<<buildSynthParam('The/he', parent)>> {is} empty-handed. ";
4486
    }
4487
    showInventoryWearingOnly(parent, wearing)
4488
    {
4489
        /* we're carrying nothing but wearing some items */
4490
        "<<buildSynthParam('The/he', parent)>> {is} carrying nothing,
4491
        and {is} wearing <<wearing>>. ";
4492
    }
4493
    showInventoryCarryingOnly(parent, carrying)
4494
    {
4495
        /* we have only carried items to report */
4496
        "<<buildSynthParam('The/he', parent)>> {is} carrying <<carrying>>. ";
4497
    }
4498
    showInventoryShortLists(parent, carrying, wearing)
4499
    {
4500
        local nm = gSynthMessageParam(parent);
4501
        
4502
        /* short lists - combine carried and worn in a single sentence */
4503
        "<<buildParam('The/he', nm)>> {is} carrying <<carrying>>,
4504
        and <<buildParam('it\'s', nm)>>{subj} wearing <<wearing>>. ";
4505
    }
4506
    showInventoryLongLists(parent, carrying, wearing)
4507
    {
4508
        local nm = gSynthMessageParam(parent);
4509
4510
        /* long lists - show carried and worn in separate sentences */
4511
        "<<buildParam('The/he', nm)>> {is} carrying <<carrying>>.
4512
        <<buildParam('It\'s', nm)>> wearing <<wearing>>. ";
4513
    }
4514
4515
    /*
4516
     *   For 'tall' listings, we'll use the standard listing style, so we
4517
     *   need to provide the framing messages for the tall-mode listing.  
4518
     */
4519
    showListPrefixTall(itemCount, pov, parent)
4520
        { "<<buildSynthParam('The/he', parent)>> {is} carrying:"; }
4521
    showListContentsPrefixTall(itemCount, pov, parent)
4522
        { "<<buildSynthParam('A/he', parent)>>, who {is} carrying:"; }
4523
    showListEmpty(pov, parent)
4524
        { "<<buildSynthParam('The/he', parent)>> {is} empty-handed. "; }
4525
;
4526
4527
/*
4528
 *   Special inventory lister for non-player character descriptions - long
4529
 *   form lister.  This is used to display the inventory of an NPC as part
4530
 *   of the full description of the NPC.
4531
 *   
4532
 *   This long form lister is meant for actors with lengthy descriptions.
4533
 *   We start the inventory listing on a new line, and use the actor's
4534
 *   full name in the list preface.  
4535
 */
4536
actorHoldingDescInventoryListerLong: actorInventoryLister
4537
    showInventoryEmpty(parent)
4538
    {
4539
        /* empty inventory - saying nothing in an actor description */
4540
    }
4541
    showInventoryWearingOnly(parent, wearing)
4542
    {
4543
        /* we're carrying nothing but wearing some items */
4544
        "<.p><<buildSynthParam('The/he', parent)>> {is}
4545
        wearing <<wearing>>. ";
4546
    }
4547
    showInventoryCarryingOnly(parent, carrying)
4548
    {
4549
        /* we have only carried items to report */
4550
        "<.p><<buildSynthParam('The/he', parent)>> {is} carrying
4551
        <<carrying>>. ";
4552
    }
4553
    showInventoryShortLists(parent, carrying, wearing)
4554
    {
4555
        local nm = gSynthMessageParam(parent);
4556
4557
        /* short lists - combine carried and worn in a single sentence */
4558
        "<.p><<buildParam('The/he', nm)>> {is} carrying <<carrying>>,
4559
        and <<buildParam('it\'s', nm)>>{subj} wearing <<wearing>>. ";
4560
    }
4561
    showInventoryLongLists(parent, carrying, wearing)
4562
    {
4563
        local nm = gSynthMessageParam(parent);
4564
4565
        /* long lists - show carried and worn in separate sentences */
4566
        "<.p><<buildParam('The/he', nm)>> {is} carrying <<carrying>>.
4567
        <<buildParam('It\'s', nm)>> wearing <<wearing>>. ";
4568
    }
4569
;
4570
4571
/* short form of non-player character description inventory lister */
4572
actorHoldingDescInventoryListerShort: actorInventoryLister
4573
    showInventoryEmpty(parent)
4574
    {
4575
        /* empty inventory - saying nothing in an actor description */
4576
    }
4577
    showInventoryWearingOnly(parent, wearing)
4578
    {
4579
        /* we're carrying nothing but wearing some items */
4580
        "<<buildSynthParam('It/he', parent)>> {is} wearing <<wearing>>. ";
4581
    }
4582
    showInventoryCarryingOnly(parent, carrying)
4583
    {
4584
        /* we have only carried items to report */
4585
        "<<buildSynthParam('It/he', parent)>> {is} carrying <<carrying>>. ";
4586
    }
4587
    showInventoryShortLists(parent, carrying, wearing)
4588
    {
4589
        local nm = gSynthMessageParam(parent);
4590
4591
        /* short lists - combine carried and worn in a single sentence */
4592
        "<<buildParam('It/he', nm)>> {is} carrying <<carrying>>, and
4593
        <<buildParam('it\'s', nm)>>{subj} wearing <<wearing>>. ";
4594
    }
4595
    showInventoryLongLists(parent, carrying, wearing)
4596
    {
4597
        local nm = gSynthMessageParam(parent);
4598
4599
        /* long lists - show carried and worn in separate sentences */
4600
        "<<buildParam('It/he', nm)>> {is} carrying <<carrying>>.
4601
        <<buildParam('It\'s', nm)>> wearing <<wearing>>. ";
4602
    }
4603
;
4604
4605
/*
4606
 *   Base contents lister for things.  This is used to display the contents
4607
 *   of things shown in room and inventory listings; we subclass this for
4608
 *   various purposes 
4609
 */
4610
class BaseThingContentsLister: Lister
4611
    showListPrefixWide(itemCount, pov, parent)
4612
        { "\^<<parent.nameVerb('contain')>> "; }
4613
    showListSuffixWide(itemCount, pov, parent)
4614
        { ". "; }
4615
    showListPrefixTall(itemCount, pov, parent)
4616
        { "\^<<parent.nameVerb('contain')>>:"; }
4617
    showListContentsPrefixTall(itemCount, pov, parent)
4618
        { "<<parent.aName>>, which contain<<parent.verbEndingSEd>>:"; }
4619
;
4620
4621
/*
4622
 *   Contents lister for things.  This is used to display the second-level
4623
 *   contents lists for things listed in the top-level list for a room
4624
 *   description, inventory listing, or object description.  
4625
 */
4626
thingContentsLister: ContentsLister, BaseThingContentsLister
4627
;
4628
4629
/*
4630
 *   Contents lister for openable things.
4631
 */
4632
openableContentsLister: thingContentsLister
4633
    showListEmpty(pov, parent)
4634
    {
4635
        "\^<<parent.openStatus>>. ";
4636
    }
4637
    showListPrefixWide(itemCount, pov, parent)
4638
    {
4639
        "\^<<parent.openStatus>>, and contain<<parent.verbEndingSEd>> ";
4640
    }
4641
;
4642
4643
/*
4644
 *   Contents lister for descriptions of things - this is used to display
4645
 *   the contents of a thing as part of the long description of the thing
4646
 *   (in response to an "examine" command); it differs from a regular
4647
 *   thing contents lister in that we use a pronoun to refer to the thing,
4648
 *   rather than its full name, since the full name was probably just used
4649
 *   in the basic long description.  
4650
 */
4651
thingDescContentsLister: DescContentsLister, BaseThingContentsLister
4652
    showListPrefixWide(itemCount, pov, parent)
4653
        { "\^<<parent.itVerb('contain')>> "; }
4654
;
4655
4656
/*
4657
 *   Base contents lister for "LOOK <PREP>" commands (LOOK IN, LOOK UNDER,
4658
 *   LOOK BEHIND, etc).  This can be subclasses for the appropriate LOOK
4659
 *   <PREP> command matching the container type - LOOK UNDER for
4660
 *   undersides, LOOK BEHIND for rear containers, etc.  To use this class,
4661
 *   combine it via multiple inheritance with the appropriate
4662
 *   Base<Prep>ContentsLister for the preposition type.  
4663
 */
4664
class LookWhereContentsLister: DescContentsLister
4665
    showListEmpty(pov, parent)
4666
    {
4667
        /* show a default message indicating the surface is empty */
4668
        gMessageParams(parent);
4669
        defaultDescReport('{You/he} {sees} nothing ' + parent.objInPrep
4670
                          + ' {the parent/him}. ');
4671
    }
4672
;
4673
4674
/*
4675
 *   Contents lister for descriptions of things whose contents are
4676
 *   explicitly inspected ("look in").  This differs from a regular
4677
 *   contents lister in that we explicitly say that the object is empty if
4678
 *   it's empty.
4679
 */
4680
thingLookInLister: LookWhereContentsLister, BaseThingContentsLister
4681
    showListEmpty(pov, parent)
4682
    {
4683
        /*
4684
         *   Indicate that the list is empty, but make this a default
4685
         *   descriptive report.  This way, if we report any special
4686
         *   descriptions for items contained within the object, we'll
4687
         *   suppress this default description that there's nothing to
4688
         *   describe, which is clearly wrong if there are
4689
         *   specially-described contents. 
4690
         */
4691
        gMessageParams(parent);
4692
        defaultDescReport('{You/he} {sees} nothing unusual
4693
            in {the parent/him}. ');
4694
    }
4695
;
4696
4697
/*
4698
 *   Default contents lister for newly-revealed objects after opening a
4699
 *   container.  
4700
 */
4701
openableOpeningLister: BaseThingContentsLister
4702
    showListEmpty(pov, parent) { }
4703
    showListPrefixWide(itemCount, pov, parent)
4704
    {
4705
        /*
4706
         *   This list is, by default, generated as a replacement for the
4707
         *   default "Opened" message in response to an OPEN command.  We
4708
         *   therefore need different messages for PC and NPC actions,
4709
         *   since this serves as the description of the entire action.
4710
         *   
4711
         *   Note that if you override the Open action response for a given
4712
         *   object, you might want to customize this lister as well, since
4713
         *   the message we generate (especially for an NPC action)
4714
         *   presumes that we'll be the only response the command.  
4715
         */
4716
        gMessageParams(pov, parent);
4717
        if (pov.isPlayerChar())
4718
            "Opening {the parent/him} reveal{s|ed} ";
4719
        else
4720
            "{The pov/he} open{s/ed} {the parent/him}, revealing ";
4721
    }
4722
;
4723
4724
/*
4725
 *   Base contents lister.  This class handles contents listings for most
4726
 *   kinds of specialized containers - Surfaces, RearConainers,
4727
 *   RearSurfaces, and Undersides.  The main variation in the contents
4728
 *   listings for these various types of containers is simply the
4729
 *   preposition that's used to describe the relationship between the
4730
 *   container and the contents, and for this we can look to the objInPrep
4731
 *   property of the container.  
4732
 */
4733
class BaseContentsLister: Lister
4734
    showListPrefixWide(itemCount, pov, parent)
4735
    {
4736
        "\^<<parent.objInPrep>> <<parent.theNameObj>>
4737
        <<itemCount == 1 ? tSel('is', 'was') : tSel('are', 'were')>> ";
4738
    }
4739
    showListSuffixWide(itemCount, pov, parent)
4740
    {
4741
        ". ";
4742
    }
4743
    showListPrefixTall(itemCount, pov, parent)
4744
    {
4745
        "\^<<parent.objInPrep>> <<parent.theNameObj>>
4746
        <<itemCount == 1 ? tSel('is', 'was') : tSel('are', 'were')>>:";
4747
    }
4748
    showListContentsPrefixTall(itemCount, pov, parent)
4749
    {
4750
        "<<parent.aName>>, <<parent.objInPrep>> which
4751
        <<itemCount == 1 ? tSel('is', 'was') : tSel('are', 'were')>>:";
4752
    }
4753
;
4754
4755
4756
/*
4757
 *   Base class for contents listers for a surface 
4758
 */
4759
class BaseSurfaceContentsLister: BaseContentsLister
4760
;
4761
4762
/*
4763
 *   Contents lister for a surface 
4764
 */
4765
surfaceContentsLister: ContentsLister, BaseSurfaceContentsLister
4766
;
4767
4768
/*
4769
 *   Contents lister for explicitly looking in a surface 
4770
 */
4771
surfaceLookInLister: LookWhereContentsLister, BaseSurfaceContentsLister
4772
;
4773
4774
/*
4775
 *   Contents lister for a surface, used in a long description. 
4776
 */
4777
surfaceDescContentsLister: DescContentsLister, BaseSurfaceContentsLister
4778
;
4779
4780
/*
4781
 *   Contents lister for room parts
4782
 */
4783
roomPartContentsLister: surfaceContentsLister
4784
    isListed(obj)
4785
    {
4786
        /* list the object if it's listed in the room part */
4787
        return obj.isListedInRoomPart(part_);
4788
    }
4789
4790
    /* the part I'm listing */
4791
    part_ = nil
4792
;
4793
4794
/*
4795
 *   contents lister for room parts, used in a long description 
4796
 */
4797
roomPartDescContentsLister: surfaceDescContentsLister
4798
    isListed(obj)
4799
    {
4800
        /* list the object if it's listed in the room part */
4801
        return obj.isListedInRoomPart(part_);
4802
    }
4803
4804
    part_ = nil
4805
;
4806
4807
/*
4808
 *   Look-in lister for room parts.  Most room parts act like surfaces
4809
 *   rather than containers, so base this lister on the surface lister.  
4810
 */
4811
roomPartLookInLister: surfaceLookInLister
4812
    isListed(obj)
4813
    {
4814
        /* list the object if it's listed in the room part */
4815
        return obj.isListedInRoomPart(part_);
4816
    }
4817
4818
    part_ = nil
4819
;
4820
                         
4821
/*
4822
 *   Base class for contents listers for an Underside.  
4823
 */
4824
class BaseUndersideContentsLister: BaseContentsLister
4825
;
4826
4827
/* basic contents lister for an Underside */
4828
undersideContentsLister: ContentsLister, BaseUndersideContentsLister
4829
;
4830
4831
/* contents lister for explicitly looking under an Underside */
4832
undersideLookUnderLister: LookWhereContentsLister, BaseUndersideContentsLister
4833
;
4834
4835
/* contents lister for moving an Underside and abandoning its contents */
4836
undersideAbandonContentsLister: undersideLookUnderLister
4837
    showListEmpty(pov, parent) { }
4838
    showListPrefixWide(itemCount, pov, parent)
4839
        { "Moving <<parent.theNameObj>> reveal<<tSel('s', 'ed')>> "; }
4840
    showListSuffixWide(itemCount, pov, parent)
4841
        { " underneath. "; }
4842
    showListPrefixTall(itemCount, pov, parent)
4843
        { "Moving <<parent.theNameObj>> reveal<<tSel('s', 'ed')>>:"; }
4844
;
4845
 
4846
/* contents lister for an Underside, used in a long description */
4847
undersideDescContentsLister: DescContentsLister, BaseUndersideContentsLister
4848
    showListPrefixWide(itemCount, pov, parent)
4849
    {
4850
        "Under <<parent.theNameObj>>
4851
        <<itemCount == 1 ? tSel('is', 'was')
4852
                         : tSel('are', 'were')>> ";
4853
    }
4854
;
4855
4856
/*
4857
 *   Base class for contents listers for an RearContainer or RearSurface 
4858
 */
4859
class BaseRearContentsLister: BaseContentsLister
4860
;
4861
4862
/* basic contents lister for a RearContainer or RearSurface */
4863
rearContentsLister: ContentsLister, BaseRearContentsLister
4864
;
4865
4866
/* contents lister for explicitly looking behind a RearContainer/Surface */
4867
rearLookBehindLister: LookWhereContentsLister, BaseRearContentsLister
4868
;
4869
 
4870
/* lister for moving a RearContainer/Surface and abandoning its contents */
4871
rearAbandonContentsLister: undersideLookUnderLister
4872
    showListEmpty(pov, parent) { }
4873
    showListPrefixWide(itemCount, pov, parent)
4874
        { "Moving <<parent.theNameObj>> reveal<<tSel('s', 'ed')>> "; }
4875
    showListSuffixWide(itemCount, pov, parent)
4876
        { " behind <<parent.itObj>>. "; }
4877
    showListPrefixTall(itemCount, pov, parent)
4878
        { "Moving <<parent.theNameObj>> reveal<<tSel('s', 'ed')>>:"; }
4879
;
4880
 
4881
/* long-description contents lister for a RearContainer/Surface */
4882
rearDescContentsLister: DescContentsLister, BaseRearContentsLister
4883
    showListPrefixWide(itemCount, pov, parent)
4884
    {
4885
        "Behind <<parent.theNameObj>>
4886
        <<itemCount == 1 ? tSel('is', 'was')
4887
                         : tSel('are', 'were')>> ";
4888
    }
4889
;
4890
4891
4892
/*
4893
 *   Base class for specialized in-line contents listers.  This shows the
4894
 *   list in the form "(<prep> which is...)", with the preposition obtained
4895
 *   from the container's objInPrep property.  
4896
 */
4897
class BaseInlineContentsLister: ContentsLister
4898
    showListEmpty(pov, parent) { }
4899
    showListPrefixWide(cnt, pov, parent)
4900
    {
4901
        " (<<parent.objInPrep>> which <<
4902
          cnt == 1 ? tSel('is', 'was') : tSel('are', 'were')>> ";
4903
    }
4904
    showListSuffixWide(itemCount, pov, parent)
4905
        { ")"; }
4906
;
4907
4908
/*
4909
 *   Contents lister for a generic in-line list entry.  We customize the
4910
 *   wording slightly here: rather than saying "(in which...)" as the base
4911
 *   class would, we use the slightly more readable "(which contains...)".
4912
 */
4913
inlineListingContentsLister: BaseInlineContentsLister
4914
    showListPrefixWide(cnt, pov, parent)
4915
        { " (which contain<<parent.verbEndingSEd>> "; }
4916
;
4917
4918
/* in-line contents lister for a surface */
4919
surfaceInlineContentsLister: BaseInlineContentsLister
4920
;
4921
4922
/* in-line contents lister for an Underside */
4923
undersideInlineContentsLister: BaseInlineContentsLister
4924
;
4925
4926
/* in-line contents lister for a RearContainer/Surface */
4927
rearInlineContentsLister: BaseInlineContentsLister
4928
;
4929
4930
/*
4931
 *   Contents lister for keyring list entry.  This is used to display a
4932
 *   keyring's contents in-line with the name of the keyring,
4933
 *   parenthetically. 
4934
 */
4935
keyringInlineContentsLister: inlineListingContentsLister
4936
    showListPrefixWide(cnt, pov, parent)
4937
        { " (with "; }
4938
    showListSuffixWide(cnt, pov, parent)
4939
        { " attached)"; }
4940
;
4941
4942
4943
/*
4944
 *   Contents lister for "examine <keyring>" 
4945
 */
4946
keyringExamineContentsLister: DescContentsLister
4947
    showListEmpty(pov, parent)
4948
    {
4949
        "\^<<parent.nameIs>> empty. ";
4950
    }
4951
    showListPrefixWide(cnt, pov, parent)
4952
    {
4953
        "Attached to <<parent.theNameObj>>
4954
        <<cnt == 1 ? tSel('is', 'was')
4955
                   : tSel('are', 'were')>> ";
4956
    }
4957
    showListSuffixWide(itemCount, pov, parent)
4958
    {
4959
        ". ";
4960
    }
4961
;
4962
4963
/*
4964
 *   Lister for actors aboard a traveler.  This is used to list the actors
4965
 *   on board a vehicle when the vehicle arrives or departs a location.  
4966
 */
4967
aboardVehicleLister: Lister
4968
    showListPrefixWide(itemCount, pov, parent)
4969
        { " (carrying "; }
4970
    showListSuffixWide(itemCount, pov, parent)
4971
        { ")"; }
4972
4973
    /* list anything whose isListedAboardVehicle returns true */
4974
    isListed(obj) { return obj.isListedAboardVehicle; }
4975
;
4976
4977
/*
4978
 *   A simple lister to show the objects to which a given Attachable
4979
 *   object is attached.  This shows the objects which have symmetrical
4980
 *   attachment relationships to the given parent object, or which are
4981
 *   "major" items to which the parent is attached.  
4982
 */
4983
class SimpleAttachmentLister: Lister
4984
    construct(parent) { parent_ = parent; }
4985
    
4986
    showListEmpty(pov, parent)
4987
        { /* say nothing when there are no attachments */ }
4988
    
4989
    showListPrefixWide(cnt, pov, parent)
4990
        { "<.p>\^<<parent.nameIs>> attached to "; }
4991
    showListSuffixWide(cnt, pov, parent)
4992
        { ". "; }
4993
4994
    /* ask the parent if we should list each item */
4995
    isListed(obj) { return parent_.isListedAsAttachedTo(obj); }
4996
4997
    /*
4998
     *   the parent object - this is the object whose attachments are being
4999
     *   listed 
5000
     */
5001
    parent_ = nil
5002
;
5003
5004
/*
5005
 *   The "major" attachment lister.  This lists the objects which are
5006
 *   attached to a given parent Attachable, and for which the parent is
5007
 *   the "major" item in the relationship.  The items in the list are
5008
 *   described as being attached to the parent.  
5009
 */
5010
class MajorAttachmentLister: SimpleAttachmentLister
5011
    showListPrefixWide(cnt, pov, parent) { "<.p>\^"; }
5012
    showListSuffixWide(cnt, pov, parent)
5013
    {
5014
        " <<cnt == 1 ? tSel('is', 'was')
5015
                     : tSel('are', 'were')>>
5016
        attached to <<parent.theNameObj>>. ";
5017
    }
5018
5019
    /* ask the parent if we should list each item */
5020
    isListed(obj) { return parent_.isListedAsMajorFor(obj); }
5021
;
5022
5023
/*
5024
 *   Finish Options lister.  This lister is used to offer the player
5025
 *   options in finishGame(). 
5026
 */
5027
finishOptionsLister: Lister
5028
    showListPrefixWide(cnt, pov, parent)
5029
    {
5030
        "<.p>Would you like to ";
5031
    }
5032
    showListSuffixWide(cnt, pov, parent)
5033
    {
5034
        /* end the question, add a blank line, and show the ">" prompt */
5035
        "?\b&gt;";
5036
    }
5037
    
5038
    isListed(obj) { return obj.isListed; }
5039
    listCardinality(obj) { return 1; }
5040
    
5041
    showListItem(obj, options, pov, infoTab)
5042
    {
5043
        /* obj is a FinishOption object; show its description */
5044
        obj.desc;
5045
    }
5046
    
5047
    showListSeparator(options, curItemNum, totalItems)
5048
    {
5049
        /*
5050
         *   for the last separator, show "or" rather than "and"; for
5051
         *   others, inherit the default handling 
5052
         */
5053
        if (curItemNum + 1 == totalItems)
5054
        {
5055
            if (totalItems == 2)
5056
                " or ";
5057
            else
5058
                ", or ";
5059
        }
5060
        else
5061
            inherited(options, curItemNum, totalItems);
5062
    }
5063
;
5064
5065
/*
5066
 *   Equivalent list state lister.  This shows a list of state names for a
5067
 *   set of otherwise indistinguishable items.  We show the state names in
5068
 *   parentheses, separated by commas only (i.e., no "and" separating the
5069
 *   last two items); we use this less verbose format so that we blend
5070
 *   into the larger enclosing list more naturally.
5071
 *   
5072
 *   The items to be listed are EquivalentStateInfo objects.  
5073
 */
5074
equivalentStateLister: Lister
5075
    showListPrefixWide(cnt, pov, parent) { " ("; }
5076
    showListSuffixWide(cnt, pov, parent) { ")"; }
5077
    isListed(obj) { return true; }
5078
    listCardinality(obj) { return 1; }
5079
    showListItem(obj, options, pov, infoTab)
5080
    {
5081
        "<<spellIntBelow(obj.getEquivCount(), 100)>> <<obj.getName()>>";
5082
    }
5083
    showListSeparator(options, curItemNum, totalItems)
5084
    {
5085
        if (curItemNum < totalItems)
5086
            ", ";
5087
    }
5088
;
5089
5090
/* in case the exits module isn't included in the build */
5091
property destName_, destIsBack_, others_, enableHyperlinks;
5092
5093
/*
5094
 *   Basic room exit lister.  This shows a list of the apparent exits from
5095
 *   a location.
5096
 *   
5097
 *   The items to be listed are DestInfo objects.  
5098
 */
5099
class ExitLister: Lister
5100
    showListPrefixWide(cnt, pov, parent)
5101
    {
5102
        if (cnt == 1)
5103
            "The only obvious exit {leads|led} ";
5104
        else
5105
            "Obvious exits {lead|led} ";
5106
    }
5107
    showListSuffixWide(cnt, pov, parent) { ". "; }
5108
5109
    isListed(obj) { return true; }
5110
    listCardinality(obj) { return 1; }
5111
5112
    showListItem(obj, options, pov, infoTab)
5113
    {
5114
        /*
5115
         *   Show the back-to-direction prefix, if we don't know the
5116
         *   destination name but this is the back-to direction: "back to
5117
         *   the north" and so on. 
5118
         */
5119
        if (obj.destIsBack_ && obj.destName_ == nil)
5120
            say(obj.dir_.backToPrefix + ' ');
5121
        
5122
        /* show the direction */
5123
        showListItemDirName(obj, nil);
5124
5125
        /* if the destination is known, show it as well */
5126
        if (obj.destName_ != nil)
5127
        {
5128
            /*
5129
             *   if we have a list of other directions going to the same
5130
             *   place, show it parenthetically 
5131
             */
5132
            otherExitLister.showListAll(obj.others_, 0, 0);
5133
            
5134
            /*
5135
             *   Show our destination name.  If we know the "back to"
5136
             *   destination name, show destination names in the format
5137
             *   "east, to the living room" so that they are consistent
5138
             *   with "west, back to the dining room".  Otherwise, just
5139
             *   show "east to the living room".  
5140
             */
5141
            if ((options & hasBackNameFlag) != 0)
5142
                ",";
5143
5144
            /* if this is the way back, say so */
5145
            if (obj.destIsBack_)
5146
                " back";
5147
5148
            /* show the destination */
5149
            " to <<obj.destName_>>";
5150
        }
5151
    }
5152
    showListSeparator(options, curItemNum, totalItems)
5153
    {
5154
        /*
5155
         *   if we have a "back to" name, use the "long" notation - this is
5156
         *   important because we'll use commas in the directions with
5157
         *   known destination names 
5158
         */
5159
        if ((options & hasBackNameFlag) != 0)
5160
            options |= ListLong;
5161
5162
        /*
5163
         *   for a two-item list, if either item has a destination name,
5164
         *   show a comma or semicolon (depending on 'long' vs 'short' list
5165
         *   mode) before the "and"; for anything else, use the default
5166
         *   handling 
5167
         */
5168
        if (curItemNum == 1
5169
            && totalItems == 2
5170
            && (options & hasDestNameFlag) != 0)
5171
        {
5172
            if ((options & ListLong) != 0)
5173
                "; and ";
5174
            else
5175
                ", and ";
5176
        }
5177
        else
5178
            inherited(options, curItemNum, totalItems);
5179
    }
5180
5181
    /* show a direction name, hyperlinking it if appropriate */
5182
    showListItemDirName(obj, initCap)
5183
    {
5184
        local dirname;
5185
        
5186
        /* get the name */
5187
        dirname = obj.dir_.name;
5188
5189
        /* capitalize the first letter, if desired */
5190
        if (initCap)
5191
            dirname = dirname.substr(1,1).toUpper() + dirname.substr(2);
5192
5193
        /* show the name with a hyperlink or not, as configured */
5194
        if (libGlobal.exitListerObj.enableHyperlinks)
5195
            say(aHref(dirname, dirname));
5196
        else
5197
            say(dirname);
5198
    }
5199
5200
    /* this lister shows destination names */
5201
    listerShowsDest = true
5202
5203
    /*
5204
     *   My special options flag: at least one object in the list has a
5205
     *   destination name.  The caller should set this flag in our options
5206
     *   if applicable. 
5207
     */
5208
    hasDestNameFlag = ListerCustomFlag(1)
5209
    hasBackNameFlag = ListerCustomFlag(2)
5210
    nextCustomFlag = ListerCustomFlag(3)
5211
;
5212
5213
/*
5214
 *   Show a list of other exits to a given destination.  We'll show the
5215
 *   list parenthetically, if there's a list to show.  The objects to be
5216
 *   listed are Direction objects.  
5217
 */
5218
otherExitLister: Lister
5219
    showListPrefixWide(cnt, pov, parent) { " (or "; }
5220
    showListSuffixWide(cnt, pov, parent) { ")"; }
5221
5222
    isListed(obj) { return true; }
5223
    listCardinality(obj) { return 1; }
5224
5225
    showListItem(obj, options, pov, infoTab)
5226
    {
5227
        if (libGlobal.exitListerObj.enableHyperlinks)
5228
            say(aHref(obj.name, obj.name));
5229
        else
5230
            say(obj.name);
5231
    }
5232
    showListSeparator(options, curItemNum, totalItems)
5233
    {
5234
        /*
5235
         *   simply show "or" for all items (these lists are usually
5236
         *   short, so omit any commas) 
5237
         */
5238
        if (curItemNum != totalItems)
5239
            " or ";
5240
    }
5241
;
5242
5243
/*
5244
 *   Show room exits as part of a room description, using the "verbose"
5245
 *   sentence-style notation.  
5246
 */
5247
lookAroundExitLister: ExitLister
5248
    showListPrefixWide(cnt, pov, parent)
5249
    {
5250
        /* add a paragraph break before the exit listing */
5251
        "<.roompara>";
5252
5253
        /* inherit default handling */
5254
        inherited(cnt, pov, parent);
5255
    }    
5256
;
5257
5258
/*
5259
 *   Show room exits as part of a room description, using the "terse"
5260
 *   notation. 
5261
 */
5262
lookAroundTerseExitLister: ExitLister
5263
    showListPrefixWide(cnt, pov, parent)
5264
    {
5265
        "<.roompara><.parser>Obvious exits: ";
5266
    }
5267
    showListItem(obj, options, pov, infoTab)
5268
    {
5269
        /* show the direction name */
5270
        showListItemDirName(obj, true);
5271
    }
5272
    showListSuffixWide(cnt, pov, parent)
5273
    {
5274
        "<./parser> ";
5275
    }
5276
    showListSeparator(options, curItemNum, totalItems)
5277
    {
5278
        /* just show a comma between items */
5279
        if (curItemNum != totalItems)
5280
            ", ";
5281
    }
5282
5283
    /* this lister does not show destination names */
5284
    listerShowsDest = nil
5285
;
5286
5287
/*
5288
 *   Show room exits in response to an explicit request (such as an EXITS
5289
 *   command).  
5290
 */
5291
explicitExitLister: ExitLister
5292
    showListEmpty(pov, parent)
5293
    {
5294
        "There {are|were} no obvious exits. ";
5295
    }
5296
;
5297
5298
/*
5299
 *   Show room exits in the status line (used in HTML mode only)
5300
 */
5301
statuslineExitLister: ExitLister
5302
    showListEmpty(pov, parent)
5303
    {
5304
        "<br><b>Exits:</b> <i>None</i><br>";
5305
    }
5306
    showListPrefixWide(cnt, pov, parent)
5307
    {
5308
        "<br><b>Exits:</b> ";
5309
    }
5310
    showListSuffixWide(cnt, pov, parent)
5311
    {
5312
        "<br>";
5313
    }
5314
    showListItem(obj, options, pov, infoTab)
5315
    {
5316
        "<a plain href='<<obj.dir_.name>>'><<obj.dir_.name>></a>";
5317
    }
5318
    showListSeparator(options, curItemNum, totalItems)
5319
    {
5320
        /* just show a space between items */
5321
        if (curItemNum != totalItems)
5322
            " &nbsp; ";
5323
    }
5324
5325
    /* this lister does not show destination names */
5326
    listerShowsDest = nil
5327
;
5328
5329
/*
5330
 *   Implied action announcement grouper.  This takes a list of
5331
 *   ImplicitActionAnnouncement reports and returns a single message string
5332
 *   describing the entire list of actions.  
5333
 */
5334
implicitAnnouncementGrouper: object
5335
    /*
5336
     *   Configuration option: keep all failures in a list of implied
5337
     *   announcements.  If this is true, then we'll write things like
5338
     *   "trying to unlock the door and then open it"; if nil, we'll
5339
     *   instead write simply "trying to unlock the door".
5340
     *   
5341
     *   By default, we keep only the first of a group of failures.  A
5342
     *   group of failures is always recursively related, so the first
5343
     *   announcement refers to the command that actually failed; the rest
5344
     *   of the announcements are for the enclosing actions that triggered
5345
     *   the first action.  All of the enclosing actions failed as well,
5346
     *   but only because the first action failed.
5347
     *   
5348
     *   Announcing all of the actions is too verbose for most tastes,
5349
     *   which is why we set the default here to nil.  The fact that the
5350
     *   first action in the group failed means that we necessarily won't
5351
     *   carry out any of the enclosing actions, so the enclosing
5352
     *   announcements don't tell us much.  All they really tell us is why
5353
     *   we're running the action that actually failed, but that's almost
5354
     *   always obvious, so suppressing them is usually fine.  
5355
     */
5356
    keepAllFailures = nil
5357
5358
    /* build the composite message */
5359
    compositeMessage(lst)
5360
    {
5361
        local txt;
5362
        local ctx = new ListImpCtx();
5363
5364
        /* add the text for each item in the list */
5365
        for (txt = '', local i = 1, local len = lst.length() ; i <= len ; ++i)
5366
        {
5367
            local curTxt;
5368
5369
            /* get this item */
5370
            local cur = lst[i];
5371
5372
            /* we're not in a 'try' or 'ask' sublist yet */
5373
            ctx.isInSublist = nil;
5374
5375
            /* set the underlying context according to this item */
5376
            ctx.setBaseCtx(cur);
5377
5378
            /*
5379
             *   Generate the announcement for this element.  Generate the
5380
             *   announcement from the message property for this item using
5381
             *   our running list context.  
5382
             */
5383
            curTxt = cur.getMessageText(
5384
                cur.getAction().getOriginalAction(), ctx);
5385
5386
            /*
5387
             *   If this one is an attempt only, and it's followed by one
5388
             *   or more other attempts, the attempts must all be
5389
             *   recursively related (in other words, the first attempt was
5390
             *   an implied action required by the second attempt, which
5391
             *   was required by the third, and so on).  They have to be
5392
             *   recursively related, because otherwise we wouldn't have
5393
             *   kept trying things after the first failed attempt.
5394
             *   
5395
             *   To make the series of failed attempts sound more natural,
5396
             *   group them into a single "trying to", and keep only the
5397
             *   first failure: rather than "trying to unlock the door,
5398
             *   then trying to open the door", write "trying to unlock the
5399
             *   door and then open it".
5400
             *   
5401
             *   An optional configuration setting makes us keep only the
5402
             *   first failed operation, so we'd instead write simply
5403
             *   "trying to unlock the door".
5404
             *   
5405
             *   Do the same grouping for attempts interrupted for an
5406
             *   interactive question.  
5407
             */
5408
            while ((cur.justTrying && i < len && lst[i+1].justTrying)
5409
                   || (cur.justAsking && i < len && lst[i+1].justAsking))
5410
            {
5411
                local addTxt;
5412
                
5413
                /*
5414
                 *   move on to the next item - we're processing it here,
5415
                 *   so we don't need to handle it again in the main loop 
5416
                 */
5417
                ++i;
5418
                cur = lst[i];
5419
5420
                /* remember that we're in a try/ask sublist */
5421
                ctx.isInSublist = true;
5422
5423
                /* add the list entry for this action, if desired */
5424
                if (keepAllFailures)
5425
                {
5426
                    /* get the added text */
5427
                    addTxt = cur.getMessageText(
5428
                        cur.getAction().getOriginalAction(), ctx);
5429
5430
                    /*
5431
                     *   if both the text so far and the added text are
5432
                     *   non-empty, string them together with 'and then';
5433
                     *   if one or the other is empty, use the non-nil one 
5434
                     */
5435
                    if (addTxt != '' && curTxt != '')
5436
                        curTxt += ' and then ' + addTxt;
5437
                    else if (addTxt != '')
5438
                        curTxt = addTxt;
5439
                }
5440
            }
5441
5442
            /* add a separator before this item if it isn't the first */
5443
            if (txt != '' && curTxt != '')
5444
                txt += ', then ';
5445
5446
            /* add the current item's text */
5447
            txt += curTxt;
5448
        }
5449
5450
        /* if we ended up with no text, the announcement is silent */
5451
        if (txt == '')
5452
            return '';
5453
5454
        /* wrap the whole list in the usual full standard phrasing */
5455
        return standardImpCtx.buildImplicitAnnouncement(txt);
5456
    }
5457
;
5458
5459
/*
5460
 *   Suggested topic lister. 
5461
 */
5462
class SuggestedTopicLister: Lister
5463
    construct(asker, askee, explicit)
5464
    {
5465
        /* remember the actors */
5466
        askingActor = asker;
5467
        targetActor = askee;
5468
5469
        /* remember whether this is explicit or implicit */
5470
        isExplicit = explicit;
5471
5472
        /* cache the actor's scope list */
5473
        scopeList = asker.scopeList();
5474
    }
5475
    
5476
    showListPrefixWide(cnt, pov, parent)
5477
    {
5478
        /* add the asking and target actors as global message parameters */
5479
        gMessageParams(askingActor, targetActor);
5480
5481
        /* show the prefix; include a paren if not in explicit mode */
5482
        "<<isExplicit ? '' : '('>>{You askingActor/he} could ";
5483
    }
5484
    showListSuffixWide(cnt, pov, parent)
5485
    {
5486
        /* end the sentence; include a paren if not in explicit mode */
5487
        ".<<isExplicit? '' : ')'>> ";
5488
    }
5489
    showListEmpty(pov, parent)
5490
    {
5491
        /*
5492
         *   say that the list is empty if it was explicitly requested;
5493
         *   say nothing if the list is being added by the library 
5494
         */
5495
        if (isExplicit)
5496
        {
5497
            gMessageParams(askingActor, targetActor);
5498
            "<<isExplicit ? '' : '('>>{You askingActor/he} {have} nothing
5499
            specific in mind right now to discuss with
5500
            {the targetActor/him}.<<isExplicit ? '' : ')'>> ";
5501
        }
5502
    }
5503
5504
    showListSeparator(options, curItemNum, totalItems)
5505
    {
5506
        /* use "or" as the conjunction */
5507
        if (curItemNum + 1 == totalItems)
5508
            ", or ";
5509
        else
5510
            inherited(options, curItemNum, totalItems);
5511
    }
5512
5513
    /* list suggestions that are currently active */
5514
    isListed(obj) { return obj.isSuggestionActive(askingActor, scopeList); }
5515
5516
    /* each item counts as one item grammatically */
5517
    listCardinality(obj) { return 1; }
5518
5519
    /* suggestions have no contents */
5520
    contentsListed(obj) { return nil; }
5521
5522
    /* get the list group */
5523
    listWith(obj) { return obj.suggestionGroup; }
5524
5525
    /* mark as seen - nothing to do for suggestions */
5526
    markAsSeen(obj, pov) { }
5527
5528
    /* show the item - show the suggestion's theName */
5529
    showListItem(obj, options, pov, infoTab)
5530
    {
5531
        /* note that we're showing the suggestion */
5532
        obj.noteSuggestion();
5533
5534
        /* show the name */
5535
        say(obj.fullName);
5536
    }
5537
5538
    /* don't use semicolons, even in long lists */
5539
    longListSepTwo { listSepTwo; }
5540
    longListSepMiddle { listSepMiddle; }
5541
    longListSepEnd { listSepEnd; }
5542
5543
    /* flag: this is an explicit listing (i.e., a TOPICS command) */
5544
    isExplicit = nil
5545
5546
    /* the actor who's asking for the topic list (usually the PC) */
5547
    askingActor = nil
5548
5549
    /* the actor we're talking to */
5550
    targetActor = nil
5551
5552
    /* our cached scope list for the actor */
5553
    scopeList = nil
5554
;
5555
5556
/* ASK/TELL suggestion list group base class */
5557
class SuggestionListGroup: ListGroupPrefixSuffix
5558
    showGroupItem(sublister, obj, options, pov, infoTab)
5559
    {
5560
        /*
5561
         *   show the short name of the item - the group prefix will have
5562
         *   shown the appropriate long name 
5563
         */
5564
        say(obj.name);
5565
    }
5566
;
5567
5568
/* ASK ABOUT suggestion list group */
5569
suggestionAskGroup: SuggestionListGroup
5570
    groupPrefix = "ask {it targetActor/him} about "
5571
;
5572
5573
/* TELL ABOUT suggestion list group */
5574
suggestionTellGroup: SuggestionListGroup
5575
    groupPrefix = "tell {it targetActor/him} about "
5576
;
5577
5578
/* ASK FOR suggestion list group */
5579
suggestionAskForGroup: SuggestionListGroup
5580
    groupPrefix = "ask {it targetActor/him} for "
5581
;
5582
5583
/* GIVE TO suggestions list group */
5584
suggestionGiveGroup: SuggestionListGroup
5585
    groupPrefix = "give {it targetActor/him} "
5586
;
5587
5588
/* SHOW TO suggestions */
5589
suggestionShowGroup: SuggestionListGroup
5590
    groupPrefix = "show {it targetActor/him} "
5591
;
5592
5593
/* YES/NO suggestion group */
5594
suggestionYesNoGroup: SuggestionListGroup
5595
    showGroupList(pov, lister, lst, options, indent, infoTab)
5596
    {
5597
        /*
5598
         *   if we have one each of YES and NO responses, make the entire
5599
         *   list "say yes or no"; otherwise, use the default behavior 
5600
         */
5601
        if (lst.length() == 2
5602
            && lst.indexWhich({x: x.ofKind(SuggestedYesTopic)}) != nil
5603
            && lst.indexWhich({x: x.ofKind(SuggestedNoTopic)}) != nil)
5604
        {
5605
            /* we have a [yes, no] group - use the simple message */
5606
            "say yes or no";
5607
        }
5608
        else
5609
        {
5610
            /* inherit the default behavior */
5611
            inherited(pov, lister, lst, options, indent, infoTab);
5612
        }
5613
    }
5614
    groupPrefix = "say";
5615
;