OSDN Git Service

update year to 2022
[jnethack/source.git] / src / role.c
1 /* NetHack 3.6  role.c  $NHDT-Date: 1547086250 2019/01/10 02:10:50 $  $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.56 $ */
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-2022            */
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     { { "Archeologist", 0 },
34 #if 0 /*JP:T*/
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:T*/
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     { { "Barbarian", 0 },
95 #if 0 /*JP:T*/
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:T*/
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     { { "Caveman", "Cavewoman" },
156 #if 0 /*JP:T*/
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:T*/
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     { { "Healer", 0 },
217 #if 0 /*JP:T*/
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:T*/
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     { { "Knight", 0 },
277 #if 0 /*JP:T*/
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:T*/
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     { { "Monk", 0 },
337 #if 0 /*JP:T*/
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:T*/
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     { { "Priest", "Priestess" },
398 #if 0 /*JP:T*/
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:T*/
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     { { "Rogue", 0 },
461 #if 0 /*JP:T*/
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:T*/
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     { { "Ranger", 0 },
521 #if 0 /*JP:T*/
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:T*/
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     { { "Samurai", 0 },
596 #if 0 /*JP:T*/
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:T*/
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     { { "Tourist", 0 },
656 #if 0 /*JP:T*/
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:T*/
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     { { "Valkyrie", 0 },
716 #if 0 /*JP:T*/
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:T*/
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     { { "Wizard", 0 },
776 #if 0 /*JP:T*/
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:T*/
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 #if 0 /*JP*/
838     { { 0, 0 } }
839 #else
840     { { 0, 0 }, { 0, 0 } }
841 #endif
842 };
843
844 /* The player's role, created at runtime from initial
845  * choices.  This may be munged in role_init().
846  */
847 struct Role urole = {
848     { "Undefined", 0 },
849 #if 1 /*JP*/
850     { "Undefined", 0 },
851 #endif
852     { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
853       { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } },
854     "L", "N", "C",
855     "Xxx", "home", "locate",
856     NON_PM, NON_PM, NON_PM, NON_PM, NON_PM, NON_PM, NON_PM, NON_PM,
857     0, 0, 0, 0,
858     /* Str Int Wis Dex Con Cha */
859     { 7, 7, 7, 7, 7, 7 },
860     { 20, 15, 15, 20, 20, 10 },
861     /* Init   Lower  Higher */
862     { 10, 0, 0, 8, 1, 0 }, /* Hit points */
863     { 2, 0, 0, 2, 0, 3 },
864     14, /* Energy */
865      0,
866     10,
867      0,
868      0,
869      4,
870     A_INT,
871      0,
872     -3
873 };
874
875 /* Table of all races */
876 const struct Race races[] = {
877     {
878         "human",
879 #if 0 /*JP:T*/
880         "human",
881         "humanity",
882 #else
883         "\90l\8aÔ",
884         "\90l\8aÔ\82Ì",
885         "\90l\8aÔ",
886 #endif
887         "Hum",
888 #if 0 /*JP:T*/
889         { "man", "woman" },
890 #else
891         { "\92j", "\8f\97" },
892 #endif
893         PM_HUMAN,
894         NON_PM,
895         PM_HUMAN_MUMMY,
896         PM_HUMAN_ZOMBIE,
897         MH_HUMAN | ROLE_MALE | ROLE_FEMALE | ROLE_LAWFUL | ROLE_NEUTRAL
898             | ROLE_CHAOTIC,
899         MH_HUMAN,
900         0,
901         MH_GNOME | MH_ORC,
902         /*    Str     Int Wis Dex Con Cha */
903         { 3, 3, 3, 3, 3, 3 },
904         { STR18(100), 18, 18, 18, 18, 18 },
905         /* Init   Lower  Higher */
906         { 2, 0, 0, 2, 1, 0 }, /* Hit points */
907         { 1, 0, 2, 0, 2, 0 }  /* Energy */
908     },
909     {
910         "elf",
911 #if 0 /*JP:T*/
912         "elven",
913         "elvenkind",
914 #else
915         "\83G\83\8b\83t",
916         "\83G\83\8b\83t\82Ì",
917         "\83G\83\8b\83t",
918 #endif
919         "Elf",
920         { 0, 0 },
921         PM_ELF,
922         NON_PM,
923         PM_ELF_MUMMY,
924         PM_ELF_ZOMBIE,
925         MH_ELF | ROLE_MALE | ROLE_FEMALE | ROLE_CHAOTIC,
926         MH_ELF,
927         MH_ELF,
928         MH_ORC,
929         /*  Str    Int Wis Dex Con Cha */
930         { 3, 3, 3, 3, 3, 3 },
931         { 18, 20, 20, 18, 16, 18 },
932         /* Init   Lower  Higher */
933         { 1, 0, 0, 1, 1, 0 }, /* Hit points */
934         { 2, 0, 3, 0, 3, 0 }  /* Energy */
935     },
936     {
937         "dwarf",
938 #if 0 /*JP:T*/
939         "dwarven",
940         "dwarvenkind",
941 #else
942         "\83h\83\8f\81[\83t",
943         "\83h\83\8f\81[\83t\82Ì",
944         "\83h\83\8f\81[\83t",
945 #endif
946         "Dwa",
947         { 0, 0 },
948         PM_DWARF,
949         NON_PM,
950         PM_DWARF_MUMMY,
951         PM_DWARF_ZOMBIE,
952         MH_DWARF | ROLE_MALE | ROLE_FEMALE | ROLE_LAWFUL,
953         MH_DWARF,
954         MH_DWARF | MH_GNOME,
955         MH_ORC,
956         /*    Str     Int Wis Dex Con Cha */
957         { 3, 3, 3, 3, 3, 3 },
958         { STR18(100), 16, 16, 20, 20, 16 },
959         /* Init   Lower  Higher */
960         { 4, 0, 0, 3, 2, 0 }, /* Hit points */
961         { 0, 0, 0, 0, 0, 0 }  /* Energy */
962     },
963     {
964         "gnome",
965 #if 0 /*JP:T*/
966         "gnomish",
967         "gnomehood",
968 #else
969         "\83m\81[\83\80",
970         "\83m\81[\83\80\82Ì",
971         "\83m\81[\83\80",
972 #endif
973         "Gno",
974         { 0, 0 },
975         PM_GNOME,
976         NON_PM,
977         PM_GNOME_MUMMY,
978         PM_GNOME_ZOMBIE,
979         MH_GNOME | ROLE_MALE | ROLE_FEMALE | ROLE_NEUTRAL,
980         MH_GNOME,
981         MH_DWARF | MH_GNOME,
982         MH_HUMAN,
983         /*  Str    Int Wis Dex Con Cha */
984         { 3, 3, 3, 3, 3, 3 },
985         { STR18(50), 19, 18, 18, 18, 18 },
986         /* Init   Lower  Higher */
987         { 1, 0, 0, 1, 0, 0 }, /* Hit points */
988         { 2, 0, 2, 0, 2, 0 }  /* Energy */
989     },
990     {
991         "orc",
992 #if 0 /*JP:T*/
993         "orcish",
994         "orcdom",
995 #else
996         "\83I\81[\83N",
997         "\83I\81[\83N\82Ì",
998         "\83I\81[\83N",
999 #endif
1000         "Orc",
1001         { 0, 0 },
1002         PM_ORC,
1003         NON_PM,
1004         PM_ORC_MUMMY,
1005         PM_ORC_ZOMBIE,
1006         MH_ORC | ROLE_MALE | ROLE_FEMALE | ROLE_CHAOTIC,
1007         MH_ORC,
1008         0,
1009         MH_HUMAN | MH_ELF | MH_DWARF,
1010         /*  Str    Int Wis Dex Con Cha */
1011         { 3, 3, 3, 3, 3, 3 },
1012         { STR18(50), 16, 16, 18, 18, 16 },
1013         /* Init   Lower  Higher */
1014         { 1, 0, 0, 1, 0, 0 }, /* Hit points */
1015         { 1, 0, 1, 0, 1, 0 }  /* Energy */
1016     },
1017     /* Array terminator */
1018     { 0, 0, 0, 0 }
1019 };
1020
1021 /* The player's race, created at runtime from initial
1022  * choices.  This may be munged in role_init().
1023  */
1024 struct Race urace = {
1025 #if 1 /*JP*/
1026     "something",
1027 #endif
1028     "something",
1029     "undefined",
1030     "something",
1031     "Xxx",
1032     { 0, 0 },
1033     NON_PM,
1034     NON_PM,
1035     NON_PM,
1036     NON_PM,
1037     0,
1038     0,
1039     0,
1040     0,
1041     /*    Str     Int Wis Dex Con Cha */
1042     { 3, 3, 3, 3, 3, 3 },
1043     { STR18(100), 18, 18, 18, 18, 18 },
1044     /* Init   Lower  Higher */
1045     { 2, 0, 0, 2, 1, 0 }, /* Hit points */
1046     { 1, 0, 2, 0, 2, 0 }  /* Energy */
1047 };
1048
1049 /* Table of all genders */
1050 /*JP:
1051 - 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Í
1052   \8aY\93\96\95\94\82à\97v\8fC\90³\81B
1053 */
1054 const struct Gender genders[] = {
1055 #if 0 /*JP:T*/
1056     { "male", "he", "him", "his", "Mal", ROLE_MALE },
1057     { "female", "she", "her", "her", "Fem", ROLE_FEMALE },
1058     { "neuter", "it", "it", "its", "Ntr", ROLE_NEUTER }
1059 #else
1060     { "\92j\90«", "\94Þ", "\94Þ", "\94Þ\82Ì", "Mal", "male", ROLE_MALE },
1061     { "\8f\97\90«", "\94Þ\8f\97", "\94Þ\8f\97", "\94Þ\8f\97\82Ì", "Fem", "female", ROLE_FEMALE },
1062     { "\92\86\90«", "\82»\82ê", "\82»\82ê", "\82»\82Ì", "Ntr", "neuter", ROLE_NEUTER }
1063 #endif
1064 };
1065
1066 /* Table of all alignments */
1067 const struct Align aligns[] = {
1068 #if 0 /*JP:T*/
1069     { "law", "lawful", "Law", ROLE_LAWFUL, A_LAWFUL },
1070     { "balance", "neutral", "Neu", ROLE_NEUTRAL, A_NEUTRAL },
1071     { "chaos", "chaotic", "Cha", ROLE_CHAOTIC, A_CHAOTIC },
1072     { "evil", "unaligned", "Una", 0, A_NONE }
1073 #else
1074     { "\92\81\8f\98", "\92\81\8f\98\82Ì", "Law", "lawful", ROLE_LAWFUL, A_LAWFUL },
1075     { "\92\86\97§", "\92\86\97§\82Ì", "Neu", "neutral", ROLE_NEUTRAL, A_NEUTRAL },
1076     { "\8d¬\93×", "\8d¬\93×\82Ì", "Cha", "chaotic", ROLE_CHAOTIC, A_CHAOTIC },
1077     { "\96³\90S", "\96³\90S\82Ì", "Una", "unaligned", 0, A_NONE }
1078 #endif
1079 };
1080
1081 /* Filters */
1082 static struct {
1083     boolean roles[SIZE(roles)];
1084     short mask;
1085 } rfilter;
1086
1087 STATIC_DCL int NDECL(randrole_filtered);
1088 STATIC_DCL char *FDECL(promptsep, (char *, int));
1089 STATIC_DCL int FDECL(role_gendercount, (int));
1090 STATIC_DCL int FDECL(race_alignmentcount, (int));
1091
1092 /* used by str2XXX() */
1093 static char NEARDATA randomstr[] = "random";
1094 #if 1 /*JP*/
1095 static char NEARDATA randomstrj[] = "\83\89\83\93\83_\83\80";
1096 #endif
1097
1098 boolean
1099 validrole(rolenum)
1100 int rolenum;
1101 {
1102     return (boolean) (rolenum >= 0 && rolenum < SIZE(roles) - 1);
1103 }
1104
1105 int
1106 randrole(for_display)
1107 boolean for_display;
1108 {
1109     int res = SIZE(roles) - 1;
1110
1111     if (for_display)
1112         res = rn2_on_display_rng(res);
1113     else
1114         res = rn2(res);
1115     return res;
1116 }
1117
1118 STATIC_OVL int
1119 randrole_filtered()
1120 {
1121     int i, n = 0, set[SIZE(roles)];
1122
1123     /* this doesn't rule out impossible combinations but attempts to
1124        honor all the filter masks */
1125     for (i = 0; i < SIZE(roles); ++i)
1126         if (ok_role(i, ROLE_NONE, ROLE_NONE, ROLE_NONE)
1127             && ok_race(i, ROLE_RANDOM, ROLE_NONE, ROLE_NONE)
1128             && ok_gend(i, ROLE_NONE, ROLE_RANDOM, ROLE_NONE)
1129             && ok_align(i, ROLE_NONE, ROLE_NONE, ROLE_RANDOM))
1130             set[n++] = i;
1131     return n ? set[rn2(n)] : randrole(FALSE);
1132 }
1133
1134 int
1135 str2role(str)
1136 const char *str;
1137 {
1138     int i, len;
1139
1140     /* Is str valid? */
1141     if (!str || !str[0])
1142         return ROLE_NONE;
1143
1144     /* Match as much of str as is provided */
1145     len = strlen(str);
1146     for (i = 0; roles[i].name.m; i++) {
1147         /* Does it match the male name? */
1148         if (!strncmpi(str, roles[i].name.m, len))
1149             return i;
1150         /* Or the female name? */
1151         if (roles[i].name.f && !strncmpi(str, roles[i].name.f, len))
1152             return i;
1153 #if 1 /*JP*/
1154         /* Does it match the male name? */
1155         if (!strncmpi(str, roles[i].opt.m, len))
1156             return i;
1157         /* Or the female name? */
1158         if (roles[i].opt.f && !strncmpi(str, roles[i].opt.f, len))
1159             return i;
1160 #endif
1161         /* Or the filecode? */
1162         if (!strcmpi(str, roles[i].filecode))
1163             return i;
1164     }
1165
1166     if ((len == 1 && (*str == '*' || *str == '@'))
1167 #if 0 /*JP*/
1168         || !strncmpi(str, randomstr, len))
1169 #else
1170         || !strncmpi(str, randomstr, len)
1171         || !strncmpi(str, randomstrj, len))
1172 #endif
1173         return ROLE_RANDOM;
1174
1175     /* Couldn't find anything appropriate */
1176     return ROLE_NONE;
1177 }
1178
1179 boolean
1180 validrace(rolenum, racenum)
1181 int rolenum, racenum;
1182 {
1183     /* Assumes validrole */
1184     return (boolean) (racenum >= 0 && racenum < SIZE(races) - 1
1185                       && (roles[rolenum].allow & races[racenum].allow
1186                           & ROLE_RACEMASK));
1187 }
1188
1189 int
1190 randrace(rolenum)
1191 int rolenum;
1192 {
1193     int i, n = 0;
1194
1195     /* Count the number of valid races */
1196     for (i = 0; races[i].noun; i++)
1197         if (roles[rolenum].allow & races[i].allow & ROLE_RACEMASK)
1198             n++;
1199
1200     /* Pick a random race */
1201     /* Use a factor of 100 in case of bad random number generators */
1202     if (n)
1203         n = rn2(n * 100) / 100;
1204     for (i = 0; races[i].noun; i++)
1205         if (roles[rolenum].allow & races[i].allow & ROLE_RACEMASK) {
1206             if (n)
1207                 n--;
1208             else
1209                 return i;
1210         }
1211
1212     /* This role has no permitted races? */
1213     return rn2(SIZE(races) - 1);
1214 }
1215
1216 int
1217 str2race(str)
1218 const char *str;
1219 {
1220     int i, len;
1221
1222     /* Is str valid? */
1223     if (!str || !str[0])
1224         return ROLE_NONE;
1225
1226     /* Match as much of str as is provided */
1227     len = strlen(str);
1228     for (i = 0; races[i].noun; i++) {
1229         /* Does it match the noun? */
1230         if (!strncmpi(str, races[i].noun, len))
1231             return i;
1232 #if 1 /*JP*/
1233         /* Does it match the noun? */
1234         if (!strncmpi(str, races[i].opt, len))
1235             return i;
1236 #endif
1237         /* Or the filecode? */
1238         if (!strcmpi(str, races[i].filecode))
1239             return i;
1240     }
1241
1242     if ((len == 1 && (*str == '*' || *str == '@'))
1243 #if 0 /*JP*/
1244         || !strncmpi(str, randomstr, len))
1245 #else
1246         || !strncmpi(str, randomstr, len)
1247         || !strncmpi(str, randomstrj, len))
1248 #endif
1249         return ROLE_RANDOM;
1250
1251     /* Couldn't find anything appropriate */
1252     return ROLE_NONE;
1253 }
1254
1255 boolean
1256 validgend(rolenum, racenum, gendnum)
1257 int rolenum, racenum, gendnum;
1258 {
1259     /* Assumes validrole and validrace */
1260     return (boolean) (gendnum >= 0 && gendnum < ROLE_GENDERS
1261                       && (roles[rolenum].allow & races[racenum].allow
1262                           & genders[gendnum].allow & ROLE_GENDMASK));
1263 }
1264
1265 int
1266 randgend(rolenum, racenum)
1267 int rolenum, racenum;
1268 {
1269     int i, n = 0;
1270
1271     /* Count the number of valid genders */
1272     for (i = 0; i < ROLE_GENDERS; i++)
1273         if (roles[rolenum].allow & races[racenum].allow & genders[i].allow
1274             & ROLE_GENDMASK)
1275             n++;
1276
1277     /* Pick a random gender */
1278     if (n)
1279         n = rn2(n);
1280     for (i = 0; i < ROLE_GENDERS; i++)
1281         if (roles[rolenum].allow & races[racenum].allow & genders[i].allow
1282             & ROLE_GENDMASK) {
1283             if (n)
1284                 n--;
1285             else
1286                 return i;
1287         }
1288
1289     /* This role/race has no permitted genders? */
1290     return rn2(ROLE_GENDERS);
1291 }
1292
1293 int
1294 str2gend(str)
1295 const char *str;
1296 {
1297     int i, len;
1298
1299     /* Is str valid? */
1300     if (!str || !str[0])
1301         return ROLE_NONE;
1302
1303     /* Match as much of str as is provided */
1304     len = strlen(str);
1305     for (i = 0; i < ROLE_GENDERS; i++) {
1306         /* Does it match the adjective? */
1307         if (!strncmpi(str, genders[i].adj, len))
1308             return i;
1309 #if 1 /*JP*/
1310         /* Does it match the adjective? */
1311         if (!strncmpi(str, genders[i].opt, len))
1312             return i;
1313 #endif
1314         /* Or the filecode? */
1315         if (!strcmpi(str, genders[i].filecode))
1316             return i;
1317     }
1318     if ((len == 1 && (*str == '*' || *str == '@'))
1319 #if 0 /*JP*/
1320         || !strncmpi(str, randomstr, len))
1321 #else
1322         || !strncmpi(str, randomstr, len)
1323         || !strncmpi(str, randomstrj, len))
1324 #endif
1325         return ROLE_RANDOM;
1326
1327     /* Couldn't find anything appropriate */
1328     return ROLE_NONE;
1329 }
1330
1331 boolean
1332 validalign(rolenum, racenum, alignnum)
1333 int rolenum, racenum, alignnum;
1334 {
1335     /* Assumes validrole and validrace */
1336     return (boolean) (alignnum >= 0 && alignnum < ROLE_ALIGNS
1337                       && (roles[rolenum].allow & races[racenum].allow
1338                           & aligns[alignnum].allow & ROLE_ALIGNMASK));
1339 }
1340
1341 int
1342 randalign(rolenum, racenum)
1343 int rolenum, racenum;
1344 {
1345     int i, n = 0;
1346
1347     /* Count the number of valid alignments */
1348     for (i = 0; i < ROLE_ALIGNS; i++)
1349         if (roles[rolenum].allow & races[racenum].allow & aligns[i].allow
1350             & ROLE_ALIGNMASK)
1351             n++;
1352
1353     /* Pick a random alignment */
1354     if (n)
1355         n = rn2(n);
1356     for (i = 0; i < ROLE_ALIGNS; i++)
1357         if (roles[rolenum].allow & races[racenum].allow & aligns[i].allow
1358             & ROLE_ALIGNMASK) {
1359             if (n)
1360                 n--;
1361             else
1362                 return i;
1363         }
1364
1365     /* This role/race has no permitted alignments? */
1366     return rn2(ROLE_ALIGNS);
1367 }
1368
1369 int
1370 str2align(str)
1371 const char *str;
1372 {
1373     int i, len;
1374
1375     /* Is str valid? */
1376     if (!str || !str[0])
1377         return ROLE_NONE;
1378
1379     /* Match as much of str as is provided */
1380     len = strlen(str);
1381     for (i = 0; i < ROLE_ALIGNS; i++) {
1382 #if 0 /*JP*/
1383         /* Does it match the adjective? */
1384         if (!strncmpi(str, aligns[i].adj, len))
1385             return i;
1386 #else
1387         /* Does it match the adjective? */
1388         if (!strncmpi(str, aligns[i].noun, len))
1389             return i;
1390         if (!strncmpi(str, aligns[i].opt, len))
1391             return i;
1392 #endif
1393         /* Or the filecode? */
1394         if (!strcmpi(str, aligns[i].filecode))
1395             return i;
1396     }
1397     if ((len == 1 && (*str == '*' || *str == '@'))
1398 #if 0 /*JP*/
1399         || !strncmpi(str, randomstr, len))
1400 #else
1401         || !strncmpi(str, randomstr, len)
1402         || !strncmpi(str, randomstrj, len))
1403 #endif
1404         return ROLE_RANDOM;
1405
1406     /* Couldn't find anything appropriate */
1407     return ROLE_NONE;
1408 }
1409
1410 /* is rolenum compatible with any racenum/gendnum/alignnum constraints? */
1411 boolean
1412 ok_role(rolenum, racenum, gendnum, alignnum)
1413 int rolenum, racenum, gendnum, alignnum;
1414 {
1415     int i;
1416     short allow;
1417
1418     if (rolenum >= 0 && rolenum < SIZE(roles) - 1) {
1419         if (rfilter.roles[rolenum])
1420             return FALSE;
1421         allow = roles[rolenum].allow;
1422         if (racenum >= 0 && racenum < SIZE(races) - 1
1423             && !(allow & races[racenum].allow & ROLE_RACEMASK))
1424             return FALSE;
1425         if (gendnum >= 0 && gendnum < ROLE_GENDERS
1426             && !(allow & genders[gendnum].allow & ROLE_GENDMASK))
1427             return FALSE;
1428         if (alignnum >= 0 && alignnum < ROLE_ALIGNS
1429             && !(allow & aligns[alignnum].allow & ROLE_ALIGNMASK))
1430             return FALSE;
1431         return TRUE;
1432     } else {
1433         /* random; check whether any selection is possible */
1434         for (i = 0; i < SIZE(roles) - 1; i++) {
1435             if (rfilter.roles[i])
1436                 continue;
1437             allow = roles[i].allow;
1438             if (racenum >= 0 && racenum < SIZE(races) - 1
1439                 && !(allow & races[racenum].allow & ROLE_RACEMASK))
1440                 continue;
1441             if (gendnum >= 0 && gendnum < ROLE_GENDERS
1442                 && !(allow & genders[gendnum].allow & ROLE_GENDMASK))
1443                 continue;
1444             if (alignnum >= 0 && alignnum < ROLE_ALIGNS
1445                 && !(allow & aligns[alignnum].allow & ROLE_ALIGNMASK))
1446                 continue;
1447             return TRUE;
1448         }
1449         return FALSE;
1450     }
1451 }
1452
1453 /* pick a random role subject to any racenum/gendnum/alignnum constraints */
1454 /* If pickhow == PICK_RIGID a role is returned only if there is  */
1455 /* a single possibility */
1456 int
1457 pick_role(racenum, gendnum, alignnum, pickhow)
1458 int racenum, gendnum, alignnum, pickhow;
1459 {
1460     int i;
1461     int roles_ok = 0, set[SIZE(roles)];
1462
1463     for (i = 0; i < SIZE(roles) - 1; i++) {
1464         if (ok_role(i, racenum, gendnum, alignnum)
1465             && ok_race(i, (racenum >= 0) ? racenum : ROLE_RANDOM,
1466                        gendnum, alignnum)
1467             && ok_gend(i, racenum,
1468                        (gendnum >= 0) ? gendnum : ROLE_RANDOM, alignnum)
1469             && ok_race(i, racenum,
1470                        gendnum, (alignnum >= 0) ? alignnum : ROLE_RANDOM))
1471             set[roles_ok++] = i;
1472     }
1473     if (roles_ok == 0 || (roles_ok > 1 && pickhow == PICK_RIGID))
1474         return ROLE_NONE;
1475     return set[rn2(roles_ok)];
1476 }
1477
1478 /* is racenum compatible with any rolenum/gendnum/alignnum constraints? */
1479 boolean
1480 ok_race(rolenum, racenum, gendnum, alignnum)
1481 int rolenum, racenum, gendnum, alignnum;
1482 {
1483     int i;
1484     short allow;
1485
1486     if (racenum >= 0 && racenum < SIZE(races) - 1) {
1487         if (rfilter.mask & races[racenum].selfmask)
1488             return FALSE;
1489         allow = races[racenum].allow;
1490         if (rolenum >= 0 && rolenum < SIZE(roles) - 1
1491             && !(allow & roles[rolenum].allow & ROLE_RACEMASK))
1492             return FALSE;
1493         if (gendnum >= 0 && gendnum < ROLE_GENDERS
1494             && !(allow & genders[gendnum].allow & ROLE_GENDMASK))
1495             return FALSE;
1496         if (alignnum >= 0 && alignnum < ROLE_ALIGNS
1497             && !(allow & aligns[alignnum].allow & ROLE_ALIGNMASK))
1498             return FALSE;
1499         return TRUE;
1500     } else {
1501         /* random; check whether any selection is possible */
1502         for (i = 0; i < SIZE(races) - 1; i++) {
1503             if (rfilter.mask & races[i].selfmask)
1504                 continue;
1505             allow = races[i].allow;
1506             if (rolenum >= 0 && rolenum < SIZE(roles) - 1
1507                 && !(allow & roles[rolenum].allow & ROLE_RACEMASK))
1508                 continue;
1509             if (gendnum >= 0 && gendnum < ROLE_GENDERS
1510                 && !(allow & genders[gendnum].allow & ROLE_GENDMASK))
1511                 continue;
1512             if (alignnum >= 0 && alignnum < ROLE_ALIGNS
1513                 && !(allow & aligns[alignnum].allow & ROLE_ALIGNMASK))
1514                 continue;
1515             return TRUE;
1516         }
1517         return FALSE;
1518     }
1519 }
1520
1521 /* Pick a random race subject to any rolenum/gendnum/alignnum constraints.
1522    If pickhow == PICK_RIGID a race is returned only if there is
1523    a single possibility. */
1524 int
1525 pick_race(rolenum, gendnum, alignnum, pickhow)
1526 int rolenum, gendnum, alignnum, pickhow;
1527 {
1528     int i;
1529     int races_ok = 0;
1530
1531     for (i = 0; i < SIZE(races) - 1; i++) {
1532         if (ok_race(rolenum, i, gendnum, alignnum))
1533             races_ok++;
1534     }
1535     if (races_ok == 0 || (races_ok > 1 && pickhow == PICK_RIGID))
1536         return ROLE_NONE;
1537     races_ok = rn2(races_ok);
1538     for (i = 0; i < SIZE(races) - 1; i++) {
1539         if (ok_race(rolenum, i, gendnum, alignnum)) {
1540             if (races_ok == 0)
1541                 return i;
1542             else
1543                 races_ok--;
1544         }
1545     }
1546     return ROLE_NONE;
1547 }
1548
1549 /* is gendnum compatible with any rolenum/racenum/alignnum constraints? */
1550 /* gender and alignment are not comparable (and also not constrainable) */
1551 boolean
1552 ok_gend(rolenum, racenum, gendnum, alignnum)
1553 int rolenum, racenum, gendnum;
1554 int alignnum UNUSED;
1555 {
1556     int i;
1557     short allow;
1558
1559     if (gendnum >= 0 && gendnum < ROLE_GENDERS) {
1560         if (rfilter.mask & genders[gendnum].allow)
1561             return FALSE;
1562         allow = genders[gendnum].allow;
1563         if (rolenum >= 0 && rolenum < SIZE(roles) - 1
1564             && !(allow & roles[rolenum].allow & ROLE_GENDMASK))
1565             return FALSE;
1566         if (racenum >= 0 && racenum < SIZE(races) - 1
1567             && !(allow & races[racenum].allow & ROLE_GENDMASK))
1568             return FALSE;
1569         return TRUE;
1570     } else {
1571         /* random; check whether any selection is possible */
1572         for (i = 0; i < ROLE_GENDERS; i++) {
1573             if (rfilter.mask & genders[i].allow)
1574                 continue;
1575             allow = genders[i].allow;
1576             if (rolenum >= 0 && rolenum < SIZE(roles) - 1
1577                 && !(allow & roles[rolenum].allow & ROLE_GENDMASK))
1578                 continue;
1579             if (racenum >= 0 && racenum < SIZE(races) - 1
1580                 && !(allow & races[racenum].allow & ROLE_GENDMASK))
1581                 continue;
1582             return TRUE;
1583         }
1584         return FALSE;
1585     }
1586 }
1587
1588 /* pick a random gender subject to any rolenum/racenum/alignnum constraints */
1589 /* gender and alignment are not comparable (and also not constrainable) */
1590 /* If pickhow == PICK_RIGID a gender is returned only if there is  */
1591 /* a single possibility */
1592 int
1593 pick_gend(rolenum, racenum, alignnum, pickhow)
1594 int rolenum, racenum, alignnum, pickhow;
1595 {
1596     int i;
1597     int gends_ok = 0;
1598
1599     for (i = 0; i < ROLE_GENDERS; i++) {
1600         if (ok_gend(rolenum, racenum, i, alignnum))
1601             gends_ok++;
1602     }
1603     if (gends_ok == 0 || (gends_ok > 1 && pickhow == PICK_RIGID))
1604         return ROLE_NONE;
1605     gends_ok = rn2(gends_ok);
1606     for (i = 0; i < ROLE_GENDERS; i++) {
1607         if (ok_gend(rolenum, racenum, i, alignnum)) {
1608             if (gends_ok == 0)
1609                 return i;
1610             else
1611                 gends_ok--;
1612         }
1613     }
1614     return ROLE_NONE;
1615 }
1616
1617 /* is alignnum compatible with any rolenum/racenum/gendnum constraints? */
1618 /* alignment and gender are not comparable (and also not constrainable) */
1619 boolean
1620 ok_align(rolenum, racenum, gendnum, alignnum)
1621 int rolenum, racenum;
1622 int gendnum UNUSED;
1623 int alignnum;
1624 {
1625     int i;
1626     short allow;
1627
1628     if (alignnum >= 0 && alignnum < ROLE_ALIGNS) {
1629         if (rfilter.mask & aligns[alignnum].allow)
1630             return FALSE;
1631         allow = aligns[alignnum].allow;
1632         if (rolenum >= 0 && rolenum < SIZE(roles) - 1
1633             && !(allow & roles[rolenum].allow & ROLE_ALIGNMASK))
1634             return FALSE;
1635         if (racenum >= 0 && racenum < SIZE(races) - 1
1636             && !(allow & races[racenum].allow & ROLE_ALIGNMASK))
1637             return FALSE;
1638         return TRUE;
1639     } else {
1640         /* random; check whether any selection is possible */
1641         for (i = 0; i < ROLE_ALIGNS; i++) {
1642             if (rfilter.mask & aligns[i].allow)
1643                 return FALSE;
1644             allow = aligns[i].allow;
1645             if (rolenum >= 0 && rolenum < SIZE(roles) - 1
1646                 && !(allow & roles[rolenum].allow & ROLE_ALIGNMASK))
1647                 continue;
1648             if (racenum >= 0 && racenum < SIZE(races) - 1
1649                 && !(allow & races[racenum].allow & ROLE_ALIGNMASK))
1650                 continue;
1651             return TRUE;
1652         }
1653         return FALSE;
1654     }
1655 }
1656
1657 /* Pick a random alignment subject to any rolenum/racenum/gendnum constraints;
1658    alignment and gender are not comparable (and also not constrainable).
1659    If pickhow == PICK_RIGID an alignment is returned only if there is
1660    a single possibility. */
1661 int
1662 pick_align(rolenum, racenum, gendnum, pickhow)
1663 int rolenum, racenum, gendnum, pickhow;
1664 {
1665     int i;
1666     int aligns_ok = 0;
1667
1668     for (i = 0; i < ROLE_ALIGNS; i++) {
1669         if (ok_align(rolenum, racenum, gendnum, i))
1670             aligns_ok++;
1671     }
1672     if (aligns_ok == 0 || (aligns_ok > 1 && pickhow == PICK_RIGID))
1673         return ROLE_NONE;
1674     aligns_ok = rn2(aligns_ok);
1675     for (i = 0; i < ROLE_ALIGNS; i++) {
1676         if (ok_align(rolenum, racenum, gendnum, i)) {
1677             if (aligns_ok == 0)
1678                 return i;
1679             else
1680                 aligns_ok--;
1681         }
1682     }
1683     return ROLE_NONE;
1684 }
1685
1686 void
1687 rigid_role_checks()
1688 {
1689     int tmp;
1690
1691     /* Some roles are limited to a single race, alignment, or gender and
1692      * calling this routine prior to XXX_player_selection() will help
1693      * prevent an extraneous prompt that actually doesn't allow
1694      * you to choose anything further. Note the use of PICK_RIGID which
1695      * causes the pick_XX() routine to return a value only if there is one
1696      * single possible selection, otherwise it returns ROLE_NONE.
1697      *
1698      */
1699     if (flags.initrole == ROLE_RANDOM) {
1700         /* If the role was explicitly specified as ROLE_RANDOM
1701          * via -uXXXX-@ or OPTIONS=role:random then choose the role
1702          * in here to narrow down later choices.
1703          */
1704         flags.initrole = pick_role(flags.initrace, flags.initgend,
1705                                    flags.initalign, PICK_RANDOM);
1706         if (flags.initrole < 0)
1707             flags.initrole = randrole_filtered();
1708     }
1709     if (flags.initrace == ROLE_RANDOM
1710         && (tmp = pick_race(flags.initrole, flags.initgend,
1711                             flags.initalign, PICK_RANDOM)) != ROLE_NONE)
1712         flags.initrace = tmp;
1713     if (flags.initalign == ROLE_RANDOM
1714         && (tmp = pick_align(flags.initrole, flags.initrace,
1715                              flags.initgend, PICK_RANDOM)) != ROLE_NONE)
1716         flags.initalign = tmp;
1717     if (flags.initgend == ROLE_RANDOM
1718         && (tmp = pick_gend(flags.initrole, flags.initrace,
1719                             flags.initalign, PICK_RANDOM)) != ROLE_NONE)
1720         flags.initgend = tmp;
1721
1722     if (flags.initrole != ROLE_NONE) {
1723         if (flags.initrace == ROLE_NONE)
1724             flags.initrace = pick_race(flags.initrole, flags.initgend,
1725                                        flags.initalign, PICK_RIGID);
1726         if (flags.initalign == ROLE_NONE)
1727             flags.initalign = pick_align(flags.initrole, flags.initrace,
1728                                          flags.initgend, PICK_RIGID);
1729         if (flags.initgend == ROLE_NONE)
1730             flags.initgend = pick_gend(flags.initrole, flags.initrace,
1731                                        flags.initalign, PICK_RIGID);
1732     }
1733 }
1734
1735 boolean
1736 setrolefilter(bufp)
1737 const char *bufp;
1738 {
1739     int i;
1740     boolean reslt = TRUE;
1741
1742     if ((i = str2role(bufp)) != ROLE_NONE && i != ROLE_RANDOM)
1743         rfilter.roles[i] = TRUE;
1744     else if ((i = str2race(bufp)) != ROLE_NONE && i != ROLE_RANDOM)
1745         rfilter.mask |= races[i].selfmask;
1746     else if ((i = str2gend(bufp)) != ROLE_NONE && i != ROLE_RANDOM)
1747         rfilter.mask |= genders[i].allow;
1748     else if ((i = str2align(bufp)) != ROLE_NONE && i != ROLE_RANDOM)
1749         rfilter.mask |= aligns[i].allow;
1750     else
1751         reslt = FALSE;
1752     return reslt;
1753 }
1754
1755 boolean
1756 gotrolefilter()
1757 {
1758     int i;
1759
1760     if (rfilter.mask)
1761         return TRUE;
1762     for (i = 0; i < SIZE(roles); ++i)
1763         if (rfilter.roles[i])
1764             return TRUE;
1765     return FALSE;
1766 }
1767
1768 void
1769 clearrolefilter()
1770 {
1771     int i;
1772
1773     for (i = 0; i < SIZE(roles); ++i)
1774         rfilter.roles[i] = FALSE;
1775     rfilter.mask = 0;
1776 }
1777
1778 #define BP_ALIGN 0
1779 #define BP_GEND 1
1780 #define BP_RACE 2
1781 #define BP_ROLE 3
1782 #define NUM_BP 4
1783
1784 STATIC_VAR char pa[NUM_BP], post_attribs;
1785
1786 STATIC_OVL char *
1787 promptsep(buf, num_post_attribs)
1788 char *buf;
1789 int num_post_attribs;
1790 {
1791 #if 0 /*JP*/
1792     const char *conjuct = "and ";
1793
1794     if (num_post_attribs > 1 && post_attribs < num_post_attribs
1795         && post_attribs > 1)
1796         Strcat(buf, ",");
1797     Strcat(buf, " ");
1798     --post_attribs;
1799     if (!post_attribs && num_post_attribs > 1)
1800         Strcat(buf, conjuct);
1801 #else
1802     /*JP: \93ú\96{\8cê\82Å\82Í "A, B, and C" \82Æ\82¢\82¤\8f\88\97\9d\82Í\95s\97v */
1803     if(num_post_attribs > post_attribs){
1804         Strcat(buf, "\81C");
1805     }
1806     --post_attribs;
1807 #endif
1808     return buf;
1809 }
1810
1811 STATIC_OVL int
1812 role_gendercount(rolenum)
1813 int rolenum;
1814 {
1815     int gendcount = 0;
1816
1817     if (validrole(rolenum)) {
1818         if (roles[rolenum].allow & ROLE_MALE)
1819             ++gendcount;
1820         if (roles[rolenum].allow & ROLE_FEMALE)
1821             ++gendcount;
1822         if (roles[rolenum].allow & ROLE_NEUTER)
1823             ++gendcount;
1824     }
1825     return gendcount;
1826 }
1827
1828 STATIC_OVL int
1829 race_alignmentcount(racenum)
1830 int racenum;
1831 {
1832     int aligncount = 0;
1833
1834     if (racenum != ROLE_NONE && racenum != ROLE_RANDOM) {
1835         if (races[racenum].allow & ROLE_CHAOTIC)
1836             ++aligncount;
1837         if (races[racenum].allow & ROLE_LAWFUL)
1838             ++aligncount;
1839         if (races[racenum].allow & ROLE_NEUTRAL)
1840             ++aligncount;
1841     }
1842     return aligncount;
1843 }
1844
1845 char *
1846 root_plselection_prompt(suppliedbuf, buflen, rolenum, racenum, gendnum,
1847                         alignnum)
1848 char *suppliedbuf;
1849 int buflen, rolenum, racenum, gendnum, alignnum;
1850 {
1851     int k, gendercount = 0, aligncount = 0;
1852     char buf[BUFSZ];
1853 /*JP
1854     static char err_ret[] = " character's";
1855 */
1856     static char err_ret[] = "\83L\83\83\83\89\83N\83^\81[\82Ì";
1857 #if 0 /*JP*/
1858     boolean donefirst = FALSE;
1859 #endif
1860
1861     if (!suppliedbuf || buflen < 1)
1862         return err_ret;
1863
1864     /* initialize these static variables each time this is called */
1865     post_attribs = 0;
1866     for (k = 0; k < NUM_BP; ++k)
1867         pa[k] = 0;
1868     buf[0] = '\0';
1869     *suppliedbuf = '\0';
1870
1871     /* How many alignments are allowed for the desired race? */
1872     if (racenum != ROLE_NONE && racenum != ROLE_RANDOM)
1873         aligncount = race_alignmentcount(racenum);
1874
1875     if (alignnum != ROLE_NONE && alignnum != ROLE_RANDOM
1876         && ok_align(rolenum, racenum, gendnum, alignnum)) {
1877         /* if race specified, and multiple choice of alignments for it */
1878         if ((racenum >= 0) && (aligncount > 1)) {
1879 #if 0 /*JP*/
1880             if (donefirst)
1881                 Strcat(buf, " ");
1882 #endif
1883             Strcat(buf, aligns[alignnum].adj);
1884 #if 0 /*JP*/
1885             donefirst = TRUE;
1886 #endif
1887         } else {
1888 #if 0 /*JP*/
1889             if (donefirst)
1890                 Strcat(buf, " ");
1891 #endif
1892             Strcat(buf, aligns[alignnum].adj);
1893 #if 0 /*JP*/
1894             donefirst = TRUE;
1895 #endif
1896         }
1897     } else {
1898         /* in case we got here by failing the ok_align() test */
1899         if (alignnum != ROLE_RANDOM)
1900             alignnum = ROLE_NONE;
1901         /* if alignment not specified, but race is specified
1902            and only one choice of alignment for that race then
1903            don't include it in the later list */
1904         if ((((racenum != ROLE_NONE && racenum != ROLE_RANDOM)
1905               && ok_race(rolenum, racenum, gendnum, alignnum))
1906              && (aligncount > 1))
1907             || (racenum == ROLE_NONE || racenum == ROLE_RANDOM)) {
1908             pa[BP_ALIGN] = 1;
1909             post_attribs++;
1910         }
1911     }
1912     /* <your lawful> */
1913
1914     /* How many genders are allowed for the desired role? */
1915     if (validrole(rolenum))
1916         gendercount = role_gendercount(rolenum);
1917
1918     if (gendnum != ROLE_NONE && gendnum != ROLE_RANDOM) {
1919         if (validrole(rolenum)) {
1920             /* if role specified, and multiple choice of genders for it,
1921                and name of role itself does not distinguish gender */
1922             if ((rolenum != ROLE_NONE) && (gendercount > 1)
1923                 && !roles[rolenum].name.f) {
1924 #if 0 /*JP*/
1925                 if (donefirst)
1926                     Strcat(buf, " ");
1927 #endif
1928                 Strcat(buf, genders[gendnum].adj);
1929 #if 0 /*JP*/
1930                 donefirst = TRUE;
1931 #endif
1932             }
1933         } else {
1934 #if 0 /*JP*/
1935             if (donefirst)
1936                 Strcat(buf, " ");
1937 #endif
1938             Strcat(buf, genders[gendnum].adj);
1939 #if 0 /*JP*/
1940             donefirst = TRUE;
1941 #endif
1942         }
1943     } else {
1944         /* if gender not specified, but role is specified
1945                 and only one choice of gender then
1946                 don't include it in the later list */
1947         if ((validrole(rolenum) && (gendercount > 1))
1948             || !validrole(rolenum)) {
1949             pa[BP_GEND] = 1;
1950             post_attribs++;
1951         }
1952     }
1953     /* <your lawful female> */
1954
1955     if (racenum != ROLE_NONE && racenum != ROLE_RANDOM) {
1956         if (validrole(rolenum)
1957             && ok_race(rolenum, racenum, gendnum, alignnum)) {
1958 #if 0 /*JP*/
1959             if (donefirst)
1960                 Strcat(buf, " ");
1961 #endif
1962             Strcat(buf, (rolenum == ROLE_NONE) ? races[racenum].noun
1963                                                : races[racenum].adj);
1964 #if 0 /*JP*/
1965             donefirst = TRUE;
1966 #endif
1967         } else if (!validrole(rolenum)) {
1968 #if 0 /*JP*/
1969             if (donefirst)
1970                 Strcat(buf, " ");
1971 #endif
1972             Strcat(buf, races[racenum].noun);
1973 #if 0 /*JP*/
1974             donefirst = TRUE;
1975 #endif
1976         } else {
1977             pa[BP_RACE] = 1;
1978             post_attribs++;
1979         }
1980     } else {
1981         pa[BP_RACE] = 1;
1982         post_attribs++;
1983     }
1984     /* <your lawful female gnomish> || <your lawful female gnome> */
1985
1986     if (validrole(rolenum)) {
1987 #if 0 /*JP*/
1988         if (donefirst)
1989             Strcat(buf, " ");
1990 #endif
1991         if (gendnum != ROLE_NONE) {
1992             if (gendnum == 1 && roles[rolenum].name.f)
1993                 Strcat(buf, roles[rolenum].name.f);
1994             else
1995                 Strcat(buf, roles[rolenum].name.m);
1996         } else {
1997             if (roles[rolenum].name.f) {
1998                 Strcat(buf, roles[rolenum].name.m);
1999                 Strcat(buf, "/");
2000                 Strcat(buf, roles[rolenum].name.f);
2001             } else
2002                 Strcat(buf, roles[rolenum].name.m);
2003         }
2004 #if 0 /*JP*/
2005         donefirst = TRUE;
2006 #endif
2007     } else if (rolenum == ROLE_NONE) {
2008         pa[BP_ROLE] = 1;
2009         post_attribs++;
2010     }
2011
2012     if ((racenum == ROLE_NONE || racenum == ROLE_RANDOM)
2013         && !validrole(rolenum)) {
2014 #if 0 /*JP*/
2015         if (donefirst)
2016             Strcat(buf, " ");
2017 #endif
2018 /*JP
2019         Strcat(buf, "character");
2020 */
2021         Strcat(buf, "\83L\83\83\83\89\83N\83^\81[");
2022 #if 0 /*JP*/
2023         donefirst = TRUE;
2024 #endif
2025     }
2026     /* <your lawful female gnomish cavewoman> || <your lawful female gnome>
2027      *    || <your lawful female character>
2028      */
2029     if (buflen > (int) (strlen(buf) + 1)) {
2030         Strcpy(suppliedbuf, buf);
2031         return suppliedbuf;
2032     } else
2033         return err_ret;
2034 }
2035
2036 char *
2037 build_plselection_prompt(buf, buflen, rolenum, racenum, gendnum, alignnum)
2038 char *buf;
2039 int buflen, rolenum, racenum, gendnum, alignnum;
2040 {
2041 /*JP
2042     const char *defprompt = "Shall I pick a character for you? [ynaq] ";
2043 */
2044     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] ";
2045     int num_post_attribs = 0;
2046 #if 0 /*JP*/
2047     char tmpbuf[BUFSZ], *p;
2048 #else
2049     char tmpbuf[BUFSZ];
2050 #endif
2051
2052     if (buflen < QBUFSZ)
2053         return (char *) defprompt;
2054
2055 #if 0 /*JP*/
2056     Strcpy(tmpbuf, "Shall I pick ");
2057     if (racenum != ROLE_NONE || validrole(rolenum))
2058         Strcat(tmpbuf, "your ");
2059     else
2060         Strcat(tmpbuf, "a ");
2061 #else
2062     Strcpy(tmpbuf, "");
2063 #endif
2064     /* <your> */
2065
2066     (void) root_plselection_prompt(eos(tmpbuf), buflen - strlen(tmpbuf),
2067                                    rolenum, racenum, gendnum, alignnum);
2068 #if 0 /*JP*//*\93ú\96{\8cê\82Å\82Í\95s\97v*/
2069     /* "Shall I pick a character's role, race, gender, and alignment for you?"
2070        plus " [ynaq] (y)" is a little too long for a conventional 80 columns;
2071        also, "pick a character's <anything>" sounds a bit stilted */
2072     strsubst(tmpbuf, "pick a character", "pick character");
2073 #endif
2074 #if 0 /*JP*/
2075     Sprintf(buf, "%s", s_suffix(tmpbuf));
2076 #else
2077     Sprintf(buf, "%s\82Ì", tmpbuf);
2078 #endif
2079 #if 0 /*JP:\93ú\96{\8cê\82Å\82Í\95s\97v*/
2080     /* don't bother splitting caveman/cavewoman or priest/priestess
2081        in order to apply possessive suffix to both halves, but do
2082        change "priest/priestess'" to "priest/priestess's" */
2083     if ((p = strstri(buf, "priest/priestess'")) != 0
2084         && p[sizeof "priest/priestess'" - sizeof ""] == '\0')
2085         strkitten(buf, 's');
2086 #endif
2087
2088     /* buf should now be:
2089      *    <your lawful female gnomish cavewoman's>
2090      * || <your lawful female gnome's>
2091      * || <your lawful female character's>
2092      *
2093      * Now append the post attributes to it
2094      */
2095     num_post_attribs = post_attribs;
2096     if (!num_post_attribs) {
2097         /* some constraints might have been mutually exclusive, in which case
2098            some prompting that would have been omitted is needed after all */
2099         if (flags.initrole == ROLE_NONE && !pa[BP_ROLE])
2100             pa[BP_ROLE] = ++post_attribs;
2101         if (flags.initrace == ROLE_NONE && !pa[BP_RACE])
2102             pa[BP_RACE] = ++post_attribs;
2103         if (flags.initalign == ROLE_NONE && !pa[BP_ALIGN])
2104             pa[BP_ALIGN] = ++post_attribs;
2105         if (flags.initgend == ROLE_NONE && !pa[BP_GEND])
2106             pa[BP_GEND] = ++post_attribs;
2107         num_post_attribs = post_attribs;
2108     }
2109     if (num_post_attribs) {
2110         if (pa[BP_RACE]) {
2111             (void) promptsep(eos(buf), num_post_attribs);
2112 /*JP
2113             Strcat(buf, "race");
2114 */
2115             Strcat(buf, "\8eí\91°");
2116         }
2117         if (pa[BP_ROLE]) {
2118             (void) promptsep(eos(buf), num_post_attribs);
2119 /*JP
2120             Strcat(buf, "role");
2121 */
2122             Strcat(buf, "\90E\8bÆ");
2123         }
2124         if (pa[BP_GEND]) {
2125             (void) promptsep(eos(buf), num_post_attribs);
2126 /*JP
2127             Strcat(buf, "gender");
2128 */
2129             Strcat(buf, "\90«\95Ê");
2130         }
2131         if (pa[BP_ALIGN]) {
2132             (void) promptsep(eos(buf), num_post_attribs);
2133 /*JP
2134             Strcat(buf, "alignment");
2135 */
2136             Strcat(buf, "\91®\90«");
2137         }
2138     }
2139 /*JP
2140     Strcat(buf, " for you? [ynaq] ");
2141 */
2142     Strcat(buf, "\82ð\93K\93\96\82É\91I\82ñ\82Å\82æ\82ë\82µ\82¢\82Å\82·\82©\81H[ynq] ");
2143     return buf;
2144 }
2145
2146 #undef BP_ALIGN
2147 #undef BP_GEND
2148 #undef BP_RACE
2149 #undef BP_ROLE
2150 #undef NUM_BP
2151
2152 void
2153 plnamesuffix()
2154 {
2155     char *sptr, *eptr;
2156     int i;
2157
2158     /* some generic user names will be ignored in favor of prompting */
2159     if (sysopt.genericusers) {
2160         if (*sysopt.genericusers == '*') {
2161             *plname = '\0';
2162         } else {
2163             i = (int) strlen(plname);
2164             if ((sptr = strstri(sysopt.genericusers, plname)) != 0
2165                 && (sptr == sysopt.genericusers || sptr[-1] == ' ')
2166                 && (sptr[i] == ' ' || sptr[i] == '\0'))
2167                 *plname = '\0'; /* call askname() */
2168         }
2169     }
2170
2171     do {
2172         if (!*plname)
2173             askname(); /* fill plname[] if necessary, or set defer_plname */
2174
2175         /* Look for tokens delimited by '-' */
2176         if ((eptr = index(plname, '-')) != (char *) 0)
2177             *eptr++ = '\0';
2178         while (eptr) {
2179             /* Isolate the next token */
2180             sptr = eptr;
2181             if ((eptr = index(sptr, '-')) != (char *) 0)
2182                 *eptr++ = '\0';
2183
2184             /* Try to match it to something */
2185             if ((i = str2role(sptr)) != ROLE_NONE)
2186                 flags.initrole = i;
2187             else if ((i = str2race(sptr)) != ROLE_NONE)
2188                 flags.initrace = i;
2189             else if ((i = str2gend(sptr)) != ROLE_NONE)
2190                 flags.initgend = i;
2191             else if ((i = str2align(sptr)) != ROLE_NONE)
2192                 flags.initalign = i;
2193         }
2194     } while (!*plname && !iflags.defer_plname);
2195
2196     /* commas in the plname confuse the record file, convert to spaces */
2197     for (sptr = plname; *sptr; sptr++) {
2198         if (*sptr == ',')
2199             *sptr = ' ';
2200     }
2201 }
2202
2203 /* show current settings for name, role, race, gender, and alignment
2204    in the specified window */
2205 void
2206 role_selection_prolog(which, where)
2207 int which;
2208 winid where;
2209 {
2210 /*JP
2211     static const char NEARDATA choosing[] = " choosing now",
2212 */
2213     static const char NEARDATA choosing[] = " \8c»\8dÝ\91I\91ð\92\86",
2214 /*JP
2215                                not_yet[] = " not yet specified",
2216 */
2217                                not_yet[] = " \96¢\91I\91ð",
2218 /*JP
2219                                rand_choice[] = " random";
2220 */
2221                                rand_choice[] = " \83\89\83\93\83_\83\80";
2222     char buf[BUFSZ];
2223     int r, c, g, a, allowmask;
2224
2225     r = flags.initrole;
2226     c = flags.initrace;
2227     g = flags.initgend;
2228     a = flags.initalign;
2229     if (r >= 0) {
2230         allowmask = roles[r].allow;
2231         if ((allowmask & ROLE_RACEMASK) == MH_HUMAN)
2232             c = 0; /* races[human] */
2233         else if (c >= 0 && !(allowmask & ROLE_RACEMASK & races[c].allow))
2234             c = ROLE_RANDOM;
2235         if ((allowmask & ROLE_GENDMASK) == ROLE_MALE)
2236             g = 0; /* role forces male (hypothetical) */
2237         else if ((allowmask & ROLE_GENDMASK) == ROLE_FEMALE)
2238             g = 1; /* role forces female (valkyrie) */
2239         if ((allowmask & ROLE_ALIGNMASK) == AM_LAWFUL)
2240             a = 0; /* aligns[lawful] */
2241         else if ((allowmask & ROLE_ALIGNMASK) == AM_NEUTRAL)
2242             a = 1; /* aligns[neutral] */
2243         else if ((allowmask & ROLE_ALIGNMASK) == AM_CHAOTIC)
2244             a = 2; /* alings[chaotic] */
2245     }
2246     if (c >= 0) {
2247         allowmask = races[c].allow;
2248         if ((allowmask & ROLE_ALIGNMASK) == AM_LAWFUL)
2249             a = 0; /* aligns[lawful] */
2250         else if ((allowmask & ROLE_ALIGNMASK) == AM_NEUTRAL)
2251             a = 1; /* aligns[neutral] */
2252         else if ((allowmask & ROLE_ALIGNMASK) == AM_CHAOTIC)
2253             a = 2; /* alings[chaotic] */
2254         /* [c never forces gender] */
2255     }
2256     /* [g and a don't constrain anything sufficiently
2257        to narrow something done to a single choice] */
2258
2259 /*JP
2260     Sprintf(buf, "%12s ", "name:");
2261 */
2262     Sprintf(buf, "%12s ", "\96¼\91O:");
2263     Strcat(buf, (which == RS_NAME) ? choosing : !*plname ? not_yet : plname);
2264     putstr(where, 0, buf);
2265 /*JP
2266     Sprintf(buf, "%12s ", "role:");
2267 */
2268     Sprintf(buf, "%12s ", "\90E\8bÆ:");
2269     Strcat(buf, (which == RS_ROLE) ? choosing : (r == ROLE_NONE)
2270                                                     ? not_yet
2271                                                     : (r == ROLE_RANDOM)
2272                                                           ? rand_choice
2273                                                           : roles[r].name.m);
2274     if (r >= 0 && roles[r].name.f) {
2275         /* distinct female name [caveman/cavewoman, priest/priestess] */
2276         if (g == 1)
2277             /* female specified; replace male role name with female one */
2278             Sprintf(index(buf, ':'), ": %s", roles[r].name.f);
2279         else if (g < 0)
2280             /* gender unspecified; append slash and female role name */
2281             Sprintf(eos(buf), "/%s", roles[r].name.f);
2282     }
2283     putstr(where, 0, buf);
2284 /*JP
2285     Sprintf(buf, "%12s ", "race:");
2286 */
2287     Sprintf(buf, "%12s ", "\8eí\91°:");
2288     Strcat(buf, (which == RS_RACE) ? choosing : (c == ROLE_NONE)
2289                                                     ? not_yet
2290                                                     : (c == ROLE_RANDOM)
2291                                                           ? rand_choice
2292                                                           : races[c].noun);
2293     putstr(where, 0, buf);
2294 /*JP
2295     Sprintf(buf, "%12s ", "gender:");
2296 */
2297     Sprintf(buf, "%12s ", "\90«\95Ê:");
2298     Strcat(buf, (which == RS_GENDER) ? choosing : (g == ROLE_NONE)
2299                                                       ? not_yet
2300                                                       : (g == ROLE_RANDOM)
2301                                                             ? rand_choice
2302                                                             : genders[g].adj);
2303     putstr(where, 0, buf);
2304 /*JP
2305     Sprintf(buf, "%12s ", "alignment:");
2306 */
2307     Sprintf(buf, "%12s ", "\91®\90«:");
2308 #if 0 /*JP:\93ú\96{\8cê\82Å\82Í\96¼\8e\8c\82ª\8e©\91R*/
2309     Strcat(buf, (which == RS_ALGNMNT) ? choosing : (a == ROLE_NONE)
2310                                                        ? not_yet
2311                                                        : (a == ROLE_RANDOM)
2312                                                              ? rand_choice
2313                                                              : aligns[a].adj);
2314 #else
2315     Strcat(buf, (which == RS_ALGNMNT) ? choosing : (a == ROLE_NONE)
2316                                                        ? not_yet
2317                                                        : (a == ROLE_RANDOM)
2318                                                              ? rand_choice
2319                                                              : aligns[a].noun);
2320 #endif
2321     putstr(where, 0, buf);
2322 }
2323
2324 /* add a "pick alignment first"-type entry to the specified menu */
2325 void
2326 role_menu_extra(which, where, preselect)
2327 int which;
2328 winid where;
2329 boolean preselect;
2330 {
2331     static NEARDATA const char RS_menu_let[] = {
2332         '=',  /* name */
2333         '?',  /* role */
2334         '/',  /* race */
2335         '\"', /* gender */
2336         '[',  /* alignment */
2337     };
2338     anything any;
2339     char buf[BUFSZ];
2340     const char *what = 0, *constrainer = 0, *forcedvalue = 0;
2341     int f = 0, r, c, g, a, i, allowmask;
2342
2343     r = flags.initrole;
2344     c = flags.initrace;
2345     switch (which) {
2346     case RS_NAME:
2347 /*JP
2348         what = "name";
2349 */
2350         what = "\96¼\91O";
2351         break;
2352     case RS_ROLE:
2353 /*JP
2354         what = "role";
2355 */
2356         what = "\90E\8bÆ";
2357         f = r;
2358         for (i = 0; i < SIZE(roles); ++i)
2359             if (i != f && !rfilter.roles[i])
2360                 break;
2361         if (i == SIZE(roles)) {
2362 /*JP
2363             constrainer = "filter";
2364 */
2365             constrainer = "\8di\82è\8d\9e\82Ý";
2366 /*JP
2367             forcedvalue = "role";
2368 */
2369             forcedvalue = "\90E\8bÆ";
2370         }
2371         break;
2372     case RS_RACE:
2373 /*JP
2374         what = "race";
2375 */
2376         what = "\8eí\91°";
2377         f = flags.initrace;
2378         c = ROLE_NONE; /* override player's setting */
2379         if (r >= 0) {
2380             allowmask = roles[r].allow & ROLE_RACEMASK;
2381             if (allowmask == MH_HUMAN)
2382                 c = 0; /* races[human] */
2383             if (c >= 0) {
2384 /*JP
2385                 constrainer = "role";
2386 */
2387                 constrainer = "\90E\8bÆ";
2388                 forcedvalue = races[c].noun;
2389             } else if (f >= 0
2390                        && (allowmask & ~rfilter.mask) == races[f].selfmask) {
2391                 /* if there is only one race choice available due to user
2392                    options disallowing others, race menu entry is disabled */
2393 /*JP
2394                 constrainer = "filter";
2395 */
2396                 constrainer = "\8di\82è\8d\9e\82Ý";
2397 /*JP
2398                 forcedvalue = "race";
2399 */
2400                 forcedvalue = "\8eí\91°";
2401             }
2402         }
2403         break;
2404     case RS_GENDER:
2405 /*JP
2406         what = "gender";
2407 */
2408         what = "\90«\95Ê";
2409         f = flags.initgend;
2410         g = ROLE_NONE;
2411         if (r >= 0) {
2412             allowmask = roles[r].allow & ROLE_GENDMASK;
2413             if (allowmask == ROLE_MALE)
2414                 g = 0; /* genders[male] */
2415             else if (allowmask == ROLE_FEMALE)
2416                 g = 1; /* genders[female] */
2417             if (g >= 0) {
2418 /*JP
2419                 constrainer = "role";
2420 */
2421                 constrainer = "\90E\8bÆ";
2422                 forcedvalue = genders[g].adj;
2423             } else if (f >= 0
2424                        && (allowmask & ~rfilter.mask) == genders[f].allow) {
2425                 /* if there is only one gender choice available due to user
2426                    options disallowing other, gender menu entry is disabled */
2427 /*JP
2428                 constrainer = "filter";
2429 */
2430                 constrainer = "\8di\82è\8d\9e\82Ý";
2431 /*JP
2432                 forcedvalue = "gender";
2433 */
2434                 forcedvalue = "\90«\95Ê";
2435             }
2436         }
2437         break;
2438     case RS_ALGNMNT:
2439 /*JP
2440         what = "alignment";
2441 */
2442         what = "\91®\90«";
2443         f = flags.initalign;
2444         a = ROLE_NONE;
2445         if (r >= 0) {
2446             allowmask = roles[r].allow & ROLE_ALIGNMASK;
2447             if (allowmask == AM_LAWFUL)
2448                 a = 0; /* aligns[lawful] */
2449             else if (allowmask == AM_NEUTRAL)
2450                 a = 1; /* aligns[neutral] */
2451             else if (allowmask == AM_CHAOTIC)
2452                 a = 2; /* aligns[chaotic] */
2453             if (a >= 0)
2454 /*JP
2455                 constrainer = "role";
2456 */
2457                 constrainer = "\90E\8bÆ";
2458         }
2459         if (c >= 0 && !constrainer) {
2460             allowmask = races[c].allow & ROLE_ALIGNMASK;
2461             if (allowmask == AM_LAWFUL)
2462                 a = 0; /* aligns[lawful] */
2463             else if (allowmask == AM_NEUTRAL)
2464                 a = 1; /* aligns[neutral] */
2465             else if (allowmask == AM_CHAOTIC)
2466                 a = 2; /* aligns[chaotic] */
2467             if (a >= 0)
2468 /*JP
2469                 constrainer = "race";
2470 */
2471                 constrainer = "\8eí\91°";
2472         }
2473         if (f >= 0 && !constrainer
2474             && (ROLE_ALIGNMASK & ~rfilter.mask) == aligns[f].allow) {
2475             /* if there is only one alignment choice available due to user
2476                options disallowing others, algn menu entry is disabled */
2477 /*JP
2478             constrainer = "filter";
2479 */
2480             constrainer = "\8di\82è\8d\9e\82Ý";
2481 /*JP
2482             forcedvalue = "alignment";
2483 */
2484             forcedvalue = "\91®\90«";
2485         }
2486         if (a >= 0)
2487 #if 0 /*JP:\93ú\96{\8cê\82Å\82Í\96¼\8e\8c\82ª\8e©\91R*/
2488             forcedvalue = aligns[a].adj;
2489 #else
2490             forcedvalue = aligns[a].noun;
2491 #endif
2492         break;
2493     }
2494
2495     any = zeroany; /* zero out all bits */
2496     if (constrainer) {
2497         any.a_int = 0;
2498         /* use four spaces of padding to fake a grayed out menu choice */
2499 /*JP
2500         Sprintf(buf, "%4s%s forces %s", "", constrainer, forcedvalue);
2501 */
2502         Sprintf(buf, "%4s\82±\82Ì%s\82Å\82Í%s\82Ì\82Ý", "", constrainer, forcedvalue);
2503         add_menu(where, NO_GLYPH, &any, 0, 0, ATR_NONE, buf,
2504                  MENU_UNSELECTED);
2505     } else if (what) {
2506         any.a_int = RS_menu_arg(which);
2507 /*JP
2508         Sprintf(buf, "Pick%s %s first", (f >= 0) ? " another" : "", what);
2509 */
2510         Sprintf(buf, "%s%s\82ð\90æ\82É\91I\82Ô", (f >= 0) ? "\91¼\82Ì" : "", what);
2511         add_menu(where, NO_GLYPH, &any, RS_menu_let[which], 0, ATR_NONE, buf,
2512                  MENU_UNSELECTED);
2513     } else if (which == RS_filter) {
2514         any.a_int = RS_menu_arg(RS_filter);
2515 #if 0 /*JP:T*/
2516         add_menu(where, NO_GLYPH, &any, '~', 0, ATR_NONE,
2517                  "Reset role/race/&c filtering", MENU_UNSELECTED);
2518 #else
2519         add_menu(where, NO_GLYPH, &any, '~', 0, ATR_NONE,
2520                  "\90E\8bÆ/\8eí\91°\82È\82Ç\82Ì\8di\82è\8d\9e\82Ý\82ð\89ð\8f\9c\82·\82é", MENU_UNSELECTED);
2521 #endif
2522     } else if (which == ROLE_RANDOM) {
2523         any.a_int = ROLE_RANDOM;
2524 #if 0 /*JP:T*/
2525         add_menu(where, NO_GLYPH, &any, '*', 0, ATR_NONE, "Random",
2526                  preselect ? MENU_SELECTED : MENU_UNSELECTED);
2527 #else
2528         add_menu(where, NO_GLYPH, &any, '*', 0, ATR_NONE, "\83\89\83\93\83_\83\80",
2529                  MENU_UNSELECTED);
2530 #endif
2531     } else if (which == ROLE_NONE) {
2532         any.a_int = ROLE_NONE;
2533 #if 0 /*JP:T*/
2534         add_menu(where, NO_GLYPH, &any, 'q', 0, ATR_NONE, "Quit",
2535                  preselect ? MENU_SELECTED : MENU_UNSELECTED);
2536 #else
2537         add_menu(where, NO_GLYPH, &any, 'q', 0, ATR_NONE, "\94²\82¯\82é",
2538                  MENU_UNSELECTED);
2539 #endif
2540     } else {
2541         impossible("role_menu_extra: bad arg (%d)", which);
2542     }
2543 }
2544
2545 /*
2546  *      Special setup modifications here:
2547  *
2548  *      Unfortunately, this is going to have to be done
2549  *      on each newgame or restore, because you lose the permonst mods
2550  *      across a save/restore.  :-)
2551  *
2552  *      1 - The Rogue Leader is the Tourist Nemesis.
2553  *      2 - Priests start with a random alignment - convert the leader and
2554  *          guardians here.
2555  *      3 - Priests also get their of deities from a randomly chosen role.
2556  *      4 - [obsolete] Elves can have one of two different leaders,
2557  *          but can't work it out here because it requires hacking the
2558  *          level file data (see sp_lev.c).
2559  *
2560  * This code also replaces quest_init().
2561  */
2562 void
2563 role_init()
2564 {
2565     int alignmnt;
2566     struct permonst *pm;
2567
2568     /* Strip the role letter out of the player name.
2569      * This is included for backwards compatibility.
2570      */
2571     plnamesuffix();
2572
2573     /* Check for a valid role.  Try flags.initrole first. */
2574     if (!validrole(flags.initrole)) {
2575         /* Try the player letter second */
2576         if ((flags.initrole = str2role(pl_character)) < 0)
2577             /* None specified; pick a random role */
2578             flags.initrole = randrole_filtered();
2579     }
2580
2581     /* We now have a valid role index.  Copy the role name back. */
2582     /* This should become OBSOLETE */
2583     Strcpy(pl_character, roles[flags.initrole].name.m);
2584     pl_character[PL_CSIZ - 1] = '\0';
2585
2586     /* Check for a valid race */
2587     if (!validrace(flags.initrole, flags.initrace))
2588         flags.initrace = randrace(flags.initrole);
2589
2590     /* Check for a valid gender.  If new game, check both initgend
2591      * and female.  On restore, assume flags.female is correct. */
2592     if (flags.pantheon == -1) { /* new game */
2593         if (!validgend(flags.initrole, flags.initrace, flags.female))
2594             flags.female = !flags.female;
2595     }
2596     if (!validgend(flags.initrole, flags.initrace, flags.initgend))
2597         /* Note that there is no way to check for an unspecified gender. */
2598         flags.initgend = flags.female;
2599
2600     /* Check for a valid alignment */
2601     if (!validalign(flags.initrole, flags.initrace, flags.initalign))
2602         /* Pick a random alignment */
2603         flags.initalign = randalign(flags.initrole, flags.initrace);
2604     alignmnt = aligns[flags.initalign].value;
2605
2606     /* Initialize urole and urace */
2607     urole = roles[flags.initrole];
2608     urace = races[flags.initrace];
2609
2610     /* Fix up the quest leader */
2611     if (urole.ldrnum != NON_PM) {
2612         pm = &mons[urole.ldrnum];
2613         pm->msound = MS_LEADER;
2614         pm->mflags2 |= (M2_PEACEFUL);
2615         pm->mflags3 |= M3_CLOSE;
2616         pm->maligntyp = alignmnt * 3;
2617         /* if gender is random, we choose it now instead of waiting
2618            until the leader monster is created */
2619         quest_status.ldrgend =
2620             is_neuter(pm) ? 2 : is_female(pm) ? 1 : is_male(pm)
2621                                                         ? 0
2622                                                         : (rn2(100) < 50);
2623     }
2624
2625     /* Fix up the quest guardians */
2626     if (urole.guardnum != NON_PM) {
2627         pm = &mons[urole.guardnum];
2628         pm->mflags2 |= (M2_PEACEFUL);
2629         pm->maligntyp = alignmnt * 3;
2630     }
2631
2632     /* Fix up the quest nemesis */
2633     if (urole.neminum != NON_PM) {
2634         pm = &mons[urole.neminum];
2635         pm->msound = MS_NEMESIS;
2636         pm->mflags2 &= ~(M2_PEACEFUL);
2637         pm->mflags2 |= (M2_NASTY | M2_STALK | M2_HOSTILE);
2638         pm->mflags3 &= ~(M3_CLOSE);
2639         pm->mflags3 |= M3_WANTSARTI | M3_WAITFORU;
2640         /* if gender is random, we choose it now instead of waiting
2641            until the nemesis monster is created */
2642         quest_status.nemgend = is_neuter(pm) ? 2 : is_female(pm) ? 1
2643                                    : is_male(pm) ? 0 : (rn2(100) < 50);
2644     }
2645
2646     /* Fix up the god names */
2647     if (flags.pantheon == -1) {             /* new game */
2648         flags.pantheon = flags.initrole;    /* use own gods */
2649         while (!roles[flags.pantheon].lgod) /* unless they're missing */
2650             flags.pantheon = randrole(FALSE);
2651     }
2652     if (!urole.lgod) {
2653         urole.lgod = roles[flags.pantheon].lgod;
2654         urole.ngod = roles[flags.pantheon].ngod;
2655         urole.cgod = roles[flags.pantheon].cgod;
2656     }
2657     /* 0 or 1; no gods are neuter, nor is gender randomized */
2658 /*JP
2659     quest_status.godgend = !strcmpi(align_gtitle(alignmnt), "goddess");
2660 */
2661     quest_status.godgend = !strcmpi(align_gtitle(alignmnt), "\8f\97\90_");
2662
2663 #if 0
2664 /*
2665  * Disable this fixup so that mons[] can be const.  The only
2666  * place where it actually matters for the hero is in set_uasmon()
2667  * and that can use mons[race] rather than mons[role] for this
2668  * particular property.  Despite the comment, it is checked--where
2669  * needed--via instrinsic 'Infravision' which set_uasmon() manages.
2670  */
2671     /* Fix up infravision */
2672     if (mons[urace.malenum].mflags3 & M3_INFRAVISION) {
2673         /* although an infravision intrinsic is possible, infravision
2674          * is purely a property of the physical race.  This means that we
2675          * must put the infravision flag in the player's current race
2676          * (either that or have separate permonst entries for
2677          * elven/non-elven members of each class).  The side effect is that
2678          * all NPCs of that class will have (probably bogus) infravision,
2679          * but since infravision has no effect for NPCs anyway we can
2680          * ignore this.
2681          */
2682         mons[urole.malenum].mflags3 |= M3_INFRAVISION;
2683         if (urole.femalenum != NON_PM)
2684             mons[urole.femalenum].mflags3 |= M3_INFRAVISION;
2685     }
2686 #endif /*0*/
2687
2688     /* Artifacts are fixed in hack_artifacts() */
2689
2690     /* Success! */
2691     return;
2692 }
2693
2694 const char *
2695 Hello(mtmp)
2696 struct monst *mtmp;
2697 {
2698 #if 0 /*JP*/
2699     switch (Role_switch) {
2700     case PM_KNIGHT:
2701         return "Salutations"; /* Olde English */
2702     case PM_SAMURAI:
2703         return (mtmp && mtmp->data == &mons[PM_SHOPKEEPER])
2704                     ? "Irasshaimase"
2705                     : "Konnichi wa"; /* Japanese */
2706     case PM_TOURIST:
2707         return "Aloha"; /* Hawaiian */
2708     case PM_VALKYRIE:
2709         return
2710 #ifdef MAIL
2711                (mtmp && mtmp->data == &mons[PM_MAIL_DAEMON]) ? "Hallo" :
2712 #endif
2713                "Velkommen"; /* Norse */
2714     default:
2715         return "Hello";
2716     }
2717 #else
2718 /*
2719   \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
2720 */
2721     static char helo_buf[BUFSZ];
2722
2723     switch (Role_switch) {
2724     case PM_KNIGHT:
2725         Sprintf(helo_buf, "\82æ\82­\82¼\8eQ\82Á\82½%s\82æ", plname);
2726         break;
2727     case PM_SAMURAI:
2728         Sprintf(helo_buf, "\82æ\82­\82¼\8eQ\82ç\82ê\82½%s\82æ", plname);
2729         break;
2730     case PM_TOURIST:
2731         Sprintf(helo_buf, "\83A\83\8d\81[\83n%s", plname);
2732         break;
2733     case PM_VALKYRIE:
2734         Sprintf(helo_buf, "\8d°\82Ì\8eç\8cì\8eÒ%s\82æ", plname);
2735         break;
2736     default:
2737         Sprintf(helo_buf, "\82æ\82¤\82±\82»%s", plname);
2738         break;
2739     }
2740
2741     return helo_buf;
2742 #endif
2743 }
2744
2745 const char *
2746 Goodbye()
2747 {
2748 #if 0 /*JP*/
2749     switch (Role_switch) {
2750     case PM_KNIGHT:
2751         return "Fare thee well"; /* Olde English */
2752     case PM_SAMURAI:
2753         return "Sayonara"; /* Japanese */
2754     case PM_TOURIST:
2755         return "Aloha"; /* Hawaiian */
2756     case PM_VALKYRIE:
2757         return "Farvel"; /* Norse */
2758     default:
2759         return "Goodbye";
2760     }
2761 #else
2762     static char helo_buf[BUFSZ];
2763
2764     switch (Role_switch) {
2765     case PM_KNIGHT:
2766         Sprintf(helo_buf, "\82³\82ç\82Î\8chåi\82È\82é");
2767         break;
2768     case PM_SAMURAI:
2769         Sprintf(helo_buf, "\82³\82ç\82Î\95\90\8em\93¹\82ð\8eu\82·");
2770         break;
2771     case PM_TOURIST:
2772         Sprintf(helo_buf, "\83A\83\8d\81[\83n");
2773         break;
2774     case PM_VALKYRIE:
2775         Sprintf(helo_buf, "\82³\82ç\82Î\8d°\82Ì\8eç\8cì\8eÒ");
2776         break;
2777     default:
2778         Sprintf(helo_buf, "\82³\82æ\82¤\82È\82ç");
2779         break;
2780     }
2781
2782     return helo_buf;
2783 #endif
2784 }
2785
2786 /* role.c */