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
510 | validrole(rolenum)
511 | int rolenum;
512 | {
513 | return (rolenum >= 0 && rolenum < SIZE(roles)-1);
514 | }
515 |
516 |
517 | int
518 | randrole()
519 | {
520 | return (rn2(SIZE(roles)-1));
521 | }
522 |
523 |
524 | int
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 *
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 *
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 */