OSDN Git Service

update year to 2019
[jnethack/source.git] / src / role.c
1 /* NetHack 3.6  role.c  $NHDT-Date: 1463561393 2016/05/18 08:49:53 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.38 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985-1999. */
3 /*-Copyright (c) Robert Patrick Rankin, 2012. */
4 /* NetHack may be freely redistributed.  See license for details. */
5
6 /* JNetHack Copyright */
7 /* (c) Issei Numata, Naoki Hamada, Shigehiro Miyashita, 1994-2000  */
8 /* For 3.4-, Copyright (c) SHIRAKATA Kentaro, 2002-2019            */
9 /* JNetHack may be freely redistributed.  See license for details. */
10
11 #include "hack.h"
12
13 /*** Table of all roles ***/
14 /* According to AD&D, HD for some classes (ex. Wizard) should be smaller
15  * (4-sided for wizards).  But this is not AD&D, and using the AD&D
16  * rule here produces an unplayable character.  Thus I have used a minimum
17  * of an 10-sided hit die for everything.  Another AD&D change: wizards get
18  * a minimum strength of 4 since without one you can't teleport or cast
19  * spells. --KAA
20  *
21  * As the wizard has been updated (wizard patch 5 jun '96) their HD can be
22  * brought closer into line with AD&D. This forces wizards to use magic more
23  * and distance themselves from their attackers. --LSZ
24  *
25  * With the introduction of races, some hit points and energy
26  * has been reallocated for each race.  The values assigned
27  * to the roles has been reduced by the amount allocated to
28  * humans.  --KMH
29  *
30  * God names use a leading underscore to flag goddesses.
31  */
32 const struct Role roles[] = {
33 #if 0 /*JP*/
34     { { "Archeologist", 0 },
35       { { "Digger", 0 },
36         { "Field Worker", 0 },
37         { "Investigator", 0 },
38         { "Exhumer", 0 },
39         { "Excavator", 0 },
40         { "Spelunker", 0 },
41         { "Speleologist", 0 },
42         { "Collector", 0 },
43         { "Curator", 0 } },
44       "Quetzalcoatl", "Camaxtli", "Huhetotl", /* Central American */
45 #else
46     { { "\8dl\8cÃ\8aw\8eÒ", 0 },
47       { { "\8dz\88õ", 0 },
48         { "\98J\93­\8eÒ", 0 },
49         { "\92²\8d¸\8eÒ", 0 },
50         { "\94­\8c@\8eÒ", 0 },
51         { "\8c@\8dí\8eÒ", 0 },
52         { "\92T\8c\9f\8eÒ", 0 },
53         { "\93´\8cA\8aw\8eÒ", 0 },
54         { "\94ü\8fp\8eû\8fW\8eÒ", 0 },
55         { "\8aÙ\92·", 0 } },
56       "\83P\83c\83A\83\8b\83J\83g\83\8b", "\83J\83}\83L\83V\83g\83\8a", "\83t\83w\83g\83g\83\8b", /* Central American */
57 #endif
58       "Arc",
59 #if 0 /*JP*/
60       "the College of Archeology",
61       "the Tomb of the Toltec Kings",
62 #else
63       "\8dl\8cÃ\8aw\91å\8aw",
64       "\83g\83\8b\83e\83J\89¤\89Æ\82Ì\95æ",
65 #endif
66       PM_ARCHEOLOGIST,
67       NON_PM,
68       NON_PM,
69       PM_LORD_CARNARVON,
70       PM_STUDENT,
71       PM_MINION_OF_HUHETOTL,
72       NON_PM,
73       PM_HUMAN_MUMMY,
74       S_SNAKE,
75       S_MUMMY,
76       ART_ORB_OF_DETECTION,
77       MH_HUMAN | MH_DWARF | MH_GNOME | ROLE_MALE | ROLE_FEMALE | ROLE_LAWFUL
78           | ROLE_NEUTRAL,
79       /* Str Int Wis Dex Con Cha */
80       { 7, 10, 10, 7, 7, 7 },
81       { 20, 20, 20, 10, 20, 10 },
82       /* Init   Lower  Higher */
83       { 11, 0, 0, 8, 1, 0 }, /* Hit points */
84       { 1, 0, 0, 1, 0, 1 },
85       14, /* Energy */
86       10,
87       5,
88       0,
89       2,
90       10,
91       A_INT,
92       SPE_MAGIC_MAPPING,
93       -4 },
94 #if 0 /*JP*/
95     { { "Barbarian", 0 },
96       { { "Plunderer", "Plunderess" },
97         { "Pillager", 0 },
98         { "Bandit", 0 },
99         { "Brigand", 0 },
100         { "Raider", 0 },
101         { "Reaver", 0 },
102         { "Slayer", 0 },
103         { "Chieftain", "Chieftainess" },
104         { "Conqueror", "Conqueress" } },
105       "Mitra", "Crom", "Set", /* Hyborian */
106 #else
107     { { "\96ì\94Ø\90l", 0 },
108       { { "\93\90\91¯", 0 },
109         { "\97ª\92D\8eÒ", 0 },
110         { "\88«\8a¿", 0 },
111         { "\8eR\91¯", 0 },
112         { "\90N\97ª\8eÒ", 0 },
113         { "\8b­\93\90", 0 },
114         { "\8eE\9dC\8eÒ", 0 },
115         { "\8eñ\97Ì", 0 },
116         { "\90ª\95\9e\8eÒ", 0 } },
117       "\83~\83g\83\89", "\83N\83\8d\83\80", "\83Z\83g", /* Hyborian */
118 #endif
119       "Bar",
120 #if 0 /*JP*/
121       "the Camp of the Duali Tribe",
122       "the Duali Oasis",
123 #else
124       "\83f\83\85\83A\83\8a\91°\82Ì\83L\83\83\83\93\83v",
125       "\83f\83\85\83A\83\8a\91°\82Ì\83I\83A\83V\83X",
126 #endif
127       PM_BARBARIAN,
128       NON_PM,
129       NON_PM,
130       PM_PELIAS,
131       PM_CHIEFTAIN,
132       PM_THOTH_AMON,
133       PM_OGRE,
134       PM_TROLL,
135       S_OGRE,
136       S_TROLL,
137       ART_HEART_OF_AHRIMAN,
138       MH_HUMAN | MH_ORC | ROLE_MALE | ROLE_FEMALE | ROLE_NEUTRAL
139           | ROLE_CHAOTIC,
140       /* Str Int Wis Dex Con Cha */
141       { 16, 7, 7, 15, 16, 6 },
142       { 30, 6, 7, 20, 30, 7 },
143       /* Init   Lower  Higher */
144       { 14, 0, 0, 10, 2, 0 }, /* Hit points */
145       { 1, 0, 0, 1, 0, 1 },
146       10, /* Energy */
147       10,
148       14,
149       0,
150       0,
151       8,
152       A_INT,
153       SPE_HASTE_SELF,
154       -4 },
155 #if 0 /*JP*/
156     { { "Caveman", "Cavewoman" },
157       { { "Troglodyte", 0 },
158         { "Aborigine", 0 },
159         { "Wanderer", 0 },
160         { "Vagrant", 0 },
161         { "Wayfarer", 0 },
162         { "Roamer", 0 },
163         { "Nomad", 0 },
164         { "Rover", 0 },
165         { "Pioneer", 0 } },
166       "Anu", "_Ishtar", "Anshar", /* Babylonian */
167 #else
168     { { "\93´\8cA\90l", 0 },
169       { { "\8c\8a\8b\8f\90l", 0 },
170         { "\8c´\8fZ\96¯", 0 },
171         { "\95ú\98Q\8eÒ", 0 },
172         { "\95\82\98Q\8eÒ", 0 },
173         { "\97·\8ds\8eÒ", 0 },
174         { "\95ú\97V\8eÒ", 0 },
175         { "\97V\96q\96¯", 0 },
176         { "\97¬\98Q\8eÒ", 0 },
177         { "\90æ\8bì\8eÒ", 0 } },
178       "\83A\83k", "_\83C\83V\83\85\83^\83\8b", "\83A\83\93\83V\83\83\83\8b", /* Babylonian */
179 #endif
180       "Cav",
181 #if 0 /*JP*/
182       "the Caves of the Ancestors",
183       "the Dragon's Lair",
184 #else
185       "\91¾\8cÃ\82Ì\93´\8cA",
186       "\97³\82Ì\89B\82ê\89Æ",
187 #endif
188       PM_CAVEMAN,
189       PM_CAVEWOMAN,
190       PM_LITTLE_DOG,
191       PM_SHAMAN_KARNOV,
192       PM_NEANDERTHAL,
193       PM_CHROMATIC_DRAGON,
194       PM_BUGBEAR,
195       PM_HILL_GIANT,
196       S_HUMANOID,
197       S_GIANT,
198       ART_SCEPTRE_OF_MIGHT,
199       MH_HUMAN | MH_DWARF | MH_GNOME | ROLE_MALE | ROLE_FEMALE | ROLE_LAWFUL
200           | ROLE_NEUTRAL,
201       /* Str Int Wis Dex Con Cha */
202       { 10, 7, 7, 7, 8, 6 },
203       { 30, 6, 7, 20, 30, 7 },
204       /* Init   Lower  Higher */
205       { 14, 0, 0, 8, 2, 0 }, /* Hit points */
206       { 1, 0, 0, 1, 0, 1 },
207       10, /* Energy */
208       0,
209       12,
210       0,
211       1,
212       8,
213       A_INT,
214       SPE_DIG,
215       -4 },
216 #if 0 /*JP*/
217     { { "Healer", 0 },
218       { { "Rhizotomist", 0 },
219         { "Empiric", 0 },
220         { "Embalmer", 0 },
221         { "Dresser", 0 },
222         { "Medicus ossium", "Medica ossium" },
223         { "Herbalist", 0 },
224         { "Magister", "Magistra" },
225         { "Physician", 0 },
226         { "Chirurgeon", 0 } },
227       "_Athena", "Hermes", "Poseidon", /* Greek */
228 #else
229     { { "\96ò\8et", 0 },
230       { { "\8c©\8fK\82¢", 0 },
231         { "\88ã\8et\8c©\8fK\82¢", 0 },
232         { "\8aÅ\8cì\8et", "\8aÅ\8cì\95w" },
233         { "\88ã\8et\8f\95\8eè", 0 },
234         { "\96ò\95¨\8eå\94C", 0 },
235         { "\8a¿\95û\88ã", 0 },
236         { "\88ã\8et\8eå\94C", 0 },
237         { "\93à\89È\88ã", 0 },
238         { "\8aO\89È\88ã", 0 } },
239       "_\83A\83e\83i", "\83w\83\8b\83\81\83X", "\83|\83Z\83C\83h\83\93", /* Greek */
240 #endif
241       "Hea",
242 #if 0 /*JP*/
243       "the Temple of Epidaurus",
244       "the Temple of Coeus",
245 #else
246       "\83G\83s\83_\83E\83\8d\83X\8e\9b\89@",
247       "\83R\83C\83I\83X\8e\9b\89@",
248 #endif
249       PM_HEALER,
250       NON_PM,
251       NON_PM,
252       PM_HIPPOCRATES,
253       PM_ATTENDANT,
254       PM_CYCLOPS,
255       PM_GIANT_RAT,
256       PM_SNAKE,
257       S_RODENT,
258       S_YETI,
259       ART_STAFF_OF_AESCULAPIUS,
260       MH_HUMAN | MH_GNOME | ROLE_MALE | ROLE_FEMALE | ROLE_NEUTRAL,
261       /* Str Int Wis Dex Con Cha */
262       { 7, 7, 13, 7, 11, 16 },
263       { 15, 20, 20, 15, 25, 5 },
264       /* Init   Lower  Higher */
265       { 11, 0, 0, 8, 1, 0 }, /* Hit points */
266       { 1, 4, 0, 1, 0, 2 },
267       20, /* Energy */
268       10,
269       3,
270       -3,
271       2,
272       10,
273       A_WIS,
274       SPE_CURE_SICKNESS,
275       -4 },
276 #if 0 /*JP*/
277     { { "Knight", 0 },
278       { { "Gallant", 0 },
279         { "Esquire", 0 },
280         { "Bachelor", 0 },
281         { "Sergeant", 0 },
282         { "Knight", 0 },
283         { "Banneret", 0 },
284         { "Chevalier", "Chevaliere" },
285         { "Seignieur", "Dame" },
286         { "Paladin", 0 } },
287       "Lugh", "_Brigit", "Manannan Mac Lir", /* Celtic */
288 #else
289     { { "\8bR\8em", 0 },
290       { { "\8c©\8fK\82¢", 0 },
291         { "\95à\95º", 0 },
292         { "\90í\8em", 0 },
293         { "\8bR\95º", 0 },
294         { "\8fd\90í\8em", 0 },
295         { "\8bR\8em", 0 },
296         { "\8fd\8bR\8em", 0 },
297         { "\8cM\8bR\8em", 0 },
298         { "\90¹\8bR\8em", 0 } },
299       "\83\8b\81[\83t", "_\83u\83\8a\83W\83b\83g", "\83}\83i\83\93\83i\83\93\81E\83}\83N\83\8a\81[\83\8b", /* Celtic */
300 #endif
301       "Kni",
302 #if 0 /*JP*/
303       "Camelot Castle",
304       "the Isle of Glass",
305 #else
306       "\83L\83\83\83\81\83\8d\83b\83g\8fé",
307       "\83K\83\89\83X\82Ì\93\87",
308 #endif
309       PM_KNIGHT,
310       NON_PM,
311       PM_PONY,
312       PM_KING_ARTHUR,
313       PM_PAGE,
314       PM_IXOTH,
315       PM_QUASIT,
316       PM_OCHRE_JELLY,
317       S_IMP,
318       S_JELLY,
319       ART_MAGIC_MIRROR_OF_MERLIN,
320       MH_HUMAN | ROLE_MALE | ROLE_FEMALE | ROLE_LAWFUL,
321       /* Str Int Wis Dex Con Cha */
322       { 13, 7, 14, 8, 10, 17 },
323       { 30, 15, 15, 10, 20, 10 },
324       /* Init   Lower  Higher */
325       { 14, 0, 0, 8, 2, 0 }, /* Hit points */
326       { 1, 4, 0, 1, 0, 2 },
327       10, /* Energy */
328       10,
329       8,
330       -2,
331       0,
332       9,
333       A_WIS,
334       SPE_TURN_UNDEAD,
335       -4 },
336 #if 0 /*JP*/
337     { { "Monk", 0 },
338       { { "Candidate", 0 },
339         { "Novice", 0 },
340         { "Initiate", 0 },
341         { "Student of Stones", 0 },
342         { "Student of Waters", 0 },
343         { "Student of Metals", 0 },
344         { "Student of Winds", 0 },
345         { "Student of Fire", 0 },
346         { "Master", 0 } },
347       "Shan Lai Ching", "Chih Sung-tzu", "Huan Ti", /* Chinese */
348 #else
349     { { "\95\90\93¬\89Æ", 0 },
350       { { "\93ü\96å\8aó\96]\8eÒ", 0 },
351         { "\8f\89\90S\8eÒ", 0 },
352         { "\93ü\96å\8eÒ\93`", 0 },
353         { "\93y\82Ì\8fK\82¢\8eè", 0 },
354         { "\90\85\82Ì\8fK\82¢\8eè", 0 },
355         { "\8bà\82Ì\8fK\82¢\8eè", 0 },
356         { "\96Ø\82Ì\8fK\82¢\8eè", 0 },
357         { "\89Î\82Ì\8fK\82¢\8eè", 0 },
358         { "\96Æ\8b\96\8aF\93`", 0 } },
359       "\8eR\97\8b\90¸", "\90Ô\8f¼\8eq", "\89©\92é", /* Chinese */
360 #endif
361       "Mon",
362 #if 0 /*JP*/
363       "the Monastery of Chan-Sune",
364       "the Monastery of the Earth-Lord",
365 #else
366       "\83`\83\83\83\93\81E\83X\81[\8fC\93¹\89@",
367       "\92n\89¤\82Ì\8fC\93¹\89@",
368 #endif
369       PM_MONK,
370       NON_PM,
371       NON_PM,
372       PM_GRAND_MASTER,
373       PM_ABBOT,
374       PM_MASTER_KAEN,
375       PM_EARTH_ELEMENTAL,
376       PM_XORN,
377       S_ELEMENTAL,
378       S_XORN,
379       ART_EYES_OF_THE_OVERWORLD,
380       MH_HUMAN | ROLE_MALE | ROLE_FEMALE | ROLE_LAWFUL | ROLE_NEUTRAL
381           | ROLE_CHAOTIC,
382       /* Str Int Wis Dex Con Cha */
383       { 10, 7, 8, 8, 7, 7 },
384       { 25, 10, 20, 20, 15, 10 },
385       /* Init   Lower  Higher */
386       { 12, 0, 0, 8, 1, 0 }, /* Hit points */
387       { 2, 2, 0, 2, 0, 2 },
388       10, /* Energy */
389       10,
390       8,
391       -2,
392       2,
393       20,
394       A_WIS,
395       SPE_RESTORE_ABILITY,
396       -4 },
397 #if 0 /*JP*/
398     { { "Priest", "Priestess" },
399       { { "Aspirant", 0 },
400         { "Acolyte", 0 },
401         { "Adept", 0 },
402         { "Priest", "Priestess" },
403         { "Curate", 0 },
404         { "Canon", "Canoness" },
405         { "Lama", 0 },
406         { "Patriarch", "Matriarch" },
407         { "High Priest", "High Priestess" } },
408       0, 0, 0, /* deities from a randomly chosen other role will be used */
409 #else
410     { { "\91m\97µ", "\93ò\91m" },
411       { { "\8fC\93¹\8eÒ", "\8fC\93¹\8f\97" },
412         { "\8e\98\8eÒ", 0 },
413         { "\8e\98\8dÕ", 0 },
414         { "\91m\97µ", "\93ò\91m" },
415         { "\8f\95\94C\8ei\8dÕ", 0 },
416         { "\90¹\8eÒ", "\90¹\8f\97" },
417         { "\8ei\8b³", 0 },
418         { "\91å\8ei\8b³", 0 },
419         { "\91å\91m\8fã", 0 } },
420       0, 0, 0, /* deities from a randomly chosen other role will be used */
421 #endif
422       "Pri",
423 #if 0 /*JP*/
424       "the Great Temple",
425       "the Temple of Nalzok",
426 #else
427       "\88Ì\91å\82È\82é\8e\9b\89@",
428       "\83i\83\8b\83]\83N\8e\9b\89@",
429 #endif
430       PM_PRIEST,
431       PM_PRIESTESS,
432       NON_PM,
433       PM_ARCH_PRIEST,
434       PM_ACOLYTE,
435       PM_NALZOK,
436       PM_HUMAN_ZOMBIE,
437       PM_WRAITH,
438       S_ZOMBIE,
439       S_WRAITH,
440       ART_MITRE_OF_HOLINESS,
441       MH_HUMAN | MH_ELF | ROLE_MALE | ROLE_FEMALE | ROLE_LAWFUL | ROLE_NEUTRAL
442           | ROLE_CHAOTIC,
443       /* Str Int Wis Dex Con Cha */
444       { 7, 7, 10, 7, 7, 7 },
445       { 15, 10, 30, 15, 20, 10 },
446       /* Init   Lower  Higher */
447       { 12, 0, 0, 8, 1, 0 }, /* Hit points */
448       { 4, 3, 0, 2, 0, 2 },
449       10, /* Energy */
450       0,
451       3,
452       -2,
453       2,
454       10,
455       A_WIS,
456       SPE_REMOVE_CURSE,
457       -4 },
458     /* Note:  Rogue precedes Ranger so that use of `-R' on the command line
459        retains its traditional meaning. */
460 #if 0 /*JP*/
461     { { "Rogue", 0 },
462       { { "Footpad", 0 },
463         { "Cutpurse", 0 },
464         { "Rogue", 0 },
465         { "Pilferer", 0 },
466         { "Robber", 0 },
467         { "Burglar", 0 },
468         { "Filcher", 0 },
469         { "Magsman", "Magswoman" },
470         { "Thief", 0 } },
471       "Issek", "Mog", "Kos", /* Nehwon */
472 #else
473     { { "\93\90\91¯", 0 },
474       { { "\92Ç\82¢\82Í\82¬", 0 },
475         { "\82Ð\82Á\82½\82­\82è", 0 },
476         { "\83X\83\8a", 0 },
477         { "\82²\82ë\82Â\82«", 0 },
478         { "\82±\82»\82Ç\82ë", 0 },
479         { "\8bó\91\83", 0 },
480         { "\93D\96_", 0 },
481         { "\8b­\93\90", 0 },
482         { "\91å\93D\96_", 0 } },
483       "\83C\83Z\83b\83N", "\83\82\83O", "\83R\83X", /* Nehwon */
484 #endif
485       "Rog",
486 #if 0 /*JP*/
487       "the Thieves' Guild Hall",
488       "the Assassins' Guild Hall",
489 #else
490       "\93\90\91¯\83M\83\8b\83h",
491       "\88Ã\8eE\8eÒ\83M\83\8b\83h",
492 #endif
493       PM_ROGUE,
494       NON_PM,
495       NON_PM,
496       PM_MASTER_OF_THIEVES,
497       PM_THUG,
498       PM_MASTER_ASSASSIN,
499       PM_LEPRECHAUN,
500       PM_GUARDIAN_NAGA,
501       S_NYMPH,
502       S_NAGA,
503       ART_MASTER_KEY_OF_THIEVERY,
504       MH_HUMAN | MH_ORC | ROLE_MALE | ROLE_FEMALE | ROLE_CHAOTIC,
505       /* Str Int Wis Dex Con Cha */
506       { 7, 7, 7, 10, 7, 6 },
507       { 20, 10, 10, 30, 20, 10 },
508       /* Init   Lower  Higher */
509       { 10, 0, 0, 8, 1, 0 }, /* Hit points */
510       { 1, 0, 0, 1, 0, 1 },
511       11, /* Energy */
512       10,
513       8,
514       0,
515       1,
516       9,
517       A_INT,
518       SPE_DETECT_TREASURE,
519       -4 },
520 #if 0 /*JP*/
521     { { "Ranger", 0 },
522       {
523 #if 0 /* OBSOLETE */
524         {"Edhel",   "Elleth"},
525         {"Edhel",   "Elleth"},         /* elf-maid */
526         {"Ohtar",   "Ohtie"},          /* warrior */
527         {"Kano",    "Kanie"},          /* commander (Q.) ['a] educated guess,
528                                           until further research- SAC */
529         {"Arandur"," Aranduriel"}, /* king's servant, minister (Q.) - guess */
530         {"Hir",         "Hiril"},      /* lord, lady (S.) ['ir] */
531         {"Aredhel",     "Arwen"},      /* noble elf, maiden (S.) */
532         {"Ernil",       "Elentariel"}, /* prince (S.), elf-maiden (Q.) */
533         {"Elentar",     "Elentari"},   /* Star-king, -queen (Q.) */
534         "Solonor Thelandira", "Aerdrie Faenya", "Lolth", /* Elven */
535 #endif
536         { "Tenderfoot", 0 },
537         { "Lookout", 0 },
538         { "Trailblazer", 0 },
539         { "Reconnoiterer", "Reconnoiteress" },
540         { "Scout", 0 },
541         { "Arbalester", 0 }, /* One skilled at crossbows */
542         { "Archer", 0 },
543         { "Sharpshooter", 0 },
544         { "Marksman", "Markswoman" } },
545       "Mercury", "_Venus", "Mars", /* Roman/planets */
546 #else
547     { { "\83\8c\83\93\83W\83\83\81[", 0 },
548       { { "\90V\95Ä", 0 },
549         { "\8c©\92£\82è", 0 },
550         { "\90æ\93±", 0 },
551         { "\92ã\8e@", 0 },
552         { "\90Ë\8có", 0 },
553         { "\8b|\95º", 0 }, /* One skilled at crossbows */
554         { "\92\86\8b\89\8b|\95º", 0 },
555         { "\8fã\8b\89\8b|\95º", 0 },
556         { "\8fã\8b\89\8b|\95º", 0 } },
557       "\83}\81[\83L\83\85\83\8a\81[", "_\83r\81[\83i\83X", "\83}\81[\83Y", /* Roman/planets */
558 #endif
559       "Ran",
560 #if 0 /*JP*/
561       "Orion's camp",
562       "the cave of the wumpus",
563 #else
564       "\83I\83\8a\83I\83\93\82Ì\83L\83\83\83\93\83v",
565       "\83\8f\83\93\83p\83X\82Ì\93´\8cA",
566 #endif
567       PM_RANGER,
568       NON_PM,
569       PM_LITTLE_DOG /* Orion & canis major */,
570       PM_ORION,
571       PM_HUNTER,
572       PM_SCORPIUS,
573       PM_FOREST_CENTAUR,
574       PM_SCORPION,
575       S_CENTAUR,
576       S_SPIDER,
577       ART_LONGBOW_OF_DIANA,
578       MH_HUMAN | MH_ELF | MH_GNOME | MH_ORC | ROLE_MALE | ROLE_FEMALE
579           | ROLE_NEUTRAL | ROLE_CHAOTIC,
580       /* Str Int Wis Dex Con Cha */
581       { 13, 13, 13, 9, 13, 7 },
582       { 30, 10, 10, 20, 20, 10 },
583       /* Init   Lower  Higher */
584       { 13, 0, 0, 6, 1, 0 }, /* Hit points */
585       { 1, 0, 0, 1, 0, 1 },
586       12, /* Energy */
587       10,
588       9,
589       2,
590       1,
591       10,
592       A_INT,
593       SPE_INVISIBILITY,
594       -4 },
595 #if 0 /*JP*/
596     { { "Samurai", 0 },
597       { { "Hatamoto", 0 },       /* Banner Knight */
598         { "Ronin", 0 },          /* no allegiance */
599         { "Ninja", "Kunoichi" }, /* secret society */
600         { "Joshu", 0 },          /* heads a castle */
601         { "Ryoshu", 0 },         /* has a territory */
602         { "Kokushu", 0 },        /* heads a province */
603         { "Daimyo", 0 },         /* a samurai lord */
604         { "Kuge", 0 },           /* Noble of the Court */
605         { "Shogun", 0 } },       /* supreme commander, warlord */
606       "_Amaterasu Omikami", "Raijin", "Susanowo", /* Japanese */
607 #else
608     { { "\8e\98", 0 },
609       { { "\8aø\96{", 0 },       /* Banner Knight */
610         { "\98Q\90l", 0 },          /* no allegiance */
611         { "\94E\8eÒ", "\82­\83m\88ê" }, /* secret society */
612         { "\8fé\8eå", 0 },          /* heads a castle */
613         { "\97Ì\8eå", 0 },         /* has a territory */
614         { "\97Ì\8eå", 0 },        /* heads a province */
615         { "\91å\96¼", "\8d\98\8c³" },         /* a samurai lord */
616         { "\8cö\89Æ", 0 },           /* Noble of the Court */
617         { "\8cö\89Æ", "\91å\89\9c" } },       /* supreme commander, warlord */
618       "_\93V\8fÆ\91å\90_", "\97\8b\90_", "\90{\8d²\94V\92j", /* Japanese */
619 #endif
620       "Sam",
621 #if 0 /*JP*/
622       "the Castle of the Taro Clan",
623       "the Shogun's Castle",
624 #else
625       "\91¾\98Y\88ê\91°\82Ì\8fé",
626       "\8f«\8cR\82Ì\8fé",
627 #endif
628       PM_SAMURAI,
629       NON_PM,
630       PM_LITTLE_DOG,
631       PM_LORD_SATO,
632       PM_ROSHI,
633       PM_ASHIKAGA_TAKAUJI,
634       PM_WOLF,
635       PM_STALKER,
636       S_DOG,
637       S_ELEMENTAL,
638       ART_TSURUGI_OF_MURAMASA,
639       MH_HUMAN | ROLE_MALE | ROLE_FEMALE | ROLE_LAWFUL,
640       /* Str Int Wis Dex Con Cha */
641       { 10, 8, 7, 10, 17, 6 },
642       { 30, 10, 8, 30, 14, 8 },
643       /* Init   Lower  Higher */
644       { 13, 0, 0, 8, 1, 0 }, /* Hit points */
645       { 1, 0, 0, 1, 0, 1 },
646       11, /* Energy */
647       10,
648       10,
649       0,
650       0,
651       8,
652       A_INT,
653       SPE_CLAIRVOYANCE,
654       -4 },
655 #if 0 /*JP*/
656     { { "Tourist", 0 },
657       { { "Rambler", 0 },
658         { "Sightseer", 0 },
659         { "Excursionist", 0 },
660         { "Peregrinator", "Peregrinatrix" },
661         { "Traveler", 0 },
662         { "Journeyer", 0 },
663         { "Voyager", 0 },
664         { "Explorer", 0 },
665         { "Adventurer", 0 } },
666       "Blind Io", "_The Lady", "Offler", /* Discworld */
667 #else
668     { { "\8aÏ\8cõ\8bq", 0 },
669       { { "\83v\81[\91¾\98Y", "\83v\81[\8eq" },
670         { "\8aÏ\8cõ\8bq", 0 },
671         { "\8eü\97V\97·\8ds\8eÒ", 0 },
672         { "\95Õ\97ð\8eÒ", 0 },
673         { "\97·\8ds\8eÒ", 0 },
674         { "\97·\90l", 0 },
675         { "\8dq\8aC\8eÒ", 0 },
676         { "\92T\8c\9f\89Æ", 0 },
677         { "\96`\8c¯\8eÒ", 0 } },
678       "\96Ó\96Ú\82Ì\83C\83I", "_\81\83\8f\97\90_\81\84", "\83I\83t\83\89\81[", /* Discworld */
679 #endif
680       "Tou",
681 #if 0 /*JP*/
682       "Ankh-Morpork",
683       "the Thieves' Guild Hall",
684 #else
685       "\83A\83\93\83N\83\82\83\8b\83|\81[\83N",
686       "\93\90\91¯\83M\83\8b\83h",
687 #endif
688       PM_TOURIST,
689       NON_PM,
690       NON_PM,
691       PM_TWOFLOWER,
692       PM_GUIDE,
693       PM_MASTER_OF_THIEVES,
694       PM_GIANT_SPIDER,
695       PM_FOREST_CENTAUR,
696       S_SPIDER,
697       S_CENTAUR,
698       ART_YENDORIAN_EXPRESS_CARD,
699       MH_HUMAN | ROLE_MALE | ROLE_FEMALE | ROLE_NEUTRAL,
700       /* Str Int Wis Dex Con Cha */
701       { 7, 10, 6, 7, 7, 10 },
702       { 15, 10, 10, 15, 30, 20 },
703       /* Init   Lower  Higher */
704       { 8, 0, 0, 8, 0, 0 }, /* Hit points */
705       { 1, 0, 0, 1, 0, 1 },
706       14, /* Energy */
707       0,
708       5,
709       1,
710       2,
711       10,
712       A_INT,
713       SPE_CHARM_MONSTER,
714       -4 },
715 #if 0 /*JP*/
716     { { "Valkyrie", 0 },
717       { { "Stripling", 0 },
718         { "Skirmisher", 0 },
719         { "Fighter", 0 },
720         { "Man-at-arms", "Woman-at-arms" },
721         { "Warrior", 0 },
722         { "Swashbuckler", 0 },
723         { "Hero", "Heroine" },
724         { "Champion", 0 },
725         { "Lord", "Lady" } },
726       "Tyr", "Odin", "Loki", /* Norse */
727 #else
728     { { "\83\8f\83\8b\83L\83\85\81[\83\8c", 0 },
729       { { "\8c©\8fK\82¢", 0 },
730         { "\95à\95º", 0 },
731         { "\90í\8em", 0 },
732         { "\8bR\95º", 0 },
733         { "\90í\93¬\95º", 0 },
734         { "\8dU\8c\82\95º", 0 },
735         { "\89p\97Y", 0 },
736         { "\90æ\93±\8eÒ", 0 },
737         { "\83\8d\81[\83h", "\83\8c\83f\83B" } },
738       "\83`\83\85\81[\83\8b", "\83I\81[\83f\83B\83\93", "\83\8d\83L", /* Norse */
739 #endif
740       "Val",
741 #if 0 /*JP*/
742       "the Shrine of Destiny",
743       "the cave of Surtur",
744 #else
745       "\89^\96½\82Ì\90¹\93°",
746       "\83X\83\8b\83g\82Ì\93´\8cA",
747 #endif
748       PM_VALKYRIE,
749       NON_PM,
750       NON_PM /*PM_WINTER_WOLF_CUB*/,
751       PM_NORN,
752       PM_WARRIOR,
753       PM_LORD_SURTUR,
754       PM_FIRE_ANT,
755       PM_FIRE_GIANT,
756       S_ANT,
757       S_GIANT,
758       ART_ORB_OF_FATE,
759       MH_HUMAN | MH_DWARF | ROLE_FEMALE | ROLE_LAWFUL | ROLE_NEUTRAL,
760       /* Str Int Wis Dex Con Cha */
761       { 10, 7, 7, 7, 10, 7 },
762       { 30, 6, 7, 20, 30, 7 },
763       /* Init   Lower  Higher */
764       { 14, 0, 0, 8, 2, 0 }, /* Hit points */
765       { 1, 0, 0, 1, 0, 1 },
766       10, /* Energy */
767       0,
768       10,
769       -2,
770       0,
771       9,
772       A_WIS,
773       SPE_CONE_OF_COLD,
774       -4 },
775 #if 0 /*JP*/
776     { { "Wizard", 0 },
777       { { "Evoker", 0 },
778         { "Conjurer", 0 },
779         { "Thaumaturge", 0 },
780         { "Magician", 0 },
781         { "Enchanter", "Enchantress" },
782         { "Sorcerer", "Sorceress" },
783         { "Necromancer", 0 },
784         { "Wizard", 0 },
785         { "Mage", 0 } },
786       "Ptah", "Thoth", "Anhur", /* Egyptian */
787 #else
788     { { "\96\82\96@\8eg\82¢", 0 },
789       { { "\8eè\95i\8et", 0 },
790         { "\8aï\8fp\8et", 0 },
791         { "\90è\82¢\8et", 0 },
792         { "\97ì\8a´\8et", 0 },
793         { "\8f¢\8a«\8et", 0 },
794         { "\97d\8fp\8et", 0 },
795         { "\96\82\8fp\8et", 0 },
796         { "\96\82\96@\8eg\82¢", 0 },
797         { "\91å\96\82\96@\8eg\82¢", 0 } },
798       "\83v\83^\83n", "\83g\81[\83g", "\83A\83\93\83t\83\8b", /* Egyptian */
799 #endif
800       "Wiz",
801 #if 0 /*JP*/
802       "the Lonely Tower",
803       "the Tower of Darkness",
804 #else
805       "\8cÇ\8d\82\82Ì\93\83",
806       "\88Ã\8d\95\82Ì\93\83",
807 #endif
808       PM_WIZARD,
809       NON_PM,
810       PM_KITTEN,
811       PM_NEFERET_THE_GREEN,
812       PM_APPRENTICE,
813       PM_DARK_ONE,
814       PM_VAMPIRE_BAT,
815       PM_XORN,
816       S_BAT,
817       S_WRAITH,
818       ART_EYE_OF_THE_AETHIOPICA,
819       MH_HUMAN | MH_ELF | MH_GNOME | MH_ORC | ROLE_MALE | ROLE_FEMALE
820           | ROLE_NEUTRAL | ROLE_CHAOTIC,
821       /* Str Int Wis Dex Con Cha */
822       { 7, 10, 7, 7, 7, 7 },
823       { 10, 30, 10, 20, 20, 10 },
824       /* Init   Lower  Higher */
825       { 10, 0, 0, 8, 1, 0 }, /* Hit points */
826       { 4, 3, 0, 2, 0, 3 },
827       12, /* Energy */
828       0,
829       1,
830       0,
831       3,
832       10,
833       A_INT,
834       SPE_MAGIC_MISSILE,
835       -4 },
836     /* Array terminator */
837     { { 0, 0 } }
838 };
839
840 /* The player's role, created at runtime from initial
841  * choices.  This may be munged in role_init().
842  */
843 struct Role urole = {
844     { "Undefined", 0 },
845     { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
846       { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } },
847     "L", "N", "C",
848     "Xxx", "home", "locate",
849     NON_PM, NON_PM, NON_PM, NON_PM, NON_PM, NON_PM, NON_PM, NON_PM,
850     0, 0, 0, 0,
851     /* Str Int Wis Dex Con Cha */
852     { 7, 7, 7, 7, 7, 7 },
853     { 20, 15, 15, 20, 20, 10 },
854     /* Init   Lower  Higher */
855     { 10, 0, 0, 8, 1, 0 }, /* Hit points */
856     { 2, 0, 0, 2, 0, 3 },
857     14, /* Energy */
858      0,
859     10,
860      0,
861      0,
862      4,
863     A_INT,
864      0,
865     -3
866 };
867
868 /* Table of all races */
869 const struct Race races[] = {
870     {
871 #if 0 /*JP*/
872         "human",
873         "human",
874         "humanity",
875 #else
876         "\90l\8aÔ",
877         "\90l\8aÔ\82Ì",
878         "\90l\8aÔ",
879 #endif
880         "Hum",
881 #if 0 /*JP*/
882         { "man", "woman" },
883 #else
884         { "\92j", "\8f\97" },
885 #endif
886         PM_HUMAN,
887         NON_PM,
888         PM_HUMAN_MUMMY,
889         PM_HUMAN_ZOMBIE,
890         MH_HUMAN | ROLE_MALE | ROLE_FEMALE | ROLE_LAWFUL | ROLE_NEUTRAL
891             | ROLE_CHAOTIC,
892         MH_HUMAN,
893         0,
894         MH_GNOME | MH_ORC,
895         /*    Str     Int Wis Dex Con Cha */
896         { 3, 3, 3, 3, 3, 3 },
897         { STR18(100), 18, 18, 18, 18, 18 },
898         /* Init   Lower  Higher */
899         { 2, 0, 0, 2, 1, 0 }, /* Hit points */
900         { 1, 0, 2, 0, 2, 0 }  /* Energy */
901     },
902     {
903 #if 0 /*JP*/
904         "elf",
905         "elven",
906         "elvenkind",
907 #else
908         "\83G\83\8b\83t",
909         "\83G\83\8b\83t\82Ì",
910         "\83G\83\8b\83t",
911 #endif
912         "Elf",
913         { 0, 0 },
914         PM_ELF,
915         NON_PM,
916         PM_ELF_MUMMY,
917         PM_ELF_ZOMBIE,
918         MH_ELF | ROLE_MALE | ROLE_FEMALE | ROLE_CHAOTIC,
919         MH_ELF,
920         MH_ELF,
921         MH_ORC,
922         /*  Str    Int Wis Dex Con Cha */
923         { 3, 3, 3, 3, 3, 3 },
924         { 18, 20, 20, 18, 16, 18 },
925         /* Init   Lower  Higher */
926         { 1, 0, 0, 1, 1, 0 }, /* Hit points */
927         { 2, 0, 3, 0, 3, 0 }  /* Energy */
928     },
929     {
930 #if 0 /*JP*/
931         "dwarf",
932         "dwarven",
933         "dwarvenkind",
934 #else
935         "\83h\83\8f\81[\83t",
936         "\83h\83\8f\81[\83t\82Ì",
937         "\83h\83\8f\81[\83t",
938 #endif
939         "Dwa",
940         { 0, 0 },
941         PM_DWARF,
942         NON_PM,
943         PM_DWARF_MUMMY,
944         PM_DWARF_ZOMBIE,
945         MH_DWARF | ROLE_MALE | ROLE_FEMALE | ROLE_LAWFUL,
946         MH_DWARF,
947         MH_DWARF | MH_GNOME,
948         MH_ORC,
949         /*    Str     Int Wis Dex Con Cha */
950         { 3, 3, 3, 3, 3, 3 },
951         { STR18(100), 16, 16, 20, 20, 16 },
952         /* Init   Lower  Higher */
953         { 4, 0, 0, 3, 2, 0 }, /* Hit points */
954         { 0, 0, 0, 0, 0, 0 }  /* Energy */
955     },
956     {
957 #if 0 /*JP*/
958         "gnome",
959         "gnomish",
960         "gnomehood",
961 #else
962         "\83m\81[\83\80",
963         "\83m\81[\83\80\82Ì",
964         "\83m\81[\83\80",
965 #endif
966         "Gno",
967         { 0, 0 },
968         PM_GNOME,
969         NON_PM,
970         PM_GNOME_MUMMY,
971         PM_GNOME_ZOMBIE,
972         MH_GNOME | ROLE_MALE | ROLE_FEMALE | ROLE_NEUTRAL,
973         MH_GNOME,
974         MH_DWARF | MH_GNOME,
975         MH_HUMAN,
976         /*  Str    Int Wis Dex Con Cha */
977         { 3, 3, 3, 3, 3, 3 },
978         { STR18(50), 19, 18, 18, 18, 18 },
979         /* Init   Lower  Higher */
980         { 1, 0, 0, 1, 0, 0 }, /* Hit points */
981         { 2, 0, 2, 0, 2, 0 }  /* Energy */
982     },
983     {
984 #if 0 /*JP*/
985         "orc",
986         "orcish",
987         "orcdom",
988 #else
989         "\83I\81[\83N",
990         "\83I\81[\83N\82Ì",
991         "\83I\81[\83N",
992 #endif
993         "Orc",
994         { 0, 0 },
995         PM_ORC,
996         NON_PM,
997         PM_ORC_MUMMY,
998         PM_ORC_ZOMBIE,
999         MH_ORC | ROLE_MALE | ROLE_FEMALE | ROLE_CHAOTIC,
1000         MH_ORC,
1001         0,
1002         MH_HUMAN | MH_ELF | MH_DWARF,
1003         /*  Str    Int Wis Dex Con Cha */
1004         { 3, 3, 3, 3, 3, 3 },
1005         { STR18(50), 16, 16, 18, 18, 16 },
1006         /* Init   Lower  Higher */
1007         { 1, 0, 0, 1, 0, 0 }, /* Hit points */
1008         { 1, 0, 1, 0, 1, 0 }  /* Energy */
1009     },
1010     /* Array terminator */
1011     { 0, 0, 0, 0 }
1012 };
1013
1014 /* The player's race, created at runtime from initial
1015  * choices.  This may be munged in role_init().
1016  */
1017 struct Race urace = {
1018     "something",
1019     "undefined",
1020     "something",
1021     "Xxx",
1022     { 0, 0 },
1023     NON_PM,
1024     NON_PM,
1025     NON_PM,
1026     NON_PM,
1027     0,
1028     0,
1029     0,
1030     0,
1031     /*    Str     Int Wis Dex Con Cha */
1032     { 3, 3, 3, 3, 3, 3 },
1033     { STR18(100), 18, 18, 18, 18, 18 },
1034     /* Init   Lower  Higher */
1035     { 2, 0, 0, 2, 1, 0 }, /* Hit points */
1036     { 1, 0, 2, 0, 2, 0 }  /* Energy */
1037 };
1038
1039 /* Table of all genders */
1040 /*JP:
1041 - steed.c kick_steed() He[] \82É\92l\82ª\83R\83s\81[\82³\82ê\82é\82Ì\82Å\92·\82³\82ð\95Ï\82¦\82½\82Æ\82«\82É\82Í
1042   \8aY\93\96\95\94\82à\97v\8fC\90³\81B
1043 */
1044 const struct Gender genders[] = {
1045 #if 0 /*JP*/
1046     { "male", "he", "him", "his", "Mal", ROLE_MALE },
1047     { "female", "she", "her", "her", "Fem", ROLE_FEMALE },
1048     { "neuter", "it", "it", "its", "Ntr", ROLE_NEUTER }
1049 #else
1050     { "\92j\90«", "\94Þ", "\94Þ", "\94Þ\82Ì", "Mal", ROLE_MALE },
1051     { "\8f\97\90«", "\94Þ\8f\97", "\94Þ\8f\97", "\94Þ\8f\97\82Ì", "Fem", ROLE_FEMALE },
1052     { "\92\86\90«", "\82»\82ê", "\82»\82ê", "\82»\82Ì", "Ntr", ROLE_NEUTER }
1053 #endif
1054 };
1055
1056 /* Table of all alignments */
1057 const struct Align aligns[] = {
1058 #if 0 /*JP*/
1059     { "law", "lawful", "Law", ROLE_LAWFUL, A_LAWFUL },
1060     { "balance", "neutral", "Neu", ROLE_NEUTRAL, A_NEUTRAL },
1061     { "chaos", "chaotic", "Cha", ROLE_CHAOTIC, A_CHAOTIC },
1062     { "evil", "unaligned", "Una", 0, A_NONE }
1063 #else
1064     { "\92\81\8f\98", "\92\81\8f\98\82Ì", "Law", ROLE_LAWFUL, A_LAWFUL },
1065     { "\92\86\97§", "\92\86\97§\82Ì", "Neu", ROLE_NEUTRAL, A_NEUTRAL },
1066     { "\8d¬\93×", "\8d¬\93×\82Ì", "Cha", ROLE_CHAOTIC, A_CHAOTIC },
1067     { "\96³\90S", "\96³\90S\82Ì", "Una", 0, A_NONE }
1068 #endif
1069 };
1070
1071 /* Filters */
1072 static struct {
1073     boolean roles[SIZE(roles)];
1074     short mask;
1075 } rfilter;
1076
1077 STATIC_DCL int NDECL(randrole_filtered);
1078 STATIC_DCL char *FDECL(promptsep, (char *, int));
1079 STATIC_DCL int FDECL(role_gendercount, (int));
1080 STATIC_DCL int FDECL(race_alignmentcount, (int));
1081
1082 /* used by str2XXX() */
1083 /*JP
1084 static char NEARDATA randomstr[] = "random";
1085 */
1086 static char NEARDATA randomstr[] = "\83\89\83\93\83_\83\80";
1087
1088 boolean
1089 validrole(rolenum)
1090 int rolenum;
1091 {
1092     return (boolean) (rolenum >= 0 && rolenum < SIZE(roles) - 1);
1093 }
1094
1095 int
1096 randrole()
1097 {
1098     return rn2(SIZE(roles) - 1);
1099 }
1100
1101 STATIC_OVL int
1102 randrole_filtered()
1103 {
1104     int i, n = 0, set[SIZE(roles)];
1105
1106     /* this doesn't rule out impossible combinations but attempts to
1107        honor all the filter masks */
1108     for (i = 0; i < SIZE(roles); ++i)
1109         if (ok_role(i, ROLE_NONE, ROLE_NONE, ROLE_NONE)
1110             && ok_race(i, ROLE_RANDOM, ROLE_NONE, ROLE_NONE)
1111             && ok_gend(i, ROLE_NONE, ROLE_RANDOM, ROLE_NONE)
1112             && ok_align(i, ROLE_NONE, ROLE_NONE, ROLE_RANDOM))
1113             set[n++] = i;
1114     return n ? set[rn2(n)] : randrole();
1115 }
1116
1117 int
1118 str2role(str)
1119 const char *str;
1120 {
1121     int i, len;
1122
1123     /* Is str valid? */
1124     if (!str || !str[0])
1125         return ROLE_NONE;
1126
1127     /* Match as much of str as is provided */
1128     len = strlen(str);
1129     for (i = 0; roles[i].name.m; i++) {
1130         /* Does it match the male name? */
1131         if (!strncmpi(str, roles[i].name.m, len))
1132             return i;
1133         /* Or the female name? */
1134         if (roles[i].name.f && !strncmpi(str, roles[i].name.f, len))
1135             return i;
1136         /* Or the filecode? */
1137         if (!strcmpi(str, roles[i].filecode))
1138             return i;
1139     }
1140
1141     if ((len == 1 && (*str == '*' || *str == '@'))
1142         || !strncmpi(str, randomstr, len))
1143         return ROLE_RANDOM;
1144
1145     /* Couldn't find anything appropriate */
1146     return ROLE_NONE;
1147 }
1148
1149 boolean
1150 validrace(rolenum, racenum)
1151 int rolenum, racenum;
1152 {
1153     /* Assumes validrole */
1154     return (boolean) (racenum >= 0 && racenum < SIZE(races) - 1
1155                       && (roles[rolenum].allow & races[racenum].allow
1156                           & ROLE_RACEMASK));
1157 }
1158
1159 int
1160 randrace(rolenum)
1161 int rolenum;
1162 {
1163     int i, n = 0;
1164
1165     /* Count the number of valid races */
1166     for (i = 0; races[i].noun; i++)
1167         if (roles[rolenum].allow & races[i].allow & ROLE_RACEMASK)
1168             n++;
1169
1170     /* Pick a random race */
1171     /* Use a factor of 100 in case of bad random number generators */
1172     if (n)
1173         n = rn2(n * 100) / 100;
1174     for (i = 0; races[i].noun; i++)
1175         if (roles[rolenum].allow & races[i].allow & ROLE_RACEMASK) {
1176             if (n)
1177                 n--;
1178             else
1179                 return i;
1180         }
1181
1182     /* This role has no permitted races? */
1183     return rn2(SIZE(races) - 1);
1184 }
1185
1186 int
1187 str2race(str)
1188 const char *str;
1189 {
1190     int i, len;
1191
1192     /* Is str valid? */
1193     if (!str || !str[0])
1194         return ROLE_NONE;
1195
1196     /* Match as much of str as is provided */
1197     len = strlen(str);
1198     for (i = 0; races[i].noun; i++) {
1199         /* Does it match the noun? */
1200         if (!strncmpi(str, races[i].noun, len))
1201             return i;
1202         /* Or the filecode? */
1203         if (!strcmpi(str, races[i].filecode))
1204             return i;
1205     }
1206
1207     if ((len == 1 && (*str == '*' || *str == '@'))
1208         || !strncmpi(str, randomstr, len))
1209         return ROLE_RANDOM;
1210
1211     /* Couldn't find anything appropriate */
1212     return ROLE_NONE;
1213 }
1214
1215 boolean
1216 validgend(rolenum, racenum, gendnum)
1217 int rolenum, racenum, gendnum;
1218 {
1219     /* Assumes validrole and validrace */
1220     return (boolean) (gendnum >= 0 && gendnum < ROLE_GENDERS
1221                       && (roles[rolenum].allow & races[racenum].allow
1222                           & genders[gendnum].allow & ROLE_GENDMASK));
1223 }
1224
1225 int
1226 randgend(rolenum, racenum)
1227 int rolenum, racenum;
1228 {
1229     int i, n = 0;
1230
1231     /* Count the number of valid genders */
1232     for (i = 0; i < ROLE_GENDERS; i++)
1233         if (roles[rolenum].allow & races[racenum].allow & genders[i].allow
1234             & ROLE_GENDMASK)
1235             n++;
1236
1237     /* Pick a random gender */
1238     if (n)
1239         n = rn2(n);
1240     for (i = 0; i < ROLE_GENDERS; i++)
1241         if (roles[rolenum].allow & races[racenum].allow & genders[i].allow
1242             & ROLE_GENDMASK) {
1243             if (n)
1244                 n--;
1245             else
1246                 return i;
1247         }
1248
1249     /* This role/race has no permitted genders? */
1250     return rn2(ROLE_GENDERS);
1251 }
1252
1253 int
1254 str2gend(str)
1255 const char *str;
1256 {
1257     int i, len;
1258
1259     /* Is str valid? */
1260     if (!str || !str[0])
1261         return ROLE_NONE;
1262
1263     /* Match as much of str as is provided */
1264     len = strlen(str);
1265     for (i = 0; i < ROLE_GENDERS; i++) {
1266         /* Does it match the adjective? */
1267         if (!strncmpi(str, genders[i].adj, len))
1268             return i;
1269         /* Or the filecode? */
1270         if (!strcmpi(str, genders[i].filecode))
1271             return i;
1272     }
1273     if ((len == 1 && (*str == '*' || *str == '@'))
1274         || !strncmpi(str, randomstr, len))
1275         return ROLE_RANDOM;
1276
1277     /* Couldn't find anything appropriate */
1278     return ROLE_NONE;
1279 }
1280
1281 boolean
1282 validalign(rolenum, racenum, alignnum)
1283 int rolenum, racenum, alignnum;
1284 {
1285     /* Assumes validrole and validrace */
1286     return (boolean) (alignnum >= 0 && alignnum < ROLE_ALIGNS
1287                       && (roles[rolenum].allow & races[racenum].allow
1288                           & aligns[alignnum].allow & ROLE_ALIGNMASK));
1289 }
1290
1291 int
1292 randalign(rolenum, racenum)
1293 int rolenum, racenum;
1294 {
1295     int i, n = 0;
1296
1297     /* Count the number of valid alignments */
1298     for (i = 0; i < ROLE_ALIGNS; i++)
1299         if (roles[rolenum].allow & races[racenum].allow & aligns[i].allow
1300             & ROLE_ALIGNMASK)
1301             n++;
1302
1303     /* Pick a random alignment */
1304     if (n)
1305         n = rn2(n);
1306     for (i = 0; i < ROLE_ALIGNS; i++)
1307         if (roles[rolenum].allow & races[racenum].allow & aligns[i].allow
1308             & ROLE_ALIGNMASK) {
1309             if (n)
1310                 n--;
1311             else
1312                 return i;
1313         }
1314
1315     /* This role/race has no permitted alignments? */
1316     return rn2(ROLE_ALIGNS);
1317 }
1318
1319 int
1320 str2align(str)
1321 const char *str;
1322 {
1323     int i, len;
1324
1325     /* Is str valid? */
1326     if (!str || !str[0])
1327         return ROLE_NONE;
1328
1329     /* Match as much of str as is provided */
1330     len = strlen(str);
1331     for (i = 0; i < ROLE_ALIGNS; i++) {
1332         /* Does it match the adjective? */
1333         if (!strncmpi(str, aligns[i].adj, len))
1334             return i;
1335         /* Or the filecode? */
1336         if (!strcmpi(str, aligns[i].filecode))
1337             return i;
1338     }
1339     if ((len == 1 && (*str == '*' || *str == '@'))
1340         || !strncmpi(str, randomstr, len))
1341         return ROLE_RANDOM;
1342
1343     /* Couldn't find anything appropriate */
1344     return ROLE_NONE;
1345 }
1346
1347 /* is rolenum compatible with any racenum/gendnum/alignnum constraints? */
1348 boolean
1349 ok_role(rolenum, racenum, gendnum, alignnum)
1350 int rolenum, racenum, gendnum, alignnum;
1351 {
1352     int i;
1353     short allow;
1354
1355     if (rolenum >= 0 && rolenum < SIZE(roles) - 1) {
1356         if (rfilter.roles[rolenum])
1357             return FALSE;
1358         allow = roles[rolenum].allow;
1359         if (racenum >= 0 && racenum < SIZE(races) - 1
1360             && !(allow & races[racenum].allow & ROLE_RACEMASK))
1361             return FALSE;
1362         if (gendnum >= 0 && gendnum < ROLE_GENDERS
1363             && !(allow & genders[gendnum].allow & ROLE_GENDMASK))
1364             return FALSE;
1365         if (alignnum >= 0 && alignnum < ROLE_ALIGNS
1366             && !(allow & aligns[alignnum].allow & ROLE_ALIGNMASK))
1367             return FALSE;
1368         return TRUE;
1369     } else {
1370         /* random; check whether any selection is possible */
1371         for (i = 0; i < SIZE(roles) - 1; i++) {
1372             if (rfilter.roles[i])
1373                 continue;
1374             allow = roles[i].allow;
1375             if (racenum >= 0 && racenum < SIZE(races) - 1
1376                 && !(allow & races[racenum].allow & ROLE_RACEMASK))
1377                 continue;
1378             if (gendnum >= 0 && gendnum < ROLE_GENDERS
1379                 && !(allow & genders[gendnum].allow & ROLE_GENDMASK))
1380                 continue;
1381             if (alignnum >= 0 && alignnum < ROLE_ALIGNS
1382                 && !(allow & aligns[alignnum].allow & ROLE_ALIGNMASK))
1383                 continue;
1384             return TRUE;
1385         }
1386         return FALSE;
1387     }
1388 }
1389
1390 /* pick a random role subject to any racenum/gendnum/alignnum constraints */
1391 /* If pickhow == PICK_RIGID a role is returned only if there is  */
1392 /* a single possibility */
1393 int
1394 pick_role(racenum, gendnum, alignnum, pickhow)
1395 int racenum, gendnum, alignnum, pickhow;
1396 {
1397     int i;
1398     int roles_ok = 0, set[SIZE(roles)];
1399
1400     for (i = 0; i < SIZE(roles) - 1; i++) {
1401         if (ok_role(i, racenum, gendnum, alignnum)
1402             && ok_race(i, (racenum >= 0) ? racenum : ROLE_RANDOM,
1403                        gendnum, alignnum)
1404             && ok_gend(i, racenum,
1405                        (gendnum >= 0) ? gendnum : ROLE_RANDOM, alignnum)
1406             && ok_race(i, racenum,
1407                        gendnum, (alignnum >= 0) ? alignnum : ROLE_RANDOM))
1408             set[roles_ok++] = i;
1409     }
1410     if (roles_ok == 0 || (roles_ok > 1 && pickhow == PICK_RIGID))
1411         return ROLE_NONE;
1412     return set[rn2(roles_ok)];
1413 }
1414
1415 /* is racenum compatible with any rolenum/gendnum/alignnum constraints? */
1416 boolean
1417 ok_race(rolenum, racenum, gendnum, alignnum)
1418 int rolenum, racenum, gendnum, alignnum;
1419 {
1420     int i;
1421     short allow;
1422
1423     if (racenum >= 0 && racenum < SIZE(races) - 1) {
1424         if (rfilter.mask & races[racenum].selfmask)
1425             return FALSE;
1426         allow = races[racenum].allow;
1427         if (rolenum >= 0 && rolenum < SIZE(roles) - 1
1428             && !(allow & roles[rolenum].allow & ROLE_RACEMASK))
1429             return FALSE;
1430         if (gendnum >= 0 && gendnum < ROLE_GENDERS
1431             && !(allow & genders[gendnum].allow & ROLE_GENDMASK))
1432             return FALSE;
1433         if (alignnum >= 0 && alignnum < ROLE_ALIGNS
1434             && !(allow & aligns[alignnum].allow & ROLE_ALIGNMASK))
1435             return FALSE;
1436         return TRUE;
1437     } else {
1438         /* random; check whether any selection is possible */
1439         for (i = 0; i < SIZE(races) - 1; i++) {
1440             if (rfilter.mask & races[i].selfmask)
1441                 continue;
1442             allow = races[i].allow;
1443             if (rolenum >= 0 && rolenum < SIZE(roles) - 1
1444                 && !(allow & roles[rolenum].allow & ROLE_RACEMASK))
1445                 continue;
1446             if (gendnum >= 0 && gendnum < ROLE_GENDERS
1447                 && !(allow & genders[gendnum].allow & ROLE_GENDMASK))
1448                 continue;
1449             if (alignnum >= 0 && alignnum < ROLE_ALIGNS
1450                 && !(allow & aligns[alignnum].allow & ROLE_ALIGNMASK))
1451                 continue;
1452             return TRUE;
1453         }
1454         return FALSE;
1455     }
1456 }
1457
1458 /* Pick a random race subject to any rolenum/gendnum/alignnum constraints.
1459    If pickhow == PICK_RIGID a race is returned only if there is
1460    a single possibility. */
1461 int
1462 pick_race(rolenum, gendnum, alignnum, pickhow)
1463 int rolenum, gendnum, alignnum, pickhow;
1464 {
1465     int i;
1466     int races_ok = 0;
1467
1468     for (i = 0; i < SIZE(races) - 1; i++) {
1469         if (ok_race(rolenum, i, gendnum, alignnum))
1470             races_ok++;
1471     }
1472     if (races_ok == 0 || (races_ok > 1 && pickhow == PICK_RIGID))
1473         return ROLE_NONE;
1474     races_ok = rn2(races_ok);
1475     for (i = 0; i < SIZE(races) - 1; i++) {
1476         if (ok_race(rolenum, i, gendnum, alignnum)) {
1477             if (races_ok == 0)
1478                 return i;
1479             else
1480                 races_ok--;
1481         }
1482     }
1483     return ROLE_NONE;
1484 }
1485
1486 /* is gendnum compatible with any rolenum/racenum/alignnum constraints? */
1487 /* gender and alignment are not comparable (and also not constrainable) */
1488 boolean
1489 ok_gend(rolenum, racenum, gendnum, alignnum)
1490 int rolenum, racenum, gendnum;
1491 int alignnum UNUSED;
1492 {
1493     int i;
1494     short allow;
1495
1496     if (gendnum >= 0 && gendnum < ROLE_GENDERS) {
1497         if (rfilter.mask & genders[gendnum].allow)
1498             return FALSE;
1499         allow = genders[gendnum].allow;
1500         if (rolenum >= 0 && rolenum < SIZE(roles) - 1
1501             && !(allow & roles[rolenum].allow & ROLE_GENDMASK))
1502             return FALSE;
1503         if (racenum >= 0 && racenum < SIZE(races) - 1
1504             && !(allow & races[racenum].allow & ROLE_GENDMASK))
1505             return FALSE;
1506         return TRUE;
1507     } else {
1508         /* random; check whether any selection is possible */
1509         for (i = 0; i < ROLE_GENDERS; i++) {
1510             if (rfilter.mask & genders[i].allow)
1511                 continue;
1512             allow = genders[i].allow;
1513             if (rolenum >= 0 && rolenum < SIZE(roles) - 1
1514                 && !(allow & roles[rolenum].allow & ROLE_GENDMASK))
1515                 continue;
1516             if (racenum >= 0 && racenum < SIZE(races) - 1
1517                 && !(allow & races[racenum].allow & ROLE_GENDMASK))
1518                 continue;
1519             return TRUE;
1520         }
1521         return FALSE;
1522     }
1523 }
1524
1525 /* pick a random gender subject to any rolenum/racenum/alignnum constraints */
1526 /* gender and alignment are not comparable (and also not constrainable) */
1527 /* If pickhow == PICK_RIGID a gender is returned only if there is  */
1528 /* a single possibility */
1529 int
1530 pick_gend(rolenum, racenum, alignnum, pickhow)
1531 int rolenum, racenum, alignnum, pickhow;
1532 {
1533     int i;
1534     int gends_ok = 0;
1535
1536     for (i = 0; i < ROLE_GENDERS; i++) {
1537         if (ok_gend(rolenum, racenum, i, alignnum))
1538             gends_ok++;
1539     }
1540     if (gends_ok == 0 || (gends_ok > 1 && pickhow == PICK_RIGID))
1541         return ROLE_NONE;
1542     gends_ok = rn2(gends_ok);
1543     for (i = 0; i < ROLE_GENDERS; i++) {
1544         if (ok_gend(rolenum, racenum, i, alignnum)) {
1545             if (gends_ok == 0)
1546                 return i;
1547             else
1548                 gends_ok--;
1549         }
1550     }
1551     return ROLE_NONE;
1552 }
1553
1554 /* is alignnum compatible with any rolenum/racenum/gendnum constraints? */
1555 /* alignment and gender are not comparable (and also not constrainable) */
1556 boolean
1557 ok_align(rolenum, racenum, gendnum, alignnum)
1558 int rolenum, racenum;
1559 int gendnum UNUSED;
1560 int alignnum;
1561 {
1562     int i;
1563     short allow;
1564
1565     if (alignnum >= 0 && alignnum < ROLE_ALIGNS) {
1566         if (rfilter.mask & aligns[alignnum].allow)
1567             return FALSE;
1568         allow = aligns[alignnum].allow;
1569         if (rolenum >= 0 && rolenum < SIZE(roles) - 1
1570             && !(allow & roles[rolenum].allow & ROLE_ALIGNMASK))
1571             return FALSE;
1572         if (racenum >= 0 && racenum < SIZE(races) - 1
1573             && !(allow & races[racenum].allow & ROLE_ALIGNMASK))
1574             return FALSE;
1575         return TRUE;
1576     } else {
1577         /* random; check whether any selection is possible */
1578         for (i = 0; i < ROLE_ALIGNS; i++) {
1579             if (rfilter.mask & aligns[i].allow)
1580                 return FALSE;
1581             allow = aligns[i].allow;
1582             if (rolenum >= 0 && rolenum < SIZE(roles) - 1
1583                 && !(allow & roles[rolenum].allow & ROLE_ALIGNMASK))
1584                 continue;
1585             if (racenum >= 0 && racenum < SIZE(races) - 1
1586                 && !(allow & races[racenum].allow & ROLE_ALIGNMASK))
1587                 continue;
1588             return TRUE;
1589         }
1590         return FALSE;
1591     }
1592 }
1593
1594 /* Pick a random alignment subject to any rolenum/racenum/gendnum constraints;
1595    alignment and gender are not comparable (and also not constrainable).
1596    If pickhow == PICK_RIGID an alignment is returned only if there is
1597    a single possibility. */
1598 int
1599 pick_align(rolenum, racenum, gendnum, pickhow)
1600 int rolenum, racenum, gendnum, pickhow;
1601 {
1602     int i;
1603     int aligns_ok = 0;
1604
1605     for (i = 0; i < ROLE_ALIGNS; i++) {
1606         if (ok_align(rolenum, racenum, gendnum, i))
1607             aligns_ok++;
1608     }
1609     if (aligns_ok == 0 || (aligns_ok > 1 && pickhow == PICK_RIGID))
1610         return ROLE_NONE;
1611     aligns_ok = rn2(aligns_ok);
1612     for (i = 0; i < ROLE_ALIGNS; i++) {
1613         if (ok_align(rolenum, racenum, gendnum, i)) {
1614             if (aligns_ok == 0)
1615                 return i;
1616             else
1617                 aligns_ok--;
1618         }
1619     }
1620     return ROLE_NONE;
1621 }
1622
1623 void
1624 rigid_role_checks()
1625 {
1626     int tmp;
1627
1628     /* Some roles are limited to a single race, alignment, or gender and
1629      * calling this routine prior to XXX_player_selection() will help
1630      * prevent an extraneous prompt that actually doesn't allow
1631      * you to choose anything further. Note the use of PICK_RIGID which
1632      * causes the pick_XX() routine to return a value only if there is one
1633      * single possible selection, otherwise it returns ROLE_NONE.
1634      *
1635      */
1636     if (flags.initrole == ROLE_RANDOM) {
1637         /* If the role was explicitly specified as ROLE_RANDOM
1638          * via -uXXXX-@ or OPTIONS=role:random then choose the role
1639          * in here to narrow down later choices.
1640          */
1641         flags.initrole = pick_role(flags.initrace, flags.initgend,
1642                                    flags.initalign, PICK_RANDOM);
1643         if (flags.initrole < 0)
1644             flags.initrole = randrole_filtered();
1645     }
1646     if (flags.initrace == ROLE_RANDOM
1647         && (tmp = pick_race(flags.initrole, flags.initgend,
1648                             flags.initalign, PICK_RANDOM)) != ROLE_NONE)
1649         flags.initrace = tmp;
1650     if (flags.initalign == ROLE_RANDOM
1651         && (tmp = pick_align(flags.initrole, flags.initrace,
1652                              flags.initgend, PICK_RANDOM)) != ROLE_NONE)
1653         flags.initalign = tmp;
1654     if (flags.initgend == ROLE_RANDOM
1655         && (tmp = pick_gend(flags.initrole, flags.initrace,
1656                             flags.initalign, PICK_RANDOM)) != ROLE_NONE)
1657         flags.initgend = tmp;
1658
1659     if (flags.initrole != ROLE_NONE) {
1660         if (flags.initrace == ROLE_NONE)
1661             flags.initrace = pick_race(flags.initrole, flags.initgend,
1662                                        flags.initalign, PICK_RIGID);
1663         if (flags.initalign == ROLE_NONE)
1664             flags.initalign = pick_align(flags.initrole, flags.initrace,
1665                                          flags.initgend, PICK_RIGID);
1666         if (flags.initgend == ROLE_NONE)
1667             flags.initgend = pick_gend(flags.initrole, flags.initrace,
1668                                        flags.initalign, PICK_RIGID);
1669     }
1670 }
1671
1672 boolean
1673 setrolefilter(bufp)
1674 const char *bufp;
1675 {
1676     int i;
1677     boolean reslt = TRUE;
1678
1679     if ((i = str2role(bufp)) != ROLE_NONE && i != ROLE_RANDOM)
1680         rfilter.roles[i] = TRUE;
1681     else if ((i = str2race(bufp)) != ROLE_NONE && i != ROLE_RANDOM)
1682         rfilter.mask |= races[i].selfmask;
1683     else if ((i = str2gend(bufp)) != ROLE_NONE && i != ROLE_RANDOM)
1684         rfilter.mask |= genders[i].allow;
1685     else if ((i = str2align(bufp)) != ROLE_NONE && i != ROLE_RANDOM)
1686         rfilter.mask |= aligns[i].allow;
1687     else
1688         reslt = FALSE;
1689     return reslt;
1690 }
1691
1692 boolean
1693 gotrolefilter()
1694 {
1695     int i;
1696
1697     if (rfilter.mask)
1698         return TRUE;
1699     for (i = 0; i < SIZE(roles); ++i)
1700         if (rfilter.roles[i])
1701             return TRUE;
1702     return FALSE;
1703 }
1704
1705 void
1706 clearrolefilter()
1707 {
1708     int i;
1709
1710     for (i = 0; i < SIZE(roles); ++i)
1711         rfilter.roles[i] = FALSE;
1712     rfilter.mask = 0;
1713 }
1714
1715 #define BP_ALIGN 0
1716 #define BP_GEND 1
1717 #define BP_RACE 2
1718 #define BP_ROLE 3
1719 #define NUM_BP 4
1720
1721 STATIC_VAR char pa[NUM_BP], post_attribs;
1722
1723 STATIC_OVL char *
1724 promptsep(buf, num_post_attribs)
1725 char *buf;
1726 int num_post_attribs;
1727 {
1728 #if 0 /*JP*/
1729     const char *conjuct = "and ";
1730
1731     if (num_post_attribs > 1 && post_attribs < num_post_attribs
1732         && post_attribs > 1)
1733         Strcat(buf, ",");
1734     Strcat(buf, " ");
1735     --post_attribs;
1736     if (!post_attribs && num_post_attribs > 1)
1737         Strcat(buf, conjuct);
1738 #else
1739     /*JP: \93ú\96{\8cê\82Å\82Í "A, B, and C" \82Æ\82¢\82¤\8f\88\97\9d\82Í\95s\97v */
1740     if(num_post_attribs > post_attribs){
1741         Strcat(buf, "\81C");
1742     }
1743     --post_attribs;
1744 #endif
1745     return buf;
1746 }
1747
1748 STATIC_OVL int
1749 role_gendercount(rolenum)
1750 int rolenum;
1751 {
1752     int gendcount = 0;
1753
1754     if (validrole(rolenum)) {
1755         if (roles[rolenum].allow & ROLE_MALE)
1756             ++gendcount;
1757         if (roles[rolenum].allow & ROLE_FEMALE)
1758             ++gendcount;
1759         if (roles[rolenum].allow & ROLE_NEUTER)
1760             ++gendcount;
1761     }
1762     return gendcount;
1763 }
1764
1765 STATIC_OVL int
1766 race_alignmentcount(racenum)
1767 int racenum;
1768 {
1769     int aligncount = 0;
1770
1771     if (racenum != ROLE_NONE && racenum != ROLE_RANDOM) {
1772         if (races[racenum].allow & ROLE_CHAOTIC)
1773             ++aligncount;
1774         if (races[racenum].allow & ROLE_LAWFUL)
1775             ++aligncount;
1776         if (races[racenum].allow & ROLE_NEUTRAL)
1777             ++aligncount;
1778     }
1779     return aligncount;
1780 }
1781
1782 char *
1783 root_plselection_prompt(suppliedbuf, buflen, rolenum, racenum, gendnum,
1784                         alignnum)
1785 char *suppliedbuf;
1786 int buflen, rolenum, racenum, gendnum, alignnum;
1787 {
1788     int k, gendercount = 0, aligncount = 0;
1789     char buf[BUFSZ];
1790 /*JP
1791     static char err_ret[] = " character's";
1792 */
1793     static char err_ret[] = "\83L\83\83\83\89\83N\83^\81[\82Ì";
1794 #if 0 /*JP*/
1795     boolean donefirst = FALSE;
1796 #endif
1797
1798     if (!suppliedbuf || buflen < 1)
1799         return err_ret;
1800
1801     /* initialize these static variables each time this is called */
1802     post_attribs = 0;
1803     for (k = 0; k < NUM_BP; ++k)
1804         pa[k] = 0;
1805     buf[0] = '\0';
1806     *suppliedbuf = '\0';
1807
1808     /* How many alignments are allowed for the desired race? */
1809     if (racenum != ROLE_NONE && racenum != ROLE_RANDOM)
1810         aligncount = race_alignmentcount(racenum);
1811
1812     if (alignnum != ROLE_NONE && alignnum != ROLE_RANDOM
1813         && ok_align(rolenum, racenum, gendnum, alignnum)) {
1814         /* if race specified, and multiple choice of alignments for it */
1815         if ((racenum >= 0) && (aligncount > 1)) {
1816 #if 0 /*JP*/
1817             if (donefirst)
1818                 Strcat(buf, " ");
1819 #endif
1820             Strcat(buf, aligns[alignnum].adj);
1821 #if 0 /*JP*/
1822             donefirst = TRUE;
1823 #endif
1824         } else {
1825 #if 0 /*JP*/
1826             if (donefirst)
1827                 Strcat(buf, " ");
1828 #endif
1829             Strcat(buf, aligns[alignnum].adj);
1830 #if 0 /*JP*/
1831             donefirst = TRUE;
1832 #endif
1833         }
1834     } else {
1835         /* in case we got here by failing the ok_align() test */
1836         if (alignnum != ROLE_RANDOM)
1837             alignnum = ROLE_NONE;
1838         /* if alignment not specified, but race is specified
1839            and only one choice of alignment for that race then
1840            don't include it in the later list */
1841         if ((((racenum != ROLE_NONE && racenum != ROLE_RANDOM)
1842               && ok_race(rolenum, racenum, gendnum, alignnum))
1843              && (aligncount > 1))
1844             || (racenum == ROLE_NONE || racenum == ROLE_RANDOM)) {
1845             pa[BP_ALIGN] = 1;
1846             post_attribs++;
1847         }
1848     }
1849     /* <your lawful> */
1850
1851     /* How many genders are allowed for the desired role? */
1852     if (validrole(rolenum))
1853         gendercount = role_gendercount(rolenum);
1854
1855     if (gendnum != ROLE_NONE && gendnum != ROLE_RANDOM) {
1856         if (validrole(rolenum)) {
1857             /* if role specified, and multiple choice of genders for it,
1858                and name of role itself does not distinguish gender */
1859             if ((rolenum != ROLE_NONE) && (gendercount > 1)
1860                 && !roles[rolenum].name.f) {
1861 #if 0 /*JP*/
1862                 if (donefirst)
1863                     Strcat(buf, " ");
1864 #endif
1865                 Strcat(buf, genders[gendnum].adj);
1866 #if 0 /*JP*/
1867                 donefirst = TRUE;
1868 #endif
1869             }
1870         } else {
1871 #if 0 /*JP*/
1872             if (donefirst)
1873                 Strcat(buf, " ");
1874 #endif
1875             Strcat(buf, genders[gendnum].adj);
1876 #if 0 /*JP*/
1877             donefirst = TRUE;
1878 #endif
1879         }
1880     } else {
1881         /* if gender not specified, but role is specified
1882                 and only one choice of gender then
1883                 don't include it in the later list */
1884         if ((validrole(rolenum) && (gendercount > 1))
1885             || !validrole(rolenum)) {
1886             pa[BP_GEND] = 1;
1887             post_attribs++;
1888         }
1889     }
1890     /* <your lawful female> */
1891
1892     if (racenum != ROLE_NONE && racenum != ROLE_RANDOM) {
1893         if (validrole(rolenum)
1894             && ok_race(rolenum, racenum, gendnum, alignnum)) {
1895 #if 0 /*JP*/
1896             if (donefirst)
1897                 Strcat(buf, " ");
1898 #endif
1899             Strcat(buf, (rolenum == ROLE_NONE) ? races[racenum].noun
1900                                                : races[racenum].adj);
1901 #if 0 /*JP*/
1902             donefirst = TRUE;
1903 #endif
1904         } else if (!validrole(rolenum)) {
1905 #if 0 /*JP*/
1906             if (donefirst)
1907                 Strcat(buf, " ");
1908 #endif
1909             Strcat(buf, races[racenum].noun);
1910 #if 0 /*JP*/
1911             donefirst = TRUE;
1912 #endif
1913         } else {
1914             pa[BP_RACE] = 1;
1915             post_attribs++;
1916         }
1917     } else {
1918         pa[BP_RACE] = 1;
1919         post_attribs++;
1920     }
1921     /* <your lawful female gnomish> || <your lawful female gnome> */
1922
1923     if (validrole(rolenum)) {
1924 #if 0 /*JP*/
1925         if (donefirst)
1926             Strcat(buf, " ");
1927 #endif
1928         if (gendnum != ROLE_NONE) {
1929             if (gendnum == 1 && roles[rolenum].name.f)
1930                 Strcat(buf, roles[rolenum].name.f);
1931             else
1932                 Strcat(buf, roles[rolenum].name.m);
1933         } else {
1934             if (roles[rolenum].name.f) {
1935                 Strcat(buf, roles[rolenum].name.m);
1936                 Strcat(buf, "/");
1937                 Strcat(buf, roles[rolenum].name.f);
1938             } else
1939                 Strcat(buf, roles[rolenum].name.m);
1940         }
1941 #if 0 /*JP*/
1942         donefirst = TRUE;
1943 #endif
1944     } else if (rolenum == ROLE_NONE) {
1945         pa[BP_ROLE] = 1;
1946         post_attribs++;
1947     }
1948
1949     if ((racenum == ROLE_NONE || racenum == ROLE_RANDOM)
1950         && !validrole(rolenum)) {
1951 #if 0 /*JP*/
1952         if (donefirst)
1953             Strcat(buf, " ");
1954 #endif
1955 /*JP
1956         Strcat(buf, "character");
1957 */
1958         Strcat(buf, "\83L\83\83\83\89\83N\83^\81[");
1959 #if 0 /*JP*/
1960         donefirst = TRUE;
1961 #endif
1962     }
1963     /* <your lawful female gnomish cavewoman> || <your lawful female gnome>
1964      *    || <your lawful female character>
1965      */
1966     if (buflen > (int) (strlen(buf) + 1)) {
1967         Strcpy(suppliedbuf, buf);
1968         return suppliedbuf;
1969     } else
1970         return err_ret;
1971 }
1972
1973 char *
1974 build_plselection_prompt(buf, buflen, rolenum, racenum, gendnum, alignnum)
1975 char *buf;
1976 int buflen, rolenum, racenum, gendnum, alignnum;
1977 {
1978 /*JP
1979     const char *defprompt = "Shall I pick a character for you? [ynaq] ";
1980 */
1981     const char *defprompt = "\93K\93\96\82É\83L\83\83\83\89\83N\83^\81[\82ð\91I\82ñ\82Å\82æ\82¢\82Å\82·\82©\81H[ynaq] ";
1982     int num_post_attribs = 0;
1983 #if 0 /*JP*/
1984     char tmpbuf[BUFSZ], *p;
1985 #else
1986     char tmpbuf[BUFSZ];
1987 #endif
1988
1989     if (buflen < QBUFSZ)
1990         return (char *) defprompt;
1991
1992 #if 0 /*JP*/
1993     Strcpy(tmpbuf, "Shall I pick ");
1994     if (racenum != ROLE_NONE || validrole(rolenum))
1995         Strcat(tmpbuf, "your ");
1996     else {
1997         Strcat(tmpbuf, "a ");
1998     }
1999 #else
2000     Strcpy(tmpbuf, "");
2001 #endif
2002     /* <your> */
2003
2004     (void) root_plselection_prompt(eos(tmpbuf), buflen - strlen(tmpbuf),
2005                                    rolenum, racenum, gendnum, alignnum);
2006 #if 0 /*JP*/
2007     Sprintf(buf, "%s", s_suffix(tmpbuf));
2008 #else
2009     Sprintf(buf, "%s\82Ì", tmpbuf);
2010 #endif
2011 #if 0 /*JP:\93ú\96{\8cê\82Å\82Í\95s\97v*/
2012     /* don't bother splitting caveman/cavewoman or priest/priestess
2013        in order to apply possessive suffix to both halves, but do
2014        change "priest/priestess'" to "priest/priestess's" */
2015     if ((p = strstri(buf, "priest/priestess'")) != 0
2016         && p[sizeof "priest/priestess'" - sizeof ""] == '\0')
2017         strkitten(buf, 's');
2018 #endif
2019
2020     /* buf should now be:
2021      *    <your lawful female gnomish cavewoman's>
2022      * || <your lawful female gnome's>
2023      * || <your lawful female character's>
2024      *
2025      * Now append the post attributes to it
2026      */
2027     num_post_attribs = post_attribs;
2028     if (!num_post_attribs) {
2029         /* some constraints might have been mutually exclusive, in which case
2030            some prompting that would have been omitted is needed after all */
2031         if (flags.initrole == ROLE_NONE && !pa[BP_ROLE])
2032             pa[BP_ROLE] = ++post_attribs;
2033         if (flags.initrace == ROLE_NONE && !pa[BP_RACE])
2034             pa[BP_RACE] = ++post_attribs;
2035         if (flags.initalign == ROLE_NONE && !pa[BP_ALIGN])
2036             pa[BP_ALIGN] = ++post_attribs;
2037         if (flags.initgend == ROLE_NONE && !pa[BP_GEND])
2038             pa[BP_GEND] = ++post_attribs;
2039         num_post_attribs = post_attribs;
2040     }
2041     if (num_post_attribs) {
2042         if (pa[BP_RACE]) {
2043             (void) promptsep(eos(buf), num_post_attribs);
2044 /*
2045             Strcat(buf, "race");
2046 */
2047             Strcat(buf, "\8eí\91°");
2048         }
2049         if (pa[BP_ROLE]) {
2050             (void) promptsep(eos(buf), num_post_attribs);
2051 /*
2052             Strcat(buf, "role");
2053 */
2054             Strcat(buf, "\90E\8bÆ");
2055         }
2056         if (pa[BP_GEND]) {
2057             (void) promptsep(eos(buf), num_post_attribs);
2058 /*JP
2059             Strcat(buf, "gender");
2060 */
2061             Strcat(buf, "\90«\95Ê");
2062         }
2063         if (pa[BP_ALIGN]) {
2064             (void) promptsep(eos(buf), num_post_attribs);
2065 /*JP
2066             Strcat(buf, "alignment");
2067 */
2068             Strcat(buf, "\91®\90«");
2069         }
2070     }
2071 /*JP
2072     Strcat(buf, " for you? [ynaq] ");
2073 */
2074     Strcat(buf, "\82ð\93K\93\96\82É\91I\82ñ\82Å\82æ\82ë\82µ\82¢\82Å\82·\82©\81H[ynq] ");
2075     return buf;
2076 }
2077
2078 #undef BP_ALIGN
2079 #undef BP_GEND
2080 #undef BP_RACE
2081 #undef BP_ROLE
2082 #undef NUM_BP
2083
2084 void
2085 plnamesuffix()
2086 {
2087     char *sptr, *eptr;
2088     int i;
2089
2090     /* some generic user names will be ignored in favor of prompting */
2091     if (sysopt.genericusers) {
2092         if (*sysopt.genericusers == '*') *plname = '\0';
2093         else {
2094             i = (int)strlen(plname);
2095             if ((sptr = strstri(sysopt.genericusers, plname)) != 0
2096                 && (sptr == sysopt.genericusers || sptr[-1] == ' ')
2097                 && (sptr[i] == ' ' || sptr[i] == '\0'))
2098                 *plname = '\0'; /* call askname() */
2099         }
2100     }
2101
2102     do {
2103         if (!*plname)
2104             askname(); /* fill plname[] if necessary, or set defer_plname */
2105
2106         /* Look for tokens delimited by '-' */
2107         if ((eptr = index(plname, '-')) != (char *) 0)
2108             *eptr++ = '\0';
2109         while (eptr) {
2110             /* Isolate the next token */
2111             sptr = eptr;
2112             if ((eptr = index(sptr, '-')) != (char *) 0)
2113                 *eptr++ = '\0';
2114
2115             /* Try to match it to something */
2116             if ((i = str2role(sptr)) != ROLE_NONE)
2117                 flags.initrole = i;
2118             else if ((i = str2race(sptr)) != ROLE_NONE)
2119                 flags.initrace = i;
2120             else if ((i = str2gend(sptr)) != ROLE_NONE)
2121                 flags.initgend = i;
2122             else if ((i = str2align(sptr)) != ROLE_NONE)
2123                 flags.initalign = i;
2124         }
2125     } while (!*plname && !iflags.defer_plname);
2126
2127     /* commas in the plname confuse the record file, convert to spaces */
2128     for (sptr = plname; *sptr; sptr++) {
2129         if (*sptr == ',')
2130             *sptr = ' ';
2131     }
2132 }
2133
2134 /* show current settings for name, role, race, gender, and alignment
2135    in the specified window */
2136 void
2137 role_selection_prolog(which, where)
2138 int which;
2139 winid where;
2140 {
2141 /*JP
2142     static const char NEARDATA choosing[] = " choosing now",
2143 */
2144     static const char NEARDATA choosing[] = " \8c»\8dÝ\91I\91ð\92\86",
2145 /*JP
2146                                not_yet[] = " not yet specified",
2147 */
2148                                not_yet[] = " \96¢\91I\91ð",
2149 /*JP
2150                                rand_choice[] = " random";
2151 */
2152                                rand_choice[] = " \83\89\83\93\83_\83\80";
2153     char buf[BUFSZ];
2154     int r, c, g, a, allowmask;
2155
2156     r = flags.initrole;
2157     c = flags.initrace;
2158     g = flags.initgend;
2159     a = flags.initalign;
2160     if (r >= 0) {
2161         allowmask = roles[r].allow;
2162         if ((allowmask & ROLE_RACEMASK) == MH_HUMAN)
2163             c = 0; /* races[human] */
2164         else if (c >= 0 && !(allowmask & ROLE_RACEMASK & races[c].allow))
2165             c = ROLE_RANDOM;
2166         if ((allowmask & ROLE_GENDMASK) == ROLE_MALE)
2167             g = 0; /* role forces male (hypothetical) */
2168         else if ((allowmask & ROLE_GENDMASK) == ROLE_FEMALE)
2169             g = 1; /* role forces female (valkyrie) */
2170         if ((allowmask & ROLE_ALIGNMASK) == AM_LAWFUL)
2171             a = 0; /* aligns[lawful] */
2172         else if ((allowmask & ROLE_ALIGNMASK) == AM_NEUTRAL)
2173             a = 1; /* aligns[neutral] */
2174         else if ((allowmask & ROLE_ALIGNMASK) == AM_CHAOTIC)
2175             a = 2; /* alings[chaotic] */
2176     }
2177     if (c >= 0) {
2178         allowmask = races[c].allow;
2179         if ((allowmask & ROLE_ALIGNMASK) == AM_LAWFUL)
2180             a = 0; /* aligns[lawful] */
2181         else if ((allowmask & ROLE_ALIGNMASK) == AM_NEUTRAL)
2182             a = 1; /* aligns[neutral] */
2183         else if ((allowmask & ROLE_ALIGNMASK) == AM_CHAOTIC)
2184             a = 2; /* alings[chaotic] */
2185         /* [c never forces gender] */
2186     }
2187     /* [g and a don't constrain anything sufficiently
2188        to narrow something done to a single choice] */
2189
2190 /*JP
2191     Sprintf(buf, "%12s ", "name:");
2192 */
2193     Sprintf(buf, "%12s ", "\96¼\91O:");
2194     Strcat(buf, (which == RS_NAME) ? choosing : !*plname ? not_yet : plname);
2195     putstr(where, 0, buf);
2196 /*JP
2197     Sprintf(buf, "%12s ", "role:");
2198 */
2199     Sprintf(buf, "%12s ", "\90E\8bÆ:");
2200     Strcat(buf, (which == RS_ROLE) ? choosing : (r == ROLE_NONE)
2201                                                     ? not_yet
2202                                                     : (r == ROLE_RANDOM)
2203                                                           ? rand_choice
2204                                                           : roles[r].name.m);
2205     if (r >= 0 && roles[r].name.f) {
2206         /* distinct female name [caveman/cavewoman, priest/priestess] */
2207         if (g == 1)
2208             /* female specified; replace male role name with female one */
2209             Sprintf(index(buf, ':'), ": %s", roles[r].name.f);
2210         else if (g < 0)
2211             /* gender unspecified; append slash and female role name */
2212             Sprintf(eos(buf), "/%s", roles[r].name.f);
2213     }
2214     putstr(where, 0, buf);
2215 /*JP
2216     Sprintf(buf, "%12s ", "race:");
2217 */
2218     Sprintf(buf, "%12s ", "\8eí\91°:");
2219     Strcat(buf, (which == RS_RACE) ? choosing : (c == ROLE_NONE)
2220                                                     ? not_yet
2221                                                     : (c == ROLE_RANDOM)
2222                                                           ? rand_choice
2223                                                           : races[c].noun);
2224     putstr(where, 0, buf);
2225 /*JP
2226     Sprintf(buf, "%12s ", "gender:");
2227 */
2228     Sprintf(buf, "%12s ", "\90«\95Ê:");
2229     Strcat(buf, (which == RS_GENDER) ? choosing : (g == ROLE_NONE)
2230                                                       ? not_yet
2231                                                       : (g == ROLE_RANDOM)
2232                                                             ? rand_choice
2233                                                             : genders[g].adj);
2234     putstr(where, 0, buf);
2235 /*JP
2236     Sprintf(buf, "%12s ", "alignment:");
2237 */
2238     Sprintf(buf, "%12s ", "\91®\90«:");
2239 #if 0 /*JP:\93ú\96{\8cê\82Å\82Í\96¼\8e\8c\82ª\8e©\91R*/
2240     Strcat(buf, (which == RS_ALGNMNT) ? choosing : (a == ROLE_NONE)
2241                                                        ? not_yet
2242                                                        : (a == ROLE_RANDOM)
2243                                                              ? rand_choice
2244                                                              : aligns[a].adj);
2245 #else
2246     Strcat(buf, (which == RS_ALGNMNT) ? choosing : (a == ROLE_NONE)
2247                                                        ? not_yet
2248                                                        : (a == ROLE_RANDOM)
2249                                                              ? rand_choice
2250                                                              : aligns[a].noun);
2251 #endif
2252     putstr(where, 0, buf);
2253 }
2254
2255 /* add a "pick alignment first"-type entry to the specified menu */
2256 void
2257 role_menu_extra(which, where, preselect)
2258 int which;
2259 winid where;
2260 boolean preselect;
2261 {
2262     static NEARDATA const char RS_menu_let[] = {
2263         '=',  /* name */
2264         '?',  /* role */
2265         '/',  /* race */
2266         '\"', /* gender */
2267         '[',  /* alignment */
2268     };
2269     anything any;
2270     char buf[BUFSZ];
2271     const char *what = 0, *constrainer = 0, *forcedvalue = 0;
2272     int f = 0, r, c, g, a, i, allowmask;
2273
2274     r = flags.initrole;
2275     c = flags.initrace;
2276     switch (which) {
2277     case RS_NAME:
2278 /*JP
2279         what = "name";
2280 */
2281         what = "\96¼\91O";
2282         break;
2283     case RS_ROLE:
2284 /*JP
2285         what = "role";
2286 */
2287         what = "\90E\8bÆ";
2288         f = r;
2289         for (i = 0; i < SIZE(roles); ++i)
2290             if (i != f && !rfilter.roles[i])
2291                 break;
2292         if (i == SIZE(roles)) {
2293 /*JP
2294             constrainer = "filter";
2295 */
2296             constrainer = "\8di\82è\8d\9e\82Ý";
2297 /*JP
2298             forcedvalue = "role";
2299 */
2300             forcedvalue = "\90E\8bÆ";
2301         }
2302         break;
2303     case RS_RACE:
2304 /*JP
2305         what = "race";
2306 */
2307         what = "\8eí\91°";
2308         f = flags.initrace;
2309         c = ROLE_NONE; /* override player's setting */
2310         if (r >= 0) {
2311             allowmask = roles[r].allow & ROLE_RACEMASK;
2312             if (allowmask == MH_HUMAN)
2313                 c = 0; /* races[human] */
2314             if (c >= 0) {
2315 /*JP
2316                 constrainer = "role";
2317 */
2318                 constrainer = "\90E\8bÆ";
2319                 forcedvalue = races[c].noun;
2320             } else if (f >= 0
2321                        && (allowmask & ~rfilter.mask) == races[f].selfmask) {
2322                 /* if there is only one race choice available due to user
2323                    options disallowing others, race menu entry is disabled */
2324 /*JP
2325                 constrainer = "filter";
2326 */
2327                 constrainer = "\8di\82è\8d\9e\82Ý";
2328 /*JP
2329                 forcedvalue = "race";
2330 */
2331                 forcedvalue = "\8eí\91°";
2332             }
2333         }
2334         break;
2335     case RS_GENDER:
2336 /*JP
2337         what = "gender";
2338 */
2339         what = "\90«\95Ê";
2340         f = flags.initgend;
2341         g = ROLE_NONE;
2342         if (r >= 0) {
2343             allowmask = roles[r].allow & ROLE_GENDMASK;
2344             if (allowmask == ROLE_MALE)
2345                 g = 0; /* genders[male] */
2346             else if (allowmask == ROLE_FEMALE)
2347                 g = 1; /* genders[female] */
2348             if (g >= 0) {
2349 /*JP
2350                 constrainer = "role";
2351 */
2352                 constrainer = "\90E\8bÆ";
2353                 forcedvalue = genders[g].adj;
2354             } else if (f >= 0
2355                        && (allowmask & ~rfilter.mask) == genders[f].allow) {
2356                 /* if there is only one gender choice available due to user
2357                    options disallowing other, gender menu entry is disabled */
2358 /*JP
2359                 constrainer = "filter";
2360 */
2361                 constrainer = "\8di\82è\8d\9e\82Ý";
2362 /*JP
2363                 forcedvalue = "gender";
2364 */
2365                 forcedvalue = "\90«\95Ê";
2366             }
2367         }
2368         break;
2369     case RS_ALGNMNT:
2370 /*JP
2371         what = "alignment";
2372 */
2373         what = "\91®\90«";
2374         f = flags.initalign;
2375         a = ROLE_NONE;
2376         if (r >= 0) {
2377             allowmask = roles[r].allow & ROLE_ALIGNMASK;
2378             if (allowmask == AM_LAWFUL)
2379                 a = 0; /* aligns[lawful] */
2380             else if (allowmask == AM_NEUTRAL)
2381                 a = 1; /* aligns[neutral] */
2382             else if (allowmask == AM_CHAOTIC)
2383                 a = 2; /* aligns[chaotic] */
2384             if (a >= 0)
2385 /*JP
2386                 constrainer = "role";
2387 */
2388                 constrainer = "\90E\8bÆ";
2389         }
2390         if (c >= 0 && !constrainer) {
2391             allowmask = races[c].allow & ROLE_ALIGNMASK;
2392             if (allowmask == AM_LAWFUL)
2393                 a = 0; /* aligns[lawful] */
2394             else if (allowmask == AM_NEUTRAL)
2395                 a = 1; /* aligns[neutral] */
2396             else if (allowmask == AM_CHAOTIC)
2397                 a = 2; /* aligns[chaotic] */
2398             if (a >= 0)
2399 /*JP
2400                 constrainer = "race";
2401 */
2402                 constrainer = "\8eí\91°";
2403         }
2404         if (f >= 0 && !constrainer
2405             && (ROLE_ALIGNMASK & ~rfilter.mask) == aligns[f].allow) {
2406             /* if there is only one alignment choice available due to user
2407                options disallowing others, algn menu entry is disabled */
2408 /*JP
2409             constrainer = "filter";
2410 */
2411             constrainer = "\8di\82è\8d\9e\82Ý";
2412 /*JP
2413             forcedvalue = "alignment";
2414 */
2415             forcedvalue = "\91®\90«";
2416         }
2417         if (a >= 0)
2418 #if 0 /*JP:\93ú\96{\8cê\82Å\82Í\96¼\8e\8c\82ª\8e©\91R*/
2419             forcedvalue = aligns[a].adj;
2420 #else
2421             forcedvalue = aligns[a].noun;
2422 #endif
2423         break;
2424     }
2425
2426     any = zeroany; /* zero out all bits */
2427     if (constrainer) {
2428         any.a_int = 0;
2429         /* use four spaces of padding to fake a grayed out menu choice */
2430 /*JP
2431         Sprintf(buf, "%4s%s forces %s", "", constrainer, forcedvalue);
2432 */
2433         Sprintf(buf, "%4s\82±\82Ì%s\82Å\82Í%s\82Ì\82Ý", "", constrainer, forcedvalue);
2434         add_menu(where, NO_GLYPH, &any, 0, 0, ATR_NONE, buf,
2435                  MENU_UNSELECTED);
2436     } else if (what) {
2437         any.a_int = RS_menu_arg(which);
2438 /*JP
2439         Sprintf(buf, "Pick%s %s first", (f >= 0) ? " another" : "", what);
2440 */
2441         Sprintf(buf, "%s%s\82ð\90æ\82É\91I\82Ô", (f >= 0) ? "\91¼\82Ì" : "", what);
2442         add_menu(where, NO_GLYPH, &any, RS_menu_let[which], 0, ATR_NONE, buf,
2443                  MENU_UNSELECTED);
2444     } else if (which == RS_filter) {
2445         any.a_int = RS_menu_arg(RS_filter);
2446 #if 0 /*JP:T*/
2447         add_menu(where, NO_GLYPH, &any, '~', 0, ATR_NONE,
2448                  "Reset role/race/&c filtering", MENU_UNSELECTED);
2449 #else
2450         add_menu(where, NO_GLYPH, &any, '~', 0, ATR_NONE,
2451                  "\90E\8bÆ/\8eí\91°\82È\82Ç\82Ì\8di\82è\8d\9e\82Ý\82ð\89ð\8f\9c\82·\82é", MENU_UNSELECTED);
2452 #endif
2453     } else if (which == ROLE_RANDOM) {
2454         any.a_int = ROLE_RANDOM;
2455 #if 0 /*JP:T*/
2456         add_menu(where, NO_GLYPH, &any, '*', 0, ATR_NONE, "Random",
2457                  preselect ? MENU_SELECTED : MENU_UNSELECTED);
2458 #else
2459         add_menu(where, NO_GLYPH, &any, '*', 0, ATR_NONE, "\83\89\83\93\83_\83\80",
2460                  MENU_UNSELECTED);
2461 #endif
2462     } else if (which == ROLE_NONE) {
2463         any.a_int = ROLE_NONE;
2464 #if 0 /*JP:T*/
2465         add_menu(where, NO_GLYPH, &any, 'q', 0, ATR_NONE, "Quit",
2466                  preselect ? MENU_SELECTED : MENU_UNSELECTED);
2467 #else
2468         add_menu(where, NO_GLYPH, &any, 'q', 0, ATR_NONE, "\94²\82¯\82é",
2469                  MENU_UNSELECTED);
2470 #endif
2471     } else {
2472         impossible("role_menu_extra: bad arg (%d)", which);
2473     }
2474 }
2475
2476 /*
2477  *      Special setup modifications here:
2478  *
2479  *      Unfortunately, this is going to have to be done
2480  *      on each newgame or restore, because you lose the permonst mods
2481  *      across a save/restore.  :-)
2482  *
2483  *      1 - The Rogue Leader is the Tourist Nemesis.
2484  *      2 - Priests start with a random alignment - convert the leader and
2485  *          guardians here.
2486  *      3 - Priests also get their of deities from a randomly chosen role.
2487  *      4 - [obsolete] Elves can have one of two different leaders,
2488  *          but can't work it out here because it requires hacking the
2489  *          level file data (see sp_lev.c).
2490  *
2491  * This code also replaces quest_init().
2492  */
2493 void
2494 role_init()
2495 {
2496     int alignmnt;
2497     struct permonst *pm;
2498
2499     /* Strip the role letter out of the player name.
2500      * This is included for backwards compatibility.
2501      */
2502     plnamesuffix();
2503
2504     /* Check for a valid role.  Try flags.initrole first. */
2505     if (!validrole(flags.initrole)) {
2506         /* Try the player letter second */
2507         if ((flags.initrole = str2role(pl_character)) < 0)
2508             /* None specified; pick a random role */
2509             flags.initrole = randrole_filtered();
2510     }
2511
2512     /* We now have a valid role index.  Copy the role name back. */
2513     /* This should become OBSOLETE */
2514     Strcpy(pl_character, roles[flags.initrole].name.m);
2515     pl_character[PL_CSIZ - 1] = '\0';
2516
2517     /* Check for a valid race */
2518     if (!validrace(flags.initrole, flags.initrace))
2519         flags.initrace = randrace(flags.initrole);
2520
2521     /* Check for a valid gender.  If new game, check both initgend
2522      * and female.  On restore, assume flags.female is correct. */
2523     if (flags.pantheon == -1) { /* new game */
2524         if (!validgend(flags.initrole, flags.initrace, flags.female))
2525             flags.female = !flags.female;
2526     }
2527     if (!validgend(flags.initrole, flags.initrace, flags.initgend))
2528         /* Note that there is no way to check for an unspecified gender. */
2529         flags.initgend = flags.female;
2530
2531     /* Check for a valid alignment */
2532     if (!validalign(flags.initrole, flags.initrace, flags.initalign))
2533         /* Pick a random alignment */
2534         flags.initalign = randalign(flags.initrole, flags.initrace);
2535     alignmnt = aligns[flags.initalign].value;
2536
2537     /* Initialize urole and urace */
2538     urole = roles[flags.initrole];
2539     urace = races[flags.initrace];
2540
2541     /* Fix up the quest leader */
2542     if (urole.ldrnum != NON_PM) {
2543         pm = &mons[urole.ldrnum];
2544         pm->msound = MS_LEADER;
2545         pm->mflags2 |= (M2_PEACEFUL);
2546         pm->mflags3 |= M3_CLOSE;
2547         pm->maligntyp = alignmnt * 3;
2548         /* if gender is random, we choose it now instead of waiting
2549            until the leader monster is created */
2550         quest_status.ldrgend =
2551             is_neuter(pm) ? 2 : is_female(pm) ? 1 : is_male(pm)
2552                                                         ? 0
2553                                                         : (rn2(100) < 50);
2554     }
2555
2556     /* Fix up the quest guardians */
2557     if (urole.guardnum != NON_PM) {
2558         pm = &mons[urole.guardnum];
2559         pm->mflags2 |= (M2_PEACEFUL);
2560         pm->maligntyp = alignmnt * 3;
2561     }
2562
2563     /* Fix up the quest nemesis */
2564     if (urole.neminum != NON_PM) {
2565         pm = &mons[urole.neminum];
2566         pm->msound = MS_NEMESIS;
2567         pm->mflags2 &= ~(M2_PEACEFUL);
2568         pm->mflags2 |= (M2_NASTY | M2_STALK | M2_HOSTILE);
2569         pm->mflags3 &= ~(M3_CLOSE);
2570         pm->mflags3 |= M3_WANTSARTI | M3_WAITFORU;
2571         /* if gender is random, we choose it now instead of waiting
2572            until the nemesis monster is created */
2573         quest_status.nemgend = is_neuter(pm) ? 2 : is_female(pm) ? 1
2574                                    : is_male(pm) ? 0 : (rn2(100) < 50);
2575     }
2576
2577     /* Fix up the god names */
2578     if (flags.pantheon == -1) {             /* new game */
2579         flags.pantheon = flags.initrole;    /* use own gods */
2580         while (!roles[flags.pantheon].lgod) /* unless they're missing */
2581             flags.pantheon = randrole();
2582     }
2583     if (!urole.lgod) {
2584         urole.lgod = roles[flags.pantheon].lgod;
2585         urole.ngod = roles[flags.pantheon].ngod;
2586         urole.cgod = roles[flags.pantheon].cgod;
2587     }
2588     /* 0 or 1; no gods are neuter, nor is gender randomized */
2589 /*JP
2590     quest_status.godgend = !strcmpi(align_gtitle(alignmnt), "goddess");
2591 */
2592     quest_status.godgend = !strcmpi(align_gtitle(alignmnt), "\8f\97\90_");
2593
2594     /* Fix up infravision */
2595     if (mons[urace.malenum].mflags3 & M3_INFRAVISION) {
2596         /* although an infravision intrinsic is possible, infravision
2597          * is purely a property of the physical race.  This means that we
2598          * must put the infravision flag in the player's current race
2599          * (either that or have separate permonst entries for
2600          * elven/non-elven members of each class).  The side effect is that
2601          * all NPCs of that class will have (probably bogus) infravision,
2602          * but since infravision has no effect for NPCs anyway we can
2603          * ignore this.
2604          */
2605         mons[urole.malenum].mflags3 |= M3_INFRAVISION;
2606         if (urole.femalenum != NON_PM)
2607             mons[urole.femalenum].mflags3 |= M3_INFRAVISION;
2608     }
2609
2610     /* Artifacts are fixed in hack_artifacts() */
2611
2612     /* Success! */
2613     return;
2614 }
2615
2616 const char *
2617 Hello(mtmp)
2618 struct monst *mtmp;
2619 {
2620 #if 0 /*JP*/
2621     switch (Role_switch) {
2622     case PM_KNIGHT:
2623         return "Salutations"; /* Olde English */
2624     case PM_SAMURAI:
2625         return (mtmp && mtmp->data == &mons[PM_SHOPKEEPER])
2626                     ? "Irasshaimase"
2627                     : "Konnichi wa"; /* Japanese */
2628     case PM_TOURIST:
2629         return "Aloha"; /* Hawaiian */
2630     case PM_VALKYRIE:
2631         return
2632 #ifdef MAIL
2633                (mtmp && mtmp->data == &mons[PM_MAIL_DAEMON]) ? "Hallo" :
2634 #endif
2635                "Velkommen"; /* Norse */
2636     default:
2637         return "Hello";
2638     }
2639 #else
2640 /*
2641   \82 \82¢\82³\82Â\82Í\93ú\96{\8cê\82Æ\82µ\82Ä\8e©\91R\82É\82È\82é\82æ\82¤\91å\82«\82­\8ed\97l\82ð\95Ï\8dX
2642 */
2643     static char helo_buf[BUFSZ];
2644
2645     switch (Role_switch) {
2646     case PM_KNIGHT:
2647         Sprintf(helo_buf, "\82æ\82­\82¼\8eQ\82Á\82½%s\82æ", plname);
2648         break;
2649     case PM_SAMURAI:
2650         Sprintf(helo_buf, "\82æ\82­\82¼\8eQ\82ç\82ê\82½%s\82æ", plname);
2651         break;
2652     case PM_TOURIST:
2653         Sprintf(helo_buf, "\83A\83\8d\81[\83n%s", plname);
2654         break;
2655     case PM_VALKYRIE:
2656         Sprintf(helo_buf, "\8d°\82Ì\8eç\8cì\8eÒ%s\82æ", plname);
2657         break;
2658     default:
2659         Sprintf(helo_buf, "\82æ\82¤\82±\82»%s", plname);
2660         break;
2661     }
2662
2663     return helo_buf;
2664 #endif
2665 }
2666
2667 const char *
2668 Goodbye()
2669 {
2670 #if 0 /*JP*/
2671     switch (Role_switch) {
2672     case PM_KNIGHT:
2673         return "Fare thee well"; /* Olde English */
2674     case PM_SAMURAI:
2675         return "Sayonara"; /* Japanese */
2676     case PM_TOURIST:
2677         return "Aloha"; /* Hawaiian */
2678     case PM_VALKYRIE:
2679         return "Farvel"; /* Norse */
2680     default:
2681         return "Goodbye";
2682     }
2683 #else
2684     static char helo_buf[BUFSZ];
2685
2686     switch (Role_switch) {
2687     case PM_KNIGHT:
2688         Sprintf(helo_buf, "\82³\82ç\82Î\8chåi\82È\82é");
2689         break;
2690     case PM_SAMURAI:
2691         Sprintf(helo_buf, "\82³\82ç\82Î\95\90\8em\93¹\82ð\8eu\82·");
2692         break;
2693     case PM_TOURIST:
2694         Sprintf(helo_buf, "\83A\83\8d\81[\83n");
2695         break;
2696     case PM_VALKYRIE:
2697         Sprintf(helo_buf, "\82³\82ç\82Î\8d°\82Ì\8eç\8cì\8eÒ");
2698         break;
2699     default:
2700         Sprintf(helo_buf, "\82³\82æ\82¤\82È\82ç");
2701         break;
2702     }
2703
2704     return helo_buf;
2705 #endif
2706 }
2707
2708 /* role.c */