summaryrefslogtreecommitdiffstats
path: root/crawl-ref/docs/monster_speech.txt
blob: 35ed996a2acfc75e54642641dbe31acf4cdd9c50 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
Overview
========

As of Dungeon Crawl Stone Soup 0.3 the previously hard-coded monster
speech has been outsourced by Matthew Cline. This makes changing 
existing messages, or adding new ones really easy. This file will
hopefully help you in this endeavour.


shout.txt handles message output for monsters noticing you.

monspeak.txt handles messages for monsters communicating with you.

wpnnoise.txt handles randart weapons with the noises property.

insult.txt handles insults thrown at you by imps and demons. 


Monster speech probabilities
============================

Not all monsters are equally likely to speak. Rather there are
different chances involved depending on several attributes, and most of
the time the database lookup stage isn't even reached.

The player will only ever hear monsters speak if they are nearby, and
monsters will only speak if they are not asleep, not submerged in
water, air or lava, and not wandering around aimlessly (unless neutral).

Berserk monsters are too busy killing and maiming to speak. Also, invisible
monsters the player can't see (for lack of see invisible) will always stay
silent, unless confused.

Monsters capable of speech (i.e. all intelligent humanoid monsters, as
well as all uniques and some non-unique demons) have a base chance of
1/21 of speaking, while humanoid monsters incapable of speech will
never communicate with the player in any form.

Non-humanoid monsters get a 1/84 probability of "speaking" per turn
(non-verbal actions, more like). This chance is divided by another 10,
if the monster in question was generated as a member of a group.
Chances are again doubled if this non-humanoid monster is fleeing, and
doubled again if confused.

Neutral monsters only speak half as often, and for charmed monsters the
probability is divided by 3. The same applies to silenced monsters, i.e.
monsters that are not naturally silent will only get to even attempt to speak in
one out of three tries where the above chances hold.

Note that the definition of which monsters are capable of speech is
entirely hardcoded. We think we made this apply to all sensible
monsters, i.e. all intelligent humanoid monsters, but of course it is
possible we've overlooked something, so if you find that your
carefully constructed monster speech never gets printed, and this
documentation also doesn't help you solve the problem, you might want
to post a bug report on Dungeon Crawl's SourceForge site [1].


A simple example
================

If you have a look at some of the speech files, you'll see that all
entries have basically the same structure: a key, followed by one or
more values.
Here is an example.

  %%%%
  # Friendly imps are very common so they speak very rarely
  friendly '5'

  w:1
  @The_monster@ laughs.

  w:1
  @_friendly_imp_@

  __NONE
  %%%%

Let's look at this entry's components in more detail.

  %%%%

Four percentage signs mark beginning and end of a database entry. If
you forget to place these, you will get buggy monster speech.

  # Friendly imps are very common so they speak very rarely

A '#' sign at the beginning of a line causes it to be ignored; these
are comment lines.

  friendly '5'

The first non-comment, non-blank line is interpreted as the key of an
entry. Most keys are hardcoded but there's place for user defined ones
as well. More on that later, though. 
In this case, the key is "friendly '5'".

'5' refers to the monster glyph, so the speech will not be entirely
restricted to imps, though they are by far the most common type of
minor demons.

  w:1
  @The_monster@ laughs.

The rest of the entry consists of messages, separated by blank
lines. This is one of them. Each may be prefixed with an optional
weight ("w:1"). A message will be chosen with a probability of its
weight out of the sum of weights for its entry. Weight defaults to 10
if not specified. In this example, this particular message will be
selected 1 time out of 12.

  @The_monster@ laughs.

This is the message that will be printed. The '@' markers indicate
variables that will be substituted before printing. This particular
variable "@The_monster@" is treated specially by the game; the
substitution will change based on the monster giving the speech. See
below for more details.

  w:1
  @_friendly_imp_@

This is another case of a substitution. Here, "_friendly_imp_" is an
entry in speak.txt. A random line from that entry will be substituted.

  __NONE

This is a special command; it prints no message. See below for more
details on special commands.


Keys in detail
==============

Key lookup is always case-insensitive. The game will make many
different attempts when trying to find monster speech, all of which
are explained in detail below. You'll find some examples at the end of
this section.

First, a monster may have one or more of a list of attributes that
might influence its speech. We will henceforth refer to these
attributes as prefixes.

"friendly" is one of a couple of allowed prefixes, distinguishing the
speech from "hostile" or "neutral". All prefixes are optional and
tested in the following order:

  default <attitude> fleeing silenced confused [related] <player god> 

where <attitude> can be any of friendly, neutral or hostile. Note that
the game generally treats neutral monsters like hostiles since they
still pose a danger to players.

The prefix "related" is added if the player and the monster share the
same genus, e.g. if you're playing a Sludge Elf, and the monster in
question is a deep elf blademaster, you both are Elves and the monster
speech may reflect that. It's currently only used for friendly
humanoids who will now sometimes mention that you're family, if you
are.

The <player god> prefix is constructed according to the religious
belief of the character. If the monster in question is a member of the
orc species and the character worships Beogh, the prefix "beogh" gets
added to the list. If you worship one of the good gods (Zin, Elyvilon,
or The Shining One) the prefix "good god" is used instead.
Conversely, worshippers of one of the evil gods (Yredelemnul, Makhleb,
Kikubaaqudgha, Lugonu, Xom, Beogh, or Vehumet) will use the prefix
"evil god". 
This allows fine-grained handling of monsters depending on your
character's religion status, e.g. orcs will use special speech for
Beogh worshippers, and neutral holy beings (Angel and Daeva) may
shout messages of encouragement to followers of the good gods, while
demons will attempt to slander the good gods.

Once the entire set of prefixes has been determined, we only need
to add the monster name and start the database search. 

First we search for the complete prefix string in combination with the
monster name. Then we try omitting some very specific prefixes that
might not be so important, first skipping on "hostile", then also
ignoring "related", then religion status, and finally "silenced", where
applicable.

If all of that didn't yield any results, next we'll take the complete
prefix list again, then, reading from left to right, combinations are
tested, beginning at three prefixes and ending at none. At this stage
the list of prefixes is always prepended with "default". This ensures
that, for example, fleeing uniques won't output their normal menacing
speech but rather the default speech defined for fleeing humanoids in
general.
In practice this means that database keys starting with "default" are
the fallback solution if the exact look-up has failed. As such, the
messages should be generic enough to allow for all the possibly skipped
prefixes, or else those cases should be caught earlier, e.g. if you
have "default friendly humanoid", you should also define "default
friendly fleeing humanoid" and "default friendly confused humanoid"
(and possibly both combined) even if only with "__NONE" (stay silent),
as the general friendly messages may look odd for a monster such
afflicted.

Only keys that match a search string perfectly (ignoring case) will
be used. Once all prefixes have been exhausted and still no match has 
been found, the database lookup will try for a more general monster
description. There are several possible ways this is attempted, in the
following order:

1. The actual monster name.
   Examples: "crystal golem", "default confused moth of wrath"
2. The monster genus.
   Examples: If "friendly ogre-mage" wasn't found, try "friendly ogre"
             instead. Same for "dragon" if "swamp drake" was
             unsuccessful.
3. Then the monster glyph, with prefix "cap-" for capital letters.
   Examples: "default 'cap-J'", "default confused 'k'"
4. A group description (such as 'insect' or 'humanoid') defined by the
   monster's body shape (winged, tailed etc). The definition of the 
   latter is entirely hardcoded, though.
   Examples: "default winged insect", "default confused humanoid"

For the last round (shape comparison, e.g. winged humanoid)
occasionally an additional intelligence estimate ("stupid", "smart")
is prefixed to the search string, depending on the monster type, e.g. 
a "stupid humanoid" may still be smarter than a "smart arachnid".

Here's a list of allowed monster shapes that should hopefully be 
self-explanatory:
  humanoid, winged humanoid (angels), tailed humanoid (draconians),
  winged tailed humanoid (gargoyles), centaur, naga, quadruped,
  tailless quadruped (frogs), winged quadruped (hippogriff), bat,
  snake (also eels and worms), fish, insect, winged insect, arachnid,
  centipede, snail, plant, fungus, orb (eyes), and blob (jellies).


If no matching keys are found after all of these rounds, the monster
definitely stays silent.


Examples
--------

Example 1: 
  The monster we want to make "speak" is a "confused killer bee".

  However, such an entry cannot be found in the database, so the game  
  tries first for "default confused killer bee", then "default killer
  bee", neither of which yields any results. 
  The monster genus is also plain "killer bee", so that doesn't help
  us any. For the next round we try again with "confused 'k'", which,
  by itself, also can't be found in the database, but once the prefix
  comparison tries it together with "default", we have a match:

%%%%
default confused 'k'

SOUND:@The_monster@ buzzes around in tight circles.
%%%%

Example 2:
  This time, we're interested in "friendly fleeing beogh orc wizard".

  This obviously made up example also has no direct equivalent in the
  database, so first we try to remove the less important prefixes,
  something that in this case only applies to "beogh". Unfortunately,
  "friendly fleeing orc wizard" also has no corresponding entry in the
  database, so that, one after another, we now check for "default
  friendly fleeing beogh orc wizard", "default friendly fleeing orc
  wizard", "default friendly beogh orc wizard", "default fleeing beogh
  orc wizard", "default friendly orc wizard", "default fleeing orc
  wizard", "default beogh orc wizard" and "default orc wizard", none of
  which is successful.
  The genus of orc wizards is "orc", so we retry the above using "orc"
  instead of "orc wizard". The same is repeated for "friendly fleeing
  beogh 'o'", and we still haven't found anything.

  This is starting to get ridiculous, so it's time for desperate
  measures: 
  With the help of some rather complicated functions the game works out
  that orcs can be described as humanoids of average intelligence.
  Thus, in a final attempt of making this orc wizard speak, we search
  the database for "friendly fleeing beogh humanoid", something that,
  not surprisingly (since Beogh and humanoid don't go well together)
  doesn't exist. Annoyingly enough, neither does "friendly fleeing 
  humanoid". 
  Still, we haven't yet tried the prefix combinations: "default
  friendly fleeing beogh humanoid" is still unsuccessful, but with
  "default friendly fleeing humanoid" we finally strike gold:

%%%%
default friendly fleeing humanoid

w:30
VISUAL:@The_monster@ tries to hide somewhere.

@The_monster@ @shouts@, "WAIT FOR ME, @player_name@!  Could you help me?"

...

  We'll leave it at that, even though the database code still has work
  to do, namely add up the weights of all the entries (and there are
  several more), and randomly choose one of them.


Weapon speech
-------------

For obvious reasons, weapon noises get by without any such prefixes,
and the only hardcoded keywords are "noisy weapon" for weapons with
the noises property, and "singing sword" for (who'd have guessed?) the
Singing Sword.


Values in detail
================

Spacing
-------

There have to be blank lines between the different messages. If
messages are placed directly one after another they will be printed as
a block. This can be useful, e.g. for outputting first a "spell" and
then its (fake) result.

Note that this does not work for weapon noises. Here only the first
part of a paragraph before a carriage return is parsed.

The message entries themselves can be longer than a line, though Crawl
will simply truncate it should it exceed the screen width (assuming 80
columns or less). The actual message length will usually differ from
the one defining an entry as parameters can be stripped from the entry
or replaced by other values, as explained in the following section.

Variables
---------

Values can contain variable references, which look like text
surrounded by @@. These variables may be defined by entries in
shout.txt for the shouting database, or monspeak.txt or one of the
other files for the speech database, in which case they are replaced
with a random value from the entry; or they may have hardcoded
expansions defined by the game.

Note that variable replacement is recursive, so be careful to avoid
infinite loops. Though the game will abort after a number of
replacement attempts, it will still look ugly in the monster speech.

The following variables are hardcoded:

@monster@       : Plain monster name, e.g. "rat" or "Sigmund"
@a_monster@     : Indefinite article plus monster name,
                  or only the name if it is unique ("Sigmund").
@the_monster@   : Definite article plus monster name ("the rat"),
                  or a possessive if it is friendly ("your rat"),
                  or only the name if it is unique ("Sigmund").
@something@     : Like @monster@, with monster name replaced by
                  "something" if the monster is invisible and the
                  player cannot see invisible.
@a_something@   : similar
@the_something@ : similar
@player_name@   : Player name.
@player_species@: Player base species, with Draconian rather than the 
                  actual subtype.
@player_genus@  : Player genus, i.e. "Elf" rather than the exact type,
                  or "Ogre" instead of "Ogre-Mage".
@player_genus_plural@ : pluralised genus form.
@player_god@    : Player's god name, or "you" if non-religious.
@Player_god@    : Player's god name, or "You" if non-religious.
@god_is@        : replaced with "<god name> is" or "you are", if 
                  non-religious.
@God_is@        : replaced with "<god name> is" or "You are", if 
                  non-religious.
@surface@       : Whatever the monster is standing on.
@feature@       : The monster's square's feature description.
@pronoun@       : it, she, he, as appropriate
@possessive@    : its, her, his, as appropriate
@imp_taunt@     : imp type insults (see insult.txt)
@demon_taunt@   : demon type insults (see insult.txt)
@says@          : synonym of "say" that fits monsters' (hardcoded)
                  speech pattern and noise level.

Capitalized forms (@Monster@, @A_something@, @Possessive@, @Pronoun@)
are expanded with capitalized text.

Weapon noises are handled differently in that all of the above
replacements don't hold. Instead you can use @The_weapon@,
@the_weapon@, @Your_weapon@, @your_weapon@ and @weapon@ which will get
replaced by "The (weapon name)", "the (weapon name)", "Your (weapon
name)", "your (weapon name)", and the plain weapon name,
respectively. Note that the Singing Sword, being unique, cannot be
referred to by the possessive variants, so they will be replaced with
the appropriate definite article ones.

Examples of pre-defined variables in the database include
_high_priest_, _mercenary_guard_, _wizard_, _hostile_adventurer_,
_friendly_imp_, _hostile_imp_, and _tormentor_, but more get added all
the time. There are also a few synonyms defined at the beginning of
monspeak.txt such as for @ATTACK@, @pointless@, @shouts@, @wails@, and
others.

Weapon noises also use a number of synonyms which are defined at the
end of wpnnoise.txt.

The best way to learn about how variables and other concepts can be
used is probably to see how it has been done for existing messages.

Channels
--------

An optional channel name at the beginning of a string causes messages
to be sent to that channel. For example:

  SPELL:@The_monster@ casts a spell.
  WARN:Your equipment suddenly seems to weigh more.

Spacing after the channel parameter won't get stripped, so it's a good
idea to double check that the speech message directly follows the
colon.

Here are the defined channels:

  TALK    :  MSGCH_TALK (Default value.)
  DANGER  :  MSGCH_DANGER
  ENCHANT :  MSGCH_MONSTER_ENCHANT
  PLAIN   :  MSGCH_PLAIN
  SOUND   :  MSGCH_SOUND
  SPELL   :  MSGCH_MONSTER_SPELL
  VISUAL  :  MSGCH_TALK_VISUAL
  WARN    :  MSGCH_WARN

The channels have been assigned different colours and are sometimes
treated differently, e.g. any of MSGCH_TALK, MSGCH_SOUND and
MSGCH_TALK_VISUAL will never interrupt resting or travel unless
specifically added in the options file.

Note that MSGCH_SOUND and MSGCH_TALK get filtered out when you are
silenced. For similar reasons monster speech of channel SPELL is muted
under silence, along with ENCHANT and WARN, both of which currently
only occur in combination with SPELL. To allow for silent spells along
with fake warnings and enchantments, you can combine these with VISUAL
and enforce output even when silenced.

  VISUAL ENCHANT : MSGCH_MONSTER_ENCHANT
  VISUAL SPELL   : MSGCH_MONSTER_SPELL
  VISUAL WARN    : MSGCH_WARN

Note, though, that these only will take effect if a VISUAL message just
happens to be chosen. As stated above, the database search doesn't
really care whether a monster is supposed to be silent, so it may pick
any noisy monster speech, but the message output will care and refuse
to print such nonsense, so that in this case the monster will actually
stay silent after all. 
All in all, chances of silent "speech" are lower (as is intended) but
only VISUAL messages even have a chance to be printed under these circumstances.

As explained earlier, "silenced" is one of the prefixes that are
regarded as "less important" and can be ignored in the exact string
search. So that both specially defined silenced messages for a
particular monster and its normal VISUAL messages can sometimes take
effect, chances for actually skipping on silenced in the direct string
matching are 50:50.

Example 3:
  The player has just cast Silence when a Killer Klown wanders into
  view. (Uh oh!) This "silenced Killer Klown" is now attempting to say
  something. The exact look-up is unsuccessful, but now there's a 50%
  chance of skipping on the "silenced" prefix. If this route is chosen
  we may get results such as

%%%%
Killer Klown

@The_monster@ giggles crazily.

@The_monster@ laughs merrily.

...

  none of which, if chosen, would actually be printed, but luckily the 
  "Killer Klown" entry also contains VISUAL statements like the
  following:

...

VISUAL:@The_monster@ beckons to you.

VISUAL:@The_monster@ does a flip.

...

  If one of these is chosen, we get a non-verbal "speech" statement of
  this silenced monster.

  However, what happens if the other 50% take effect and we will *not*   
  ignore the "silenced" prefix? In this case, we'll simply continue
  like in the earlier examples above, get no results for either of
  "default silenced Killer Klown" or "default Killer Klown", and try
  the genus next: human, which cannot be found in the database,
  silenced or no. Neither will we find anything for the monster glyph
  '@'. Now all that remains is to check the monster shape, which is
  "humanoid" again. "silenced humanoid" won't get us any results, nor
  will simply "humanoid", but "default silenced humanoid" has some
  statements defined.

%%%%
default silenced humanoid

w:30
VISUAL:@The_monster@ says something but you don't hear anything.

w:30
VISUAL:@The_monster@ gestures.

...

  All of the statements in these predefined "silenced" entries have to
  be of the type VISUAL; otherwise they'll never get printed.


For shouts the default is also MSGCH_TALK which is automatically
changed to MSGCH_TALK_VISUAL for monsters that can't speak (animals,
usually), and manually set to MSGCH_SOUND for all those variants of
"You hear a shout!"

For weapon noises only a subset of the above is relevant, as anything
including VISUAL and the channel keys SPELL and ENCHANT are considered
invalid and will trigger a default message instead. Again, the default
channel is MSGCH_TALK.

Special commands and variables
------------------------------

Message entries may also be one of several special commands. These
aren't variables, so they aren't surrounded by @@. Accordingly, they
are not expanded, but rather they produce special game behaviour.

  __NONE : no message
  __NEXT : try a more general monster description
  __MORE : enforce a "--more--" prompt
  __YOU_RESIST : print "You resist."
  __NOTHING_HAPPENS : print "Nothing appears to happen."

Some special keys are defined in monspeak.txt and shout.txt, such as
__RESIST_OR_NOTHING and __SHOUT. These are normal variable expansions,
and may be used as such. They are given special-looking names because
Crawl looks up the noises a given monster can produce and looks for
keys that match the string, i.e. __SHOUT, __BARK and so on.


Testing your changes
====================

Get a version of Stone Soup that contains WIZARD mode. You can check
whether this is the case by pressing '&' during the game. If you are
told that this is an "unknown command" (likely, since WIZARD builds
are generally not distributed), you will have to compile the game for
yourself.

To build Crawl yourself, download the source code from the Crawl
homepage [1] and read the "INSTALL" file in the main directory for
instructions. Should you still have any questions after reading the
documentation and checking the archives of the Crawl newsgroup [2],
ask away!

If you have WIZARD mode compiled in, you can simply answer "yes" to
the safety question resulting from pressing '&', and then test to your
heart's content. Pressing '&' followed by a number of other keys will
execute wizard mode commands that are all listed in the wizard help
menu (press '&?').

In particular, you can create a monster with '&M', and enforce
behaviour on a monster by examining it (with 'x', as usual). In wizard
mode, examining monsters offers several new sub-commands such as 'F'
(make monster friendly/neutral/hostile) and 's' (make monster shout).
These last two are of particular interest to monster speech designers.

The Singing Sword and all other hardcoded artefacts can be created
with '&|'. The Elemental Staff and the spear of Voo-Doo are examples
of noisy weapons.

You can also temporarily increase the likelihood of a given message by
adding a high weight value before it, e.g. w:5000, or equally
temporarily push it into another channel (e.g. MSGCH_WARN) to make it
more noticeable.

If you successfully got Crawl compiled, you can easily enable more 
detailed debug information. All you need to do is add 

  #define DEBUG_MONSPEAK

somewhere in AppHdr.h, for example at the beginning of the section
entitled "Debugging Defines", and then compile the game anew, first
using "make clean", then "make wizard". 
If you play with DEBUG_MONSPEAK compiled in, whenever the game is 
searching the monspeak database you'll get extensive information on all
keys and prefixes tried. Once you're done testing don't forget to 
remove (or comment out) the DEBUG_MONSPEAK setting as trying to
actually play that way would sure be annoying. 


Publishing your changes
=======================

If you feel that your additions really add something to the game and
would like to make them available to the general public, you can post
them (in the form of a diff file, or in plain text) as a feature
request on sourceforge.net [1] or in the newsgroup [2].


.. [1] http://crawl-ref.sourceforge.net
   http://sourceforge.net/projects/crawl-ref

.. [2] rec.games.roguelike.misc
   Since this newsgroup is being shared with a number of other 
   roguelike games, it is generally considered polite to flag 
   subjects of posts pertaining only to Crawl with "-crawl-" or 
   a similar marker.