1 /* SCCS Id: @(#)role.c 3.3 2000/05/21 */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985-1999. */
3 /* NetHack may be freely redistributed. See license for details. */
4
5 #include "hack.h"
6
7
8 /*** Table of all roles ***/
9 /* According to AD&D, HD for some classes (ex. Wizard) should be smaller
10 * (4-sided for wizards). But this is not AD&D, and using the AD&D
11 * rule here produces an unplayable character. Thus I have used a minimum
12 * of an 10-sided hit die for everything. Another AD&D change: wizards get
13 * a minimum strength of 4 since without one you can't teleport or cast
14 * spells. --KAA
15 *
16 * As the wizard has been updated (wizard patch 5 jun '96) their HD can be
17 * brought closer into line with AD&D. This forces wizards to use magic more
18 * and distance themselves from their attackers. --LSZ
19 *
20 * With the introduction of races, some hit points and energy
21 * has been reallocated for each race. The values assigned
22 * to the roles has been reduced by the amount allocated to
23 * humans. --KMH
24 *
25 * God names use a leading underscore to flag goddesses.
26 */
27 const struct Role roles[] = {
28 { {"Archeologist", 0}, {
29 {"Digger", 0},
30 {"Field Worker",0},
31 {"Investigator",0},
32 {"Exhumer", 0},
33 {"Excavator", 0},
34 {"Spelunker", 0},
35 {"Speleologist",0},
36 {"Collector", 0},
37 {"Curator", 0} },
38 "Quetzalcoatl", "Camaxtli", "Huhetotl", /* Central American */
39 "Arc", "the College of Archeology", "the Tomb of the Toltec Kings",
40 PM_ARCHEOLOGIST, NON_PM, NON_PM,
41 PM_LORD_CARNARVON, PM_STUDENT, PM_MINION_OF_HUHETOTL,
42 NON_PM, PM_HUMAN_MUMMY, S_SNAKE, S_MUMMY,
43 ART_ORB_OF_DETECTION,
44 MH_HUMAN|MH_DWARF|MH_GNOME | ROLE_MALE|ROLE_FEMALE |
45 ROLE_LAWFUL|ROLE_NEUTRAL,
46 /* Str Int Wis Dex Con Cha */
47 { 7, 10, 10, 7, 7, 7 },
48 { 20, 20, 20, 10, 20, 10 },
49 /* Init Lower Higher */
50 { 11, 0, 0, 8, 1, 0 }, /* Hit points */
51 { 1, 0, 0, 1, 0, 1 },14, /* Energy */
52 10, 5, 0, 2, 10, A_INT, SPE_MAGIC_MAPPING, -4
53 },
54 { {"Barbarian", 0}, {
55 {"Plunderer", "Plunderess"},
56 {"Pillager", 0},
57 {"Bandit", 0},
58 {"Brigand", 0},
59 {"Raider", 0},
60 {"Reaver", 0},
61 {"Slayer", 0},
62 {"Chieftain", "Chieftainess"},
63 {"Conqueror", "Conqueress"} },
64 "Mitra", "Crom", "Set", /* Hyborian */
65 "Bar", "the Camp of the Duali Tribe", "the Duali Oasis",
66 PM_BARBARIAN, NON_PM, NON_PM,
67 PM_PELIAS, PM_CHIEFTAIN, PM_THOTH_AMON,
68 PM_OGRE, PM_TROLL, S_OGRE, S_TROLL,
69 ART_HEART_OF_AHRIMAN,
70 MH_HUMAN|MH_ORC | ROLE_MALE|ROLE_FEMALE |
71 ROLE_NEUTRAL|ROLE_CHAOTIC,
72 /* Str Int Wis Dex Con Cha */
73 { 16, 7, 7, 15, 16, 6 },
74 { 30, 6, 7, 20, 30, 7 },
75 /* Init Lower Higher */
76 { 14, 0, 0,10, 2, 0 }, /* Hit points */
77 { 1, 0, 0, 1, 0, 1 },10, /* Energy */
78 10, 14, 0, 0, 8, A_INT, SPE_HASTE_SELF, -4
79 },
80 { {"Caveman", "Cavewoman"}, {
81 {"Troglodyte", 0},
82 {"Aborigine", 0},
83 {"Wanderer", 0},
84 {"Vagrant", 0},
85 {"Wayfarer", 0},
86 {"Roamer", 0},
87 {"Nomad", 0},
88 {"Rover", 0},
89 {"Pioneer", 0} },
90 "Anu", "_Ishtar", "Anshar", /* Babylonian */
91 "Cav", "the Caves of the Ancestors", "the Dragon's Lair",
92 PM_CAVEMAN, PM_CAVEWOMAN, PM_LITTLE_DOG,
93 PM_SHAMAN_KARNOV, PM_NEANDERTHAL, PM_CHROMATIC_DRAGON,
94 PM_BUGBEAR, PM_HILL_GIANT, S_HUMANOID, S_GIANT,
95 ART_SCEPTRE_OF_MIGHT,
96 MH_HUMAN|MH_DWARF|MH_GNOME | ROLE_MALE|ROLE_FEMALE |
97 ROLE_LAWFUL|ROLE_NEUTRAL,
98 /* Str Int Wis Dex Con Cha */
99 { 10, 7, 7, 7, 8, 6 },
100 { 30, 6, 7, 20, 30, 7 },
101 /* Init Lower Higher */
102 { 14, 0, 0, 8, 2, 0 }, /* Hit points */
103 { 1, 0, 0, 1, 0, 1 },10, /* Energy */
104 0, 12, 0, 1, 8, A_INT, SPE_DIG, -4
105 },
106 { {"Healer", 0}, {
107 {"Rhizotomist", 0},
108 {"Empiric", 0},
109 {"Embalmer", 0},
110 {"Dresser", 0},
111 {"Medici ossium", 0},
112 {"Herbalist", 0},
113 {"Magister", 0},
114 {"Physician", 0},
115 {"Chirurgeon", 0} },
116 "_Athena", "Hermes", "Poseidon", /* Greek */
117 "Hea", "the Temple of Epidaurus", "the Temple of Coeus",
118 PM_HEALER, NON_PM, NON_PM,
119 PM_HIPPOCRATES, PM_ATTENDANT, PM_CYCLOPS,
120 PM_GIANT_RAT, PM_SNAKE, S_RODENT, S_YETI,
121 ART_STAFF_OF_AESCULAPIUS,
122 MH_HUMAN|MH_GNOME | ROLE_MALE|ROLE_FEMALE | ROLE_NEUTRAL,
123 /* Str Int Wis Dex Con Cha */
124 { 7, 7, 13, 7, 11, 16 },
125 { 15, 20, 20, 15, 25, 10 },
126 /* Init Lower Higher */
127 { 11, 0, 0, 8, 1, 0 }, /* Hit points */
128 { 1, 4, 0, 1, 0, 2 },20, /* Energy */
129 10, 3,-3, 2, 10, A_WIS, SPE_CURE_SICKNESS, -4
130 },
131 { {"Knight", 0}, {
132 {"Gallant", 0},
133 {"Esquire", 0},
134 {"Bachelor", 0},
135 {"Sergeant", 0},
136 {"Knight", 0},
137 {"Banneret", 0},
138 {"Chevalier", 0},
139 {"Seignieur", 0},
140 {"Paladin", 0} },
141 "Lugh", "_Brigit", "Manannan Mac Lir", /* Celtic */
142 "Kni", "Camelot Castle", "the Isle of Glass",
143 PM_KNIGHT, NON_PM, PM_PONY,
144 PM_KING_ARTHUR, PM_PAGE, PM_IXOTH,
145 PM_QUASIT, PM_OCHRE_JELLY, S_IMP, S_JELLY,
146 ART_MAGIC_MIRROR_OF_MERLIN,
147 MH_HUMAN | ROLE_MALE|ROLE_FEMALE | ROLE_LAWFUL,
148 /* Str Int Wis Dex Con Cha */
149 { 13, 7, 14, 8, 10, 17 },
150 { 20, 15, 15, 10, 20, 10 },
151 /* Init Lower Higher */
152 { 14, 0, 0, 8, 2, 0 }, /* Hit points */
153 { 1, 4, 0, 1, 0, 2 },10, /* Energy */
154 10, 8,-2, 0, 9, A_WIS, SPE_TURN_UNDEAD, -4
155 },
156 { {"Monk", 0}, {
157 {"Candidate", 0},
158 {"Novice", 0},
159 {"Initiate", 0},
160 {"Student of Stones", 0},
161 {"Student of Waters", 0},
162 {"Student of Metals", 0},
163 {"Student of Winds", 0},
164 {"Student of Fire", 0},
165 {"Master", 0} },
166 "Shan Lai Ching", "Chih Sung-tzu", "Huan Ti", /* Chinese */
167 "Mon", "the Monastery of Chan-Sune",
168 "the Monastery of the Earth-Lord",
169 PM_MONK, NON_PM, NON_PM,
170 PM_GRAND_MASTER, PM_ABBOT, PM_MASTER_KAEN,
171 PM_EARTH_ELEMENTAL, PM_XORN, S_ELEMENTAL, S_XORN,
172 ART_EYES_OF_THE_OVERWORLD,
173 MH_HUMAN | ROLE_MALE|ROLE_FEMALE |
174 ROLE_LAWFUL|ROLE_NEUTRAL|ROLE_CHAOTIC,
175 /* Str Int Wis Dex Con Cha */
176 { 10, 7, 8, 8, 7, 7 },
177 { 25, 10, 20, 20, 15, 10 },
178 /* Init Lower Higher */
179 { 12, 0, 0, 8, 1, 0 }, /* Hit points */
180 { 2, 2, 0, 2, 0, 2 },10, /* Energy */
181 10, 8,-2, 2, 20, A_WIS, SPE_RESTORE_ABILITY, -4
182 },
183 { {"Priest", "Priestess"}, {
184 {"Aspirant", 0},
185 {"Acolyte", 0},
186 {"Adept", 0},
187 {"Priest", "Priestess"},
188 {"Curate", 0},
189 {"Canon", "Canoness"},
190 {"Lama", 0},
191 {"Patriarch", "Matriarch"},
192 {"High Priest", "High Priestess"} },
193 0, 0, 0, /* chosen randomly from among the other roles */
194 "Pri", "the Great Temple", "the Temple of Nalzok",
195 PM_PRIEST, PM_PRIESTESS, NON_PM,
196 PM_ARCH_PRIEST, PM_ACOLYTE, PM_NALZOK,
197 PM_HUMAN_ZOMBIE, PM_WRAITH, S_ZOMBIE, S_WRAITH,
198 ART_MITRE_OF_HOLINESS,
199 MH_HUMAN|MH_ELF | ROLE_MALE|ROLE_FEMALE |
200 ROLE_LAWFUL|ROLE_NEUTRAL|ROLE_CHAOTIC,
201 /* Str Int Wis Dex Con Cha */
202 { 7, 7, 10, 7, 7, 7 },
203 { 15, 10, 30, 15, 20, 10 },
204 /* Init Lower Higher */
205 { 12, 0, 0, 8, 1, 0 }, /* Hit points */
206 { 4, 3, 0, 2, 0, 2 },10, /* Energy */
207 0, 3,-2, 2, 10, A_WIS, SPE_REMOVE_CURSE, -4
208 },
209 /* Note: Rogue precedes Ranger so that use of `-R' on the command line
210 retains its traditional meaning. */
211 { {"Rogue", 0}, {
212 {"Footpad", 0},
213 {"Cutpurse", 0},
214 {"Rogue", 0},
215 {"Pilferer", 0},
216 {"Robber", 0},
217 {"Burglar", 0},
218 {"Filcher", 0},
219 {"Magsman", "Magswoman"},
220 {"Thief", 0} },
221 "Issek", "Mog", "Kos", /* Nehwon */
222 "Rog", "the Thieves' Guild Hall", "the Assassins' Guild Hall",
223 PM_ROGUE, NON_PM, NON_PM,
224 PM_MASTER_OF_THIEVES, PM_THUG, PM_MASTER_ASSASSIN,
225 PM_LEPRECHAUN, PM_GUARDIAN_NAGA, S_NYMPH, S_NAGA,
226 ART_MASTER_KEY_OF_THIEVERY,
227 MH_HUMAN|MH_ORC | ROLE_MALE|ROLE_FEMALE |
228 ROLE_CHAOTIC,
229 /* Str Int Wis Dex Con Cha */
230 { 7, 7, 7, 10, 7, 6 },
231 { 20, 10, 10, 30, 20, 10 },
232 /* Init Lower Higher */
233 { 10, 0, 0, 8, 1, 0 }, /* Hit points */
234 { 1, 0, 0, 1, 0, 1 },11, /* Energy */
235 10, 8, 0, 1, 9, A_INT, SPE_DETECT_TREASURE, -4
236 },
237 { {"Ranger", 0}, {
238 #if 0 /* OBSOLETE */
239 {"Edhel", "Elleth"},
240 {"Edhel", "Elleth"}, /* elf-maid */
241 {"Ohtar", "Ohtie"}, /* warrior */
242 {"Kano", /* commander (Q.) ['a] */
243 "Kanie"}, /* educated guess, until further research- SAC */
244 {"Arandur", /* king's servant, minister (Q.) - guess */
245 "Aranduriel"}, /* educated guess */
246 {"Hir", "Hiril"}, /* lord, lady (S.) ['ir] */
247 {"Aredhel", "Arwen"}, /* noble elf, maiden (S.) */
248 {"Ernil", "Elentariel"}, /* prince (S.), elf-maiden (Q.) */
249 {"Elentar", "Elentari"}, /* Star-king, -queen (Q.) */
250 "Solonor Thelandira", "Aerdrie Faenya", "Lolth", /* Elven */
251 #endif
252 {"Tenderfoot", 0},
253 {"Lookout", 0},
254 {"Trailblazer", 0},
255 {"Reconnoiterer", "Reconnoiteress"},
256 {"Scout", 0},
257 {"Arbalester", 0}, /* One skilled at crossbows */
258 {"Archer", 0},
259 {"Sharpshooter", 0},
260 {"Marksman", "Markswoman"} },
261 "Mercury", "_Venus", "Mars", /* Roman/planets */
262 "Ran", "Orion's camp", "the cave of the wumpus",
263 PM_RANGER, NON_PM, PM_LITTLE_DOG /* Orion & canis major */,
264 PM_ORION, PM_HUNTER, PM_SCORPIUS,
265 PM_FOREST_CENTAUR, PM_SCORPION, S_CENTAUR, S_SPIDER,
266 ART_LONGBOW_OF_DIANA,
267 MH_HUMAN|MH_ELF|MH_GNOME|MH_ORC | ROLE_MALE|ROLE_FEMALE |
268 ROLE_NEUTRAL|ROLE_CHAOTIC,
269 /* Str Int Wis Dex Con Cha */
270 { 13, 13, 13, 9, 13, 7 },
271 { 30, 10, 10, 20, 20, 10 },
272 /* Init Lower Higher */
273 { 13, 0, 0, 6, 1, 0 }, /* Hit points */
274 { 1, 0, 0, 1, 0, 1 },12, /* Energy */
275 10, 9, 2, 1, 10, A_INT, SPE_INVISIBILITY, -4
276 },
277 { {"Samurai", 0}, {
278 {"Hatamoto", 0}, /* Banner Knight */
279 {"Ronin", 0}, /* no allegiance */
280 {"Ninja", 0}, /* secret society */
281 {"Joshu", 0}, /* heads a castle */
282 {"Ryoshu", 0}, /* has a territory */
283 {"Kokushu", 0}, /* heads a province */
284 {"Daimyo", 0}, /* a samurai lord */
285 {"Kuge", 0}, /* Noble of the Court */
286 {"Shogun", 0} },/* supreme commander, warlord */
287 "_Amaterasu Omikami", "Raijin", "Susanowo", /* Japanese */
288 "Sam", "the Castle of the Taro Clan", "the Shogun's Castle",
289 PM_SAMURAI, NON_PM, PM_LITTLE_DOG,
290 PM_LORD_SATO, PM_ROSHI, PM_ASHIKAGA_TAKAUJI,
291 PM_WOLF, PM_STALKER, S_DOG, S_ELEMENTAL,
292 ART_TSURUGI_OF_MURAMASA,
293 MH_HUMAN | ROLE_MALE|ROLE_FEMALE | ROLE_LAWFUL,
294 /* Str Int Wis Dex Con Cha */
295 { 10, 8, 7, 10, 17, 6 },
296 { 30, 10, 10, 30, 14, 10 },
297 /* Init Lower Higher */
298 { 13, 0, 0, 8, 1, 0 }, /* Hit points */
299 { 1, 0, 0, 1, 0, 1 },11, /* Energy */
300 10, 10, 0, 0, 8, A_INT, SPE_CLAIRVOYANCE, -4
301 },
302 #ifdef TOURIST
303 { {"Tourist", 0}, {
304 {"Rambler", 0},
305 {"Sightseer", 0},
306 {"Excursionist",0},
307 {"Peregrinator","Peregrinatrix"},
308 {"Traveler", 0},
309 {"Journeyer", 0},
310 {"Voyager", 0},
311 {"Explorer", 0},
312 {"Adventurer", 0} },
313 "Blind Io", "_The Lady", "Offler", /* Discworld */
314 "Tou", "Ankh-Morpork", "the Thieves' Guild Hall",
315 PM_TOURIST, NON_PM, NON_PM,
316 PM_TWOFLOWER, PM_GUIDE, PM_MASTER_OF_THIEVES,
317 PM_GIANT_SPIDER, PM_FOREST_CENTAUR, S_SPIDER, S_CENTAUR,
318 ART_YENDORIAN_EXPRESS_CARD,
319 MH_HUMAN | ROLE_MALE|ROLE_FEMALE | ROLE_NEUTRAL,
320 /* Str Int Wis Dex Con Cha */
321 { 7, 10, 6, 7, 7, 10 },
322 { 15, 10, 10, 15, 30, 20 },
323 /* Init Lower Higher */
324 { 8, 0, 0, 8, 0, 0 }, /* Hit points */
325 { 1, 0, 0, 1, 0, 1 },14, /* Energy */
326 0, 5, 1, 2, 10, A_INT, SPE_CHARM_MONSTER, -4
327 },
328 #endif
329 { {"Valkyrie", 0}, {
330 {"Stripling", 0},
331 {"Skirmisher", 0},
332 {"Fighter", 0},
333 {"Man-at-arms", "Woman-at-arms"},
334 {"Warrior", 0},
335 {"Swashbuckler",0},
336 {"Hero", "Heroine"},
337 {"Champion", 0},
338 {"Lord", "Lady"} },
339 "Tyr", "Odin", "Loki", /* Norse */
340 "Val", "the Shrine of Destiny", "the cave of Surtur",
341 PM_VALKYRIE, NON_PM, NON_PM /*PM_WINTER_WOLF_CUB*/,
342 PM_NORN, PM_WARRIOR, PM_LORD_SURTUR,
343 PM_FIRE_ANT, PM_FIRE_GIANT, S_ANT, S_GIANT,
344 ART_ORB_OF_FATE,
345 MH_HUMAN|MH_DWARF | ROLE_FEMALE | ROLE_LAWFUL|ROLE_NEUTRAL,
346 /* Str Int Wis Dex Con Cha */
347 { 10, 7, 7, 7, 10, 7 },
348 { 30, 6, 7, 20, 30, 7 },
349 /* Init Lower Higher */
350 { 14, 0, 0, 8, 2, 0 }, /* Hit points */
351 { 1, 0, 0, 1, 0, 1 },10, /* Energy */
352 0, 10,-2, 0, 9, A_WIS, SPE_CONE_OF_COLD, -4
353 },
354 { {"Wizard", 0}, {
355 {"Evoker", 0},
356 {"Conjurer", 0},
357 {"Thaumaturge", 0},
358 {"Magician", 0},
359 {"Enchanter", "Enchantress"},
360 {"Sorcerer", "Sorceress"},
361 {"Necromancer", 0},
362 {"Wizard", 0},
363 {"Mage", 0} },
364 "Ptah", "Thoth", "Anhur", /* Egyptian */
365 "Wiz", "the Tower of the Balance", "the Tower of Darkness",
366 PM_WIZARD, NON_PM, PM_KITTEN,
367 PM_WIZARD_OF_BALANCE, PM_APPRENTICE, PM_DARK_ONE,
368 PM_VAMPIRE_BAT, PM_XORN, S_BAT, S_WRAITH,
369 ART_EYE_OF_THE_AETHIOPICA,
370 MH_HUMAN|MH_ELF|MH_GNOME|MH_ORC | ROLE_MALE|ROLE_FEMALE |
371 ROLE_NEUTRAL|ROLE_CHAOTIC,
372 /* Str Int Wis Dex Con Cha */
373 { 7, 10, 7, 7, 7, 7 },
374 { 10, 30, 10, 20, 20, 10 },
375 /* Init Lower Higher */
376 { 10, 0, 0, 8, 1, 0 }, /* Hit points */
377 { 4, 3, 0, 2, 0, 3 },12, /* Energy */
378 0, 1, 0, 3, 10, A_INT, SPE_MAGIC_MISSILE, -4
379 },
380 /* Array terminator */
381 {{0, 0}}
382 };
383
384
385 /* The player's role, created at runtime from initial
386 * choices. This may be munged in role_init().
387 */
388 struct Role urole =
389 { {"Undefined", 0}, { {0, 0}, {0, 0}, {0, 0},
390 {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0} },
391 "L", "N", "C", "Xxx", "home", "locate",
392 NON_PM, NON_PM, NON_PM, NON_PM, NON_PM, NON_PM,
393 NON_PM, NON_PM, 0, 0, 0, 0,
394 /* Str Int Wis Dex Con Cha */
395 { 7, 7, 7, 7, 7, 7 },
396 { 20, 15, 15, 20, 20, 10 },
397 /* Init Lower Higher */
398 { 10, 0, 0, 8, 1, 0 }, /* Hit points */
399 { 2, 0, 0, 2, 0, 3 },14, /* Energy */
400 0, 10, 0, 0, 4, A_INT, 0, -3
401 };
402
403
404
405 /* Table of all races */
406 const struct Race races[] = {
407 { "human", "human", "humanity", "Hum",
408 {"man", "woman"},
409 PM_HUMAN, NON_PM, PM_HUMAN_MUMMY, PM_HUMAN_ZOMBIE,
410 MH_HUMAN | ROLE_MALE|ROLE_FEMALE |
411 ROLE_LAWFUL|ROLE_NEUTRAL|ROLE_CHAOTIC,
412 MH_HUMAN, 0, MH_GNOME|MH_ORC,
413 /* Str Int Wis Dex Con Cha */
414 { 3, 3, 3, 3, 3, 3 },
415 { STR18(100), 18, 18, 18, 18, 18 },
416 /* Init Lower Higher */
417 { 2, 0, 0, 2, 1, 0 }, /* Hit points */
418 { 1, 0, 2, 0, 2, 0 } /* Energy */
419 },
420 { "elf", "elven", "elvenkind", "Elf",
421 {0, 0},
422 PM_ELF, NON_PM, PM_ELF_MUMMY, PM_ELF_ZOMBIE,
423 MH_ELF | ROLE_MALE|ROLE_FEMALE | ROLE_CHAOTIC,
424 MH_ELF, MH_ELF, MH_ORC,
425 /* Str Int Wis Dex Con Cha */
426 { 3, 3, 3, 3, 3, 3 },
427 { 18, 20, 20, 18, 16, 18 },
428 /* Init Lower Higher */
429 { 1, 0, 0, 1, 1, 0 }, /* Hit points */
430 { 2, 0, 3, 0, 3, 0 } /* Energy */
431 },
432 { "dwarf", "dwarven", "dwarvenkind", "Dwa",
433 {0, 0},
434 PM_DWARF, NON_PM, PM_DWARF_MUMMY, PM_DWARF_ZOMBIE,
435 MH_DWARF | ROLE_MALE|ROLE_FEMALE | ROLE_LAWFUL,
436 MH_DWARF, MH_DWARF|MH_GNOME, MH_ORC,
437 /* Str Int Wis Dex Con Cha */
438 { 3, 3, 3, 3, 3, 3 },
439 { STR18(100), 16, 16, 20, 20, 16 },
440 /* Init Lower Higher */
441 { 4, 0, 0, 3, 2, 0 }, /* Hit points */
442 { 0, 0, 0, 0, 0, 0 } /* Energy */
443 },
444 { "gnome", "gnomish", "gnomehood", "Gno",
445 {0, 0},
446 PM_GNOME, NON_PM, PM_GNOME_MUMMY, PM_GNOME_ZOMBIE,
447 MH_GNOME | ROLE_MALE|ROLE_FEMALE | ROLE_NEUTRAL,
448 MH_GNOME, MH_DWARF|MH_GNOME, MH_HUMAN,
449 /* Str Int Wis Dex Con Cha */
450 { 3, 3, 3, 3, 3, 3 },
451 {STR18(50),19, 18, 18, 18, 18 },
452 /* Init Lower Higher */
453 { 1, 0, 0, 1, 0, 0 }, /* Hit points */
454 { 2, 0, 2, 0, 2, 0 } /* Energy */
455 },
456 { "orc", "orcish", "orcdom", "Orc",
457 {0, 0},
458 PM_ORC, NON_PM, PM_ORC_MUMMY, PM_ORC_ZOMBIE,
459 MH_ORC | ROLE_MALE|ROLE_FEMALE | ROLE_CHAOTIC,
460 MH_ORC, 0, MH_HUMAN|MH_ELF|MH_DWARF,
461 /* Str Int Wis Dex Con Cha */
462 { 3, 3, 3, 3, 3, 3 },
463 {STR18(50),16, 16, 18, 18, 16 },
464 /* Init Lower Higher */
465 { 1, 0, 0, 1, 0, 0 }, /* Hit points */
466 { 1, 0, 1, 0, 1, 0 } /* Energy */
467 },
468 /* Array terminator */
469 { 0, 0, 0, 0 }};
470
471
472 /* The player's race, created at runtime from initial
473 * choices. This may be munged in role_init().
474 */
475 struct Race urace =
476 { "something", "undefined", "something", "Xxx",
477 {0, 0},
478 NON_PM, NON_PM, NON_PM, NON_PM,
479 0, 0, 0, 0,
480 /* Str Int Wis Dex Con Cha */
481 { 3, 3, 3, 3, 3, 3 },
482 { STR18(100), 18, 18, 18, 18, 18 },
483 /* Init Lower Higher */
484 { 2, 0, 0, 2, 1, 0 }, /* Hit points */
485 { 1, 0, 2, 0, 2, 0 } /* Energy */
486 };
487
488
489 /* Table of all genders */
490 const struct Gender genders[] = {
491 {"male", "he", "him", "his", "Mal", ROLE_MALE},
492 {"female", "she", "her", "her", "Fem", ROLE_FEMALE},
493 {"neuter", "it", "it", "its", "Ntr", ROLE_NEUTER}
494 };
495
496
497 /* Table of all alignments */
498 const struct Align aligns[] = {
499 {"law", "lawful", "Law", ROLE_LAWFUL, A_LAWFUL},
500 {"balance", "neutral", "Neu", ROLE_NEUTRAL, A_NEUTRAL},
501 {"chaos", "chaotic", "Cha", ROLE_CHAOTIC, A_CHAOTIC},
502 {"evil", "unaligned", "Una", 0, A_NONE}
503 };
504
505 /* used by str2XXX() */
506 static char NEARDATA randomstr[] = "random";
507
508
509 boolean
validrole(rolenum)510 validrole(rolenum)
511 int rolenum;
512 {
513 return (rolenum >= 0 && rolenum < SIZE(roles)-1);
514 }
515
516
517 int
randrole()518 randrole()
519 {
520 return (rn2(SIZE(roles)-1));
521 }
522
523
524 int
str2role(str)525 str2role(str)
526 char *str;
527 {
528 int i, len;
529
530 /* Is str valid? */
531 if (!str || !str[0])
532 return ROLE_NONE;
533
534 /* Match as much of str as is provided */
535 len = strlen(str);
536 for (i = 0; roles[i].name.m; i++) {
537 /* Does it match the male name? */
538 if (!strncmpi(str, roles[i].name.m, len))
539 return i;
540 /* Or the female name? */
541 if (roles[i].name.f && !strncmpi(str, roles[i].name.f, len))
542 return i;
543 /* Or the filecode? */
544 if (!strcmpi(str, roles[i].filecode))
545 return i;
546 }
547
548 if ((len == 1 && (*str == '*' || *str == '@')) ||
549 !strncmpi(str, randomstr, len))
550 return ROLE_RANDOM;
551
552 /* Couldn't find anything appropriate */
553 return ROLE_NONE;
554 }
555
556
557 boolean
validrace(rolenum,racenum)558 validrace(rolenum, racenum)
559 int rolenum, racenum;
560 {
561 /* Assumes validrole */
562 return (racenum >= 0 && racenum < SIZE(races)-1 &&
563 (roles[rolenum].allow & races[racenum].allow & ROLE_RACEMASK));
564 }
565
566
567 int
randrace(rolenum)568 randrace(rolenum)
569 int rolenum;
570 {
571 int i, n = 0;
572
573 /* Count the number of valid races */
574 for (i = 0; races[i].noun; i++)
575 if (roles[rolenum].allow & races[i].allow & ROLE_RACEMASK)
576 n++;
577
578 /* Pick a random race */
579 /* Use a factor of 100 in case of bad random number generators */
580 if (n) n = rn2(n*100)/100;
581 for (i = 0; races[i].noun; i++)
582 if (roles[rolenum].allow & races[i].allow & ROLE_RACEMASK) {
583 if (n) n--;
584 else return (i);
585 }
586
587 /* This role has no permitted races? */
588 return (rn2(SIZE(races)-1));
589 }
590
591
592 int
str2race(str)593 str2race(str)
594 char *str;
595 {
596 int i, len;
597
598 /* Is str valid? */
599 if (!str || !str[0])
600 return ROLE_NONE;
601
602 /* Match as much of str as is provided */
603 len = strlen(str);
604 for (i = 0; races[i].noun; i++) {
605 /* Does it match the noun? */
606 if (!strncmpi(str, races[i].noun, len))
607 return i;
608 /* Or the filecode? */
609 if (!strcmpi(str, races[i].filecode))
610 return i;
611 }
612
613 if ((len == 1 && (*str == '*' || *str == '@')) ||
614 !strncmpi(str, randomstr, len))
615 return ROLE_RANDOM;
616
617 /* Couldn't find anything appropriate */
618 return ROLE_NONE;
619 }
620
621
622 boolean
validgend(rolenum,racenum,gendnum)623 validgend(rolenum, racenum, gendnum)
624 int rolenum, racenum, gendnum;
625 {
626 /* Assumes validrole and validrace */
627 return (gendnum >= 0 && gendnum < ROLE_GENDERS &&
628 (roles[rolenum].allow & races[racenum].allow &
629 genders[gendnum].allow & ROLE_GENDMASK));
630 }
631
632
633 int
randgend(rolenum,racenum)634 randgend(rolenum, racenum)
635 int rolenum, racenum;
636 {
637 int i, n = 0;
638
639 /* Count the number of valid genders */
640 for (i = 0; i < ROLE_GENDERS; i++)
641 if (roles[rolenum].allow & races[racenum].allow &
642 genders[i].allow & ROLE_GENDMASK)
643 n++;
644
645 /* Pick a random gender */
646 if (n) n = rn2(n);
647 for (i = 0; i < ROLE_GENDERS; i++)
648 if (roles[rolenum].allow & races[racenum].allow &
649 genders[i].allow & ROLE_GENDMASK) {
650 if (n) n--;
651 else return (i);
652 }
653
654 /* This role/race has no permitted genders? */
655 return (rn2(ROLE_GENDERS));
656 }
657
658
659 int
str2gend(str)660 str2gend(str)
661 char *str;
662 {
663 int i, len;
664
665 /* Is str valid? */
666 if (!str || !str[0])
667 return ROLE_NONE;
668
669 /* Match as much of str as is provided */
670 len = strlen(str);
671 for (i = 0; i < ROLE_GENDERS; i++) {
672 /* Does it match the adjective? */
673 if (!strncmpi(str, genders[i].adj, len))
674 return i;
675 /* Or the filecode? */
676 if (!strcmpi(str, genders[i].filecode))
677 return i;
678 }
679 if ((len == 1 && (*str == '*' || *str == '@')) ||
680 !strncmpi(str, randomstr, len))
681 return ROLE_RANDOM;
682
683 /* Couldn't find anything appropriate */
684 return ROLE_NONE;
685 }
686
687
688 boolean
validalign(rolenum,racenum,alignnum)689 validalign(rolenum, racenum, alignnum)
690 int rolenum, racenum, alignnum;
691 {
692 /* Assumes validrole and validrace */
693 return (alignnum >= 0 && alignnum < ROLE_ALIGNS &&
694 (roles[rolenum].allow & races[racenum].allow &
695 aligns[alignnum].allow & ROLE_ALIGNMASK));
696 }
697
698
699 int
randalign(rolenum,racenum)700 randalign(rolenum, racenum)
701 int rolenum, racenum;
702 {
703 int i, n = 0;
704
705 /* Count the number of valid alignments */
706 for (i = 0; i < ROLE_ALIGNS; i++)
707 if (roles[rolenum].allow & races[racenum].allow &
708 aligns[i].allow & ROLE_ALIGNMASK)
709 n++;
710
711 /* Pick a random alignment */
712 if (n) n = rn2(n);
713 for (i = 0; i < ROLE_ALIGNS; i++)
714 if (roles[rolenum].allow & races[racenum].allow &
715 aligns[i].allow & ROLE_ALIGNMASK) {
716 if (n) n--;
717 else return (i);
718 }
719
720 /* This role/race has no permitted alignments? */
721 return (rn2(ROLE_ALIGNS));
722 }
723
724
725 int
str2align(str)726 str2align(str)
727 char *str;
728 {
729 int i, len;
730
731 /* Is str valid? */
732 if (!str || !str[0])
733 return ROLE_NONE;
734
735 /* Match as much of str as is provided */
736 len = strlen(str);
737 for (i = 0; i < ROLE_ALIGNS; i++) {
738 /* Does it match the adjective? */
739 if (!strncmpi(str, aligns[i].adj, len))
740 return i;
741 /* Or the filecode? */
742 if (!strcmpi(str, aligns[i].filecode))
743 return i;
744 }
745 if ((len == 1 && (*str == '*' || *str == '@')) ||
746 !strncmpi(str, randomstr, len))
747 return ROLE_RANDOM;
748
749 /* Couldn't find anything appropriate */
750 return ROLE_NONE;
751 }
752
753 /* is rolenum compatible with any racenum/gendnum/alignnum constraints? */
754 boolean
ok_role(rolenum,racenum,gendnum,alignnum)755 ok_role(rolenum, racenum, gendnum, alignnum)
756 int rolenum, racenum, gendnum, alignnum;
757 {
758 int i;
759 short allow;
760
761 if (rolenum >= 0 && rolenum < SIZE(roles)-1) {
762 allow = roles[rolenum].allow;
763 if (racenum >= 0 && racenum < SIZE(races)-1 &&
764 !(allow & races[racenum].allow & ROLE_RACEMASK))
765 return FALSE;
766 if (gendnum >= 0 && gendnum < ROLE_GENDERS &&
767 !(allow & genders[gendnum].allow & ROLE_GENDMASK))
768 return FALSE;
769 if (alignnum >= 0 && alignnum < ROLE_ALIGNS &&
770 !(allow & aligns[alignnum].allow & ROLE_ALIGNMASK))
771 return FALSE;
772 return TRUE;
773 } else {
774 for (i = 0; i < SIZE(roles)-1; i++) {
775 allow = roles[i].allow;
776 if (racenum >= 0 && racenum < SIZE(races)-1 &&
777 !(allow & races[racenum].allow & ROLE_RACEMASK))
778 continue;
779 if (gendnum >= 0 && gendnum < ROLE_GENDERS &&
780 !(allow & genders[gendnum].allow & ROLE_GENDMASK))
781 continue;
782 if (alignnum >= 0 && alignnum < ROLE_ALIGNS &&
783 !(allow & aligns[alignnum].allow & ROLE_ALIGNMASK))
784 continue;
785 return TRUE;
786 }
787 return FALSE;
788 }
789 }
790
791 /* pick a random role subject to any racenum/gendnum/alignnum constraints */
792 int
pick_role(racenum,gendnum,alignnum)793 pick_role(racenum, gendnum, alignnum)
794 int racenum, gendnum, alignnum;
795 {
796 int i;
797 int roles_ok = 0;
798
799 for (i = 0; i < SIZE(roles)-1; i++) {
800 if (ok_role(i, racenum, gendnum, alignnum))
801 roles_ok++;
802 }
803 if (roles_ok == 0)
804 return ROLE_NONE;
805 roles_ok = rn2(roles_ok);
806 for (i = 0; i < SIZE(roles)-1; i++) {
807 if (ok_role(i, racenum, gendnum, alignnum)) {
808 if (roles_ok == 0)
809 return i;
810 else
811 roles_ok--;
812 }
813 }
814 return ROLE_NONE;
815 }
816
817 /* is racenum compatible with any rolenum/gendnum/alignnum constraints? */
818 boolean
ok_race(rolenum,racenum,gendnum,alignnum)819 ok_race(rolenum, racenum, gendnum, alignnum)
820 int rolenum, racenum, gendnum, alignnum;
821 {
822 int i;
823 short allow;
824
825 if (racenum >= 0 && racenum < SIZE(races)-1) {
826 allow = races[racenum].allow;
827 if (rolenum >= 0 && rolenum < SIZE(roles)-1 &&
828 !(allow & roles[rolenum].allow & ROLE_RACEMASK))
829 return FALSE;
830 if (gendnum >= 0 && gendnum < ROLE_GENDERS &&
831 !(allow & genders[gendnum].allow & ROLE_GENDMASK))
832 return FALSE;
833 if (alignnum >= 0 && alignnum < ROLE_ALIGNS &&
834 !(allow & aligns[alignnum].allow & ROLE_ALIGNMASK))
835 return FALSE;
836 return TRUE;
837 } else {
838 for (i = 0; i < SIZE(races)-1; i++) {
839 allow = races[i].allow;
840 if (rolenum >= 0 && rolenum < SIZE(roles)-1 &&
841 !(allow & roles[rolenum].allow & ROLE_RACEMASK))
842 continue;
843 if (gendnum >= 0 && gendnum < ROLE_GENDERS &&
844 !(allow & genders[gendnum].allow & ROLE_GENDMASK))
845 continue;
846 if (alignnum >= 0 && alignnum < ROLE_ALIGNS &&
847 !(allow & aligns[alignnum].allow & ROLE_ALIGNMASK))
848 continue;
849 return TRUE;
850 }
851 return FALSE;
852 }
853 }
854
855 /* pick a random race subject to any rolenum/gendnum/alignnum constraints */
856 int
pick_race(rolenum,gendnum,alignnum)857 pick_race(rolenum, gendnum, alignnum)
858 int rolenum, gendnum, alignnum;
859 {
860 int i;
861 int races_ok = 0;
862
863 for (i = 0; i < SIZE(races)-1; i++) {
864 if (ok_race(rolenum, i, gendnum, alignnum))
865 races_ok++;
866 }
867 if (races_ok == 0)
868 return ROLE_NONE;
869 races_ok = rn2(races_ok);
870 for (i = 0; i < SIZE(races)-1; i++) {
871 if (ok_race(rolenum, i, gendnum, alignnum)) {
872 if (races_ok == 0)
873 return i;
874 else
875 races_ok--;
876 }
877 }
878 return ROLE_NONE;
879 }
880
881 /* is gendnum compatible with any rolenum/racenum/alignnum constraints? */
882 /* gender and alignment are not comparable (and also not constrainable) */
883 boolean
ok_gend(rolenum,racenum,gendnum,alignnum)884 ok_gend(rolenum, racenum, gendnum, alignnum)
885 int rolenum, racenum, gendnum, alignnum;
886 {
887 int i;
888 short allow;
889
890 if (gendnum >= 0 && gendnum < ROLE_GENDERS) {
891 allow = genders[gendnum].allow;
892 if (rolenum >= 0 && rolenum < SIZE(roles)-1 &&
893 !(allow & roles[rolenum].allow & ROLE_GENDMASK))
894 return FALSE;
895 if (racenum >= 0 && racenum < SIZE(races)-1 &&
896 !(allow & races[racenum].allow & ROLE_GENDMASK))
897 return FALSE;
898 return TRUE;
899 } else {
900 for (i = 0; i < ROLE_GENDERS; i++) {
901 allow = genders[i].allow;
902 if (rolenum >= 0 && rolenum < SIZE(roles)-1 &&
903 !(allow & roles[rolenum].allow & ROLE_GENDMASK))
904 continue;
905 if (racenum >= 0 && racenum < SIZE(races)-1 &&
906 !(allow & races[racenum].allow & ROLE_GENDMASK))
907 continue;
908 return TRUE;
909 }
910 return FALSE;
911 }
912 }
913
914 /* pick a random gender subject to any rolenum/racenum/alignnum constraints */
915 /* gender and alignment are not comparable (and also not constrainable) */
916 int
pick_gend(rolenum,racenum,alignnum)917 pick_gend(rolenum, racenum, alignnum)
918 int rolenum, racenum, alignnum;
919 {
920 int i;
921 int gends_ok = 0;
922
923 for (i = 0; i < ROLE_GENDERS; i++) {
924 if (ok_gend(rolenum, racenum, i, alignnum))
925 gends_ok++;
926 }
927 if (gends_ok == 0)
928 return ROLE_NONE;
929 gends_ok = rn2(gends_ok);
930 for (i = 0; i < ROLE_GENDERS; i++) {
931 if (ok_gend(rolenum, racenum, i, alignnum)) {
932 if (gends_ok == 0)
933 return i;
934 else
935 gends_ok--;
936 }
937 }
938 return ROLE_NONE;
939 }
940
941 /* is alignnum compatible with any rolenum/racenum/gendnum constraints? */
942 /* alignment and gender are not comparable (and also not constrainable) */
943 boolean
ok_align(rolenum,racenum,gendnum,alignnum)944 ok_align(rolenum, racenum, gendnum, alignnum)
945 int rolenum, racenum, gendnum, alignnum;
946 {
947 int i;
948 short allow;
949
950 if (alignnum >= 0 && alignnum < ROLE_ALIGNS) {
951 allow = aligns[alignnum].allow;
952 if (rolenum >= 0 && rolenum < SIZE(roles)-1 &&
953 !(allow & roles[rolenum].allow & ROLE_ALIGNMASK))
954 return FALSE;
955 if (racenum >= 0 && racenum < SIZE(races)-1 &&
956 !(allow & races[racenum].allow & ROLE_ALIGNMASK))
957 return FALSE;
958 return TRUE;
959 } else {
960 for (i = 0; i < ROLE_ALIGNS; i++) {
961 allow = races[i].allow;
962 if (rolenum >= 0 && rolenum < SIZE(roles)-1 &&
963 !(allow & roles[rolenum].allow & ROLE_ALIGNMASK))
964 continue;
965 if (racenum >= 0 && racenum < SIZE(races)-1 &&
966 !(allow & races[racenum].allow & ROLE_ALIGNMASK))
967 continue;
968 return TRUE;
969 }
970 return FALSE;
971 }
972 }
973
974 /* pick a random alignment subject to any rolenum/racenum/gendnum constraints */
975 /* alignment and gender are not comparable (and also not constrainable) */
976 int
pick_align(rolenum,racenum,gendnum)977 pick_align(rolenum, racenum, gendnum)
978 int rolenum, racenum, gendnum;
979 {
980 int i;
981 int aligns_ok = 0;
982
983 for (i = 0; i < ROLE_ALIGNS; i++) {
984 if (ok_align(rolenum, racenum, gendnum, i))
985 aligns_ok++;
986 }
987 if (aligns_ok == 0)
988 return ROLE_NONE;
989 aligns_ok = rn2(aligns_ok);
990 for (i = 0; i < ROLE_ALIGNS; i++) {
991 if (ok_align(rolenum, racenum, gendnum, i)) {
992 if (aligns_ok == 0)
993 return i;
994 else
995 aligns_ok--;
996 }
997 }
998 return ROLE_NONE;
999 }
1000
1001
1002 void
plnamesuffix()1003 plnamesuffix()
1004 {
1005 char *sptr, *eptr;
1006 int i;
1007
1008 /* Look for tokens delimited by '-' */
1009 if ((eptr = index(plname, '-')) != (char *) 0)
1010 *eptr++ = '\0';
1011 while (eptr) {
1012 /* Isolate the next token */
1013 sptr = eptr;
1014 if ((eptr = index(sptr, '-')) != (char *)0)
1015 *eptr++ = '\0';
1016
1017 /* Try to match it to something */
1018 if ((i = str2role(sptr)) != ROLE_NONE)
1019 flags.initrole = i;
1020 else if ((i = str2race(sptr)) != ROLE_NONE)
1021 flags.initrace = i;
1022 else if ((i = str2gend(sptr)) != ROLE_NONE)
1023 flags.initgend = i;
1024 else if ((i = str2align(sptr)) != ROLE_NONE)
1025 flags.initalign = i;
1026 }
1027 if(!plname[0]) {
1028 askname();
1029 plnamesuffix();
1030 }
1031
1032 /* commas in the plname confuse the record file, convert to spaces */
1033 for (sptr = plname; *sptr; sptr++) {
1034 if (*sptr == ',') *sptr = ' ';
1035 }
1036 }
1037
1038
1039 /*
1040 * Special setup modifications here:
1041 *
1042 * Unfortunately, this is going to have to be done
1043 * on each newgame or restore, because you lose the permonst mods
1044 * across a save/restore. :-)
1045 *
1046 * 1 - The Rogue Leader is the Tourist Nemesis.
1047 * 2 - Priests start with a random alignment - convert the leader and
1048 * guardians here.
1049 * 3 - Elves can have one of two different leaders, but can't work it
1050 * out here because it requires hacking the level file data (see
1051 * sp_lev.c).
1052 *
1053 * This code also replaces quest_init().
1054 */
1055 void
role_init()1056 role_init()
1057 {
1058 int alignmnt;
1059
1060 /* Strip the role letter out of the player name.
1061 * This is included for backwards compatibility.
1062 */
1063 plnamesuffix();
1064
1065 /* Check for a valid role. Try flags.initrole first. */
1066 if (!validrole(flags.initrole)) {
1067 /* Try the player letter second */
1068 if ((flags.initrole = str2role(pl_character)) < 0)
1069 /* None specified; pick a random role */
1070 flags.initrole = randrole();
1071 }
1072
1073 /* We now have a valid role index. Copy the role name back. */
1074 /* This should become OBSOLETE */
1075 Strcpy(pl_character, roles[flags.initrole].name.m);
1076 pl_character[PL_CSIZ-1] = '\0';
1077
1078 /* Check for a valid race */
1079 if (!validrace(flags.initrole, flags.initrace))
1080 flags.initrace = randrace(flags.initrole);
1081
1082 /* Check for a valid gender. Try flags.igend first. */
1083 if (!validgend(flags.initrole, flags.initrace, flags.initgend))
1084 /* Use flags.female second. Note that there is no way
1085 * to check for an unspecified gender.
1086 */
1087 flags.initgend = flags.female;
1088 /* Don't change flags.female; this may be a restore */
1089
1090 /* Check for a valid alignment */
1091 if (!validalign(flags.initrole, flags.initrace, flags.initalign))
1092 /* Pick a random alignment */
1093 flags.initalign = randalign(flags.initrole, flags.initrace);
1094 alignmnt = aligns[flags.initalign].value;
1095
1096 /* Initialize urole and urace */
1097 urole = roles[flags.initrole];
1098 urace = races[flags.initrace];
1099
1100 /* Fix up the quest leader */
1101 if (urole.ldrnum != NON_PM) {
1102 mons[urole.ldrnum].msound = MS_LEADER;
1103 mons[urole.ldrnum].mflags2 |= (M2_PEACEFUL);
1104 mons[urole.ldrnum].mflags3 |= M3_CLOSE;
1105 mons[urole.ldrnum].maligntyp = alignmnt * 3;
1106 }
1107
1108 /* Fix up the quest guardians */
1109 if (urole.guardnum != NON_PM) {
1110 mons[urole.guardnum].mflags2 |= (M2_PEACEFUL);
1111 mons[urole.guardnum].maligntyp = alignmnt * 3;
1112 }
1113
1114 /* Fix up the quest nemesis */
1115 if (urole.neminum != NON_PM) {
1116 mons[urole.neminum].msound = MS_NEMESIS;
1117 mons[urole.neminum].mflags2 &= ~(M2_PEACEFUL);
1118 mons[urole.neminum].mflags2 |= (M2_NASTY|M2_STALK|M2_HOSTILE);
1119 mons[urole.neminum].mflags3 |= M3_WANTSARTI | M3_WAITFORU;
1120 }
1121
1122 /* Fix up the god names */
1123 if (flags.pantheon == -1) { /* new game */
1124 flags.pantheon = flags.initrole; /* use own gods */
1125 while (!roles[flags.pantheon].lgod) /* unless they're missing */
1126 flags.pantheon = randrole();
1127 }
1128 if (!urole.lgod) {
1129 urole.lgod = roles[flags.pantheon].lgod;
1130 urole.ngod = roles[flags.pantheon].ngod;
1131 urole.cgod = roles[flags.pantheon].cgod;
1132 }
1133
1134 /* Fix up infravision */
1135 if (mons[urace.malenum].mflags3 & M3_INFRAVISION) {
1136 /* although an infravision intrinsic is possible, infravision
1137 * is purely a property of the physical race. This means that we
1138 * must put the infravision flag in the player's current race
1139 * (either that or have separate permonst entries for
1140 * elven/non-elven members of each class). The side effect is that
1141 * all NPCs of that class will have (probably bogus) infravision,
1142 * but since infravision has no effect for NPCs anyway we can
1143 * ignore this.
1144 */
1145 mons[urole.malenum].mflags3 |= M3_INFRAVISION;
1146 if (urole.femalenum != NON_PM)
1147 mons[urole.femalenum].mflags3 |= M3_INFRAVISION;
1148 }
1149
1150 /* Artifacts are fixed in hack_artifacts() */
1151
1152 /* Success! */
1153 return;
1154 }
1155
1156 const char *
Hello(mtmp)1157 Hello(mtmp)
1158 struct monst *mtmp;
1159 {
1160 switch (Role_switch) {
1161 case PM_KNIGHT:
1162 return ("Salutations"); /* Olde English */
1163 case PM_SAMURAI:
1164 return (mtmp && mtmp->data == &mons[PM_SHOPKEEPER] ?
1165 "Irasshaimase" : "Konnichi wa"); /* Japanese */
1166 #ifdef TOURIST
1167 case PM_TOURIST:
1168 return ("Aloha"); /* Hawaiian */
1169 #endif
1170 case PM_VALKYRIE:
1171 return (
1172 #ifdef MAIL
1173 mtmp && mtmp->data == &mons[PM_MAIL_DAEMON] ? "Hallo" :
1174 #endif
1175 "Velkommen"); /* Norse */
1176 default:
1177 return ("Hello");
1178 }
1179 }
1180
1181 const char *
Goodbye()1182 Goodbye()
1183 {
1184 switch (Role_switch) {
1185 case PM_KNIGHT:
1186 return ("Fare thee well"); /* Olde English */
1187 case PM_SAMURAI:
1188 return ("Sayonara"); /* Japanese */
1189 #ifdef TOURIST
1190 case PM_TOURIST:
1191 return ("Aloha"); /* Hawaiian */
1192 #endif
1193 case PM_VALKYRIE:
1194 return ("Farvel"); /* Norse */
1195 default:
1196 return ("Goodbye");
1197 }
1198 }
1199
1200 /* role.c */
1201