FANDOM


Below is the full text to role.c from the source code of SLASH'EM 0.0.7E7F2. To link to a particular line, write [[SLASH'EM 0.0.7E7F2/role.c#line123]], for example.

The latest source code for vanilla NetHack is at Source code.


The NetHack General Public License applies to screenshots, source code and other content from NetHack.
1.    /*	SCCS Id: @(#)role.c	3.4	2003/01/08	*/
2.    /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985-1999. */
3.    /* NetHack may be freely redistributed.  See license for details. */
4.    
5.    #include "hack.h"
6.    
7.    
8.    /*** Table of all roles ***/
9.    /* According to AD&D, HD for some classes (ex. Wizard) should be smaller
10.    * (4-sided for wizards).  But this is not AD&D, and using the AD&D
11.    * rule here produces an unplayable character.  Thus I have used a minimum
12.    * of an 10-sided hit die for everything.  Another AD&D change: wizards get
13.    * a minimum strength of 4 since without one you can't teleport or cast
14.    * spells. --KAA
15.    *
16.    * As the wizard has been updated (wizard patch 5 jun '96) their HD can be
17.    * brought closer into line with AD&D. This forces wizards to use magic more
18.    * and distance themselves from their attackers. --LSZ
19.    *
20.    * With the introduction of races, some hit points and energy
21.    * has been reallocated for each race.  The values assigned
22.    * to the roles has been reduced by the amount allocated to
23.    * humans.  --KMH
24.    *
25.    * God names use a leading underscore to flag goddesses.
26.    */
27.   const struct Role roles[] = {
28.   {	{"Archeologist", 0}, {
29.   	{"Digger",      0},
30.   	{"Field Worker",0},
31.   	{"Investigator",0},
32.   	{"Exhumer",     0},
33.   	{"Excavator",   0},
34.   	{"Spelunker",   0},
35.   	{"Speleologist",0},
36.   	{"Collector",   0},
37.   	{"Curator",     0} },
38.   	"Quetzalcoatl", "Camaxtli", "Huhetotl", /* Central American */
39.   	"Arc", "the College of Archeology", "the Tomb of the Toltec Kings",
40.   	PM_ARCHEOLOGIST, NON_PM, NON_PM,
41.   	PM_LORD_CARNARVON, PM_STUDENT, PM_MINION_OF_HUHETOTL,
42.   	NON_PM, PM_HUMAN_MUMMY, S_SNAKE, S_MUMMY,
43.   #if 0
44.   	ART_WEREBANE, ART_GRAYSWANDIR,
45.   #endif
46.   	ART_ORB_OF_DETECTION,
47.   	MH_HUMAN|MH_ELF|MH_DWARF|MH_GNOME|MH_HOBBIT|MH_VAMPIRE | 
48.   	  ROLE_MALE|ROLE_FEMALE | ROLE_LAWFUL|ROLE_NEUTRAL,
49.   	/* Str Int Wis Dex Con Cha */
50.   	{   7, 10, 10,  7,  7,  7 },
51.   	{  20, 20, 20, 10, 20, 10 },
52.   	/* Init   Lower  Higher */
53.   	{ 11, 0,  0, 8,  1, 0 },	/* Hit points */
54.   	{  1, 0,  0, 1,  0, 1 },14,	/* Energy */
55.   	10, 5, 0, 2, 10, A_INT, SPE_MAGIC_MAPPING,   -4
56.   },
57.   {	{"Barbarian", 0}, {
58.   	{"Plunderer",   "Plunderess"},
59.   	{"Pillager",    0},
60.   	{"Bandit",      0},
61.   	{"Brigand",     0},
62.   	{"Raider",      0},
63.   	{"Reaver",      0},
64.   	{"Slayer",      0},
65.   	{"Chieftain",   "Chieftainess"},
66.   	{"Conqueror",   "Conqueress"} },
67.   	"Mitra", "Crom", "Set", /* Hyborian */
68.   	"Bar", "the Camp of the Duali Tribe", "the Duali Oasis",
69.   	PM_BARBARIAN, NON_PM, NON_PM,
70.   	PM_PELIAS, PM_CHIEFTAIN, PM_THOTH_AMON,
71.   	PM_OGRE, PM_TROLL, S_OGRE, S_TROLL,
72.   #if 0
73.   	ART_CLEAVER, ART_DEATHSWORD,
74.   #endif
75.   	ART_HEART_OF_AHRIMAN,
76.   	MH_HUMAN|MH_ELF|MH_ORC|MH_WERE|MH_VAMPIRE | ROLE_MALE|ROLE_FEMALE |
77.   	  ROLE_NEUTRAL|ROLE_CHAOTIC,
78.   	/* Str Int Wis Dex Con Cha */
79.   	{  16,  7,  7, 15, 16,  6 },
80.   	{  30,  6,  7, 20, 30,  7 },
81.   	/* Init   Lower  Higher */
82.   	{ 14, 0,  0,10,  2, 0 },	/* Hit points */
83.   	{  1, 0,  0, 1,  0, 1 },10,	/* Energy */
84.   	10, 14, 0, 0,  8, A_INT, SPE_HASTE_SELF,      -4
85.   },
86.   {	{"Caveman", "Cavewoman"}, {
87.   	{"Troglodyte",  0},
88.   	{"Aborigine",   0},
89.   	{"Wanderer",    0},
90.   	{"Vagrant",     0},
91.   	{"Wayfarer",    0},
92.   	{"Roamer",      0},
93.   	{"Nomad",       0},
94.   	{"Rover",       0},
95.   	{"Pioneer",     0} },
96.   	"Anu", "_Ishtar", "Anshar", /* Babylonian */
97.   	"Cav", "the Caves of the Ancestors", "the Dragon's Lair",
98.   	PM_CAVEMAN, PM_CAVEWOMAN, PM_LITTLE_DOG,
99.   	PM_SHAMAN_KARNOV, PM_NEANDERTHAL, PM_CHROMATIC_DRAGON,
100.  	PM_BUGBEAR, PM_HILL_GIANT, S_HUMANOID, S_GIANT,
101.  #if 0
102.  	ART_GIANTKILLER, ART_SKULLCRUSHER,
103.  #endif
104.  	ART_SCEPTRE_OF_MIGHT,
105.  	MH_HUMAN|MH_DWARF|MH_GNOME|MH_VAMPIRE | ROLE_MALE|ROLE_FEMALE |
106.  	  ROLE_LAWFUL|ROLE_NEUTRAL,
107.  	/* Str Int Wis Dex Con Cha */
108.  	{  10,  7,  7,  7,  8,  6 },
109.  	{  30,  6,  7, 20, 30,  7 },
110.  	/* Init   Lower  Higher */
111.  	{ 14, 0,  0, 8,  2, 0 },	/* Hit points */
112.  	{  1, 0,  0, 1,  0, 1 },10,	/* Energy */
113.  	0, 12, 0, 1,  8, A_INT, SPE_DIG,             -4
114.  },
115.  {	{"Flame Mage", 0}, {
116.  	{"Spark",         0},   /* WAC was Igniter */
117.  	{"Igniter",       0},
118.  	{"Broiler",       0},   /* WAC was Igniter */
119.  	{"Combuster",     0},   /* WAC was Torcher */
120.  	{"Torcher",       0},
121.  	{"Scorcher",      0},   /* WAC was Torcher */
122.  	{"Incinerator",   0},
123.  	{"Disintegrator", 0},   /* WAC was Incinerator */
124.  	{"Flame-Master",  0} },
125.  	"Earth", "Fire", "Ash", /* Special */
126.  	"Fla", "the great Circle of Flame", "the Water Mage's Cave",
127.  	PM_FLAME_MAGE, NON_PM, PM_HELL_HOUND_PUP,
128.  	PM_HIGH_FLAME_MAGE, PM_IGNITER, PM_WATER_MAGE,
129.  	PM_WATER_ELEMENTAL, PM_RUST_MONSTER, S_ELEMENTAL, S_RUSTMONST,
130.  #if 0
131.  	ART_FIREWALL, ART_FIRE_BRAND,
132.  #endif
133.  	ART_CANDLE_OF_ETERNAL_FLAME,
134.  	MH_HUMAN|MH_ELF|MH_GNOME|MH_ORC|MH_HOBBIT | 
135.  	ROLE_MALE|ROLE_FEMALE|ROLE_LAWFUL|ROLE_NEUTRAL|ROLE_CHAOTIC,
136.  	/* Str Int Wis Dex Con Cha */  /* Direct copy from Wizard */
137.  	{   7, 10,  7,  7,  7,  7 },
138.  	{  10, 30, 10, 20, 20, 10 },
139.  	/* Init   Lower  Higher */
140.  	{ 10, 0,  0, 8,  1, 0 },	/* Hit points */
141.  	{  4, 3,  0, 2,  0, 3 },12,	/* Energy */
142.  	0, 1, 0, 
143.  	2, 10, A_INT, SPE_FIREBALL,        -4 /* From old role.c */
144.  },
145.  {	{"Healer", 0}, {
146.  	{"Rhizotomist",    0},
147.  	{"Empiric",        0},
148.  	{"Embalmer",       0},
149.  	{"Dresser",        0},
150.  	{"Medicus ossium", "Medica ossium"},
151.  	{"Herbalist",      0},
152.  	{"Magister",       "Magistra"},
153.  	{"Physician",      0},
154.  	{"Chirurgeon",     0} },
155.  	"_Athena", "Hermes", "Poseidon", /* Greek */
156.  	"Hea", "the Temple of Epidaurus", "the Temple of Coeus",
157.  	PM_HEALER, NON_PM, NON_PM,
158.  	PM_HIPPOCRATES, PM_ATTENDANT, PM_CYCLOPS,
159.  	PM_GIANT_RAT, PM_SNAKE, S_RODENT, S_YETI,
160.  #if 0
161.  	ART_DELUDER, ART_MIRRORBRIGHT,
162.  #endif
163.  	ART_STAFF_OF_AESCULAPIUS,
164.  	MH_HUMAN|MH_GNOME|MH_ELF|MH_HOBBIT | ROLE_MALE|ROLE_FEMALE |
165.  	ROLE_NEUTRAL,
166.  	/* Str Int Wis Dex Con Cha */
167.  	{   7,  7, 13,  7, 11, 16 },
168.  	{  15, 20, 20, 15, 25, 5 },
169.  	/* Init   Lower  Higher */
170.  	{ 11, 0,  0, 8,  1, 0 },	/* Hit points */
171.  	{  1, 4,  0, 1,  0, 2 },20,	/* Energy */
172.  	10, 3,-3, 2, 10, A_WIS, SPE_CURE_SICKNESS,   -4
173.  },
174.  {	{"Ice Mage", 0}, {
175.  	{"Cooler",        0},   /* WAC was Chiller */
176.  	{"Condenser",     0},   /* WAC was Chiller */
177.  	{"Chiller",       0},
178.  	{"Froster",       0},
179.  	{"Permafroster",  0},   /* WAC was Froster */
180.  	{"Icer",          0},   /* WAC was Froster */
181.  	{"Freezer",       0},
182.  	{"Sublimer",      0},   /* WAC was Freezer */
183.  	{"Ice-Master",    0} },
184.  	"Air", "Frost", "Smoke", /* Special */
185.  	"Ice", "the great Ring of Ice", "the Earth Mage's Cave",
186.  	PM_ICE_MAGE, NON_PM, PM_WINTER_WOLF_CUB,
187.  	PM_HIGH_ICE_MAGE, PM_FROSTER, PM_EARTH_MAGE,
188.  	PM_RUST_MONSTER, PM_XORN, S_RUSTMONST, S_XORN,
189.  #if 0
190.  	ART_DEEP_FREEZE, ART_FROST_BRAND,
191.  #endif
192.  	ART_STORM_WHISTLE,
193.  	MH_HUMAN|MH_ELF|MH_GNOME|MH_ORC|MH_HOBBIT|MH_VAMPIRE | 
194.  	ROLE_MALE|ROLE_FEMALE|ROLE_LAWFUL|ROLE_NEUTRAL|ROLE_CHAOTIC,
195.  	/* Str Int Wis Dex Con Cha */  /* Direct copy from Wizard */
196.  	{   7, 10,  7,  7,  7,  7 },
197.  	{  10, 30, 10, 20, 20, 10 },
198.  	/* Init   Lower  Higher */
199.  	{ 10, 0,  0, 8,  1, 0 },	/* Hit points */
200.  	{  4, 3,  0, 2,  0, 3 },12,	/* Energy */
201.  	0, 1, 0, 
202.  	2, 10, A_INT, SPE_CONE_OF_COLD,    -4 /* From old role.c */
203.  },
204.  {	{"Knight", 0}, {
205.  	{"Gallant",     0},
206.  	{"Esquire",     0},
207.  	{"Bachelor",    0},
208.  	{"Sergeant",    0},
209.  	{"Knight",      0},
210.  	{"Banneret",    0},
211.  	{"Chevalier",   "Chevaliere"},
212.  	{"Seignieur",   "Dame"},
213.  	{"Paladin",     0} },
214.  	"Lugh", "_Brigit", "Manannan Mac Lir", /* Celtic */
215.  	"Kni", "Camelot Castle", "the Isle of Glass",
216.  	PM_KNIGHT, NON_PM, PM_PONY,
217.  	PM_KING_ARTHUR, PM_PAGE, PM_IXOTH,
218.  	PM_QUASIT, PM_OCHRE_JELLY, S_IMP, S_JELLY,
219.  #if 0
220.  	ART_DRAGONBANE, ART_DEMONBANE,
221.  #endif
222.  	ART_MAGIC_MIRROR_OF_MERLIN,
223.  	MH_HUMAN | ROLE_MALE|ROLE_FEMALE | ROLE_LAWFUL,
224.  	/* Str Int Wis Dex Con Cha */
225.  	{  13,  7, 14,  8, 10, 17 },
226.  	{  30, 15, 15, 10, 20, 10 },
227.  	/* Init   Lower  Higher */
228.  	{ 14, 0,  0, 8,  2, 0 },	/* Hit points */
229.  	{  1, 4,  0, 1,  0, 2 },10,	/* Energy */
230.  	10, 8,-2, 0,  9, A_WIS, SPE_TURN_UNDEAD,     -4
231.  },
232.  {	{"Monk", 0}, {
233.  	{"Candidate",         0},
234.  	{"Novice",            0},
235.  	{"Initiate",          0},
236.  	{"Student of Stones", 0},
237.  	{"Student of Waters", 0},
238.  	{"Student of Metals", 0},
239.  	{"Student of Winds",  0},
240.  	{"Student of Fire",   0},
241.  	{"Master",            0} },
242.  	"Shan Lai Ching", "Chih Sung-tzu", "Huan Ti", /* Chinese */
243.  	"Mon", "the Monastery of Chan-Sune",
244.  	  "the Monastery of the Earth-Lord",
245.  	PM_MONK, NON_PM, NON_PM,
246.  	PM_GRAND_MASTER, PM_ABBOT, PM_MASTER_KAEN,
247.  	PM_EARTH_ELEMENTAL, PM_XORN, S_ELEMENTAL, S_XORN,
248.  #if 0
249.  	ART_GAUNTLETS_OF_DEFENSE, ART_WHISPERFEET,
250.  #endif
251.  	ART_EYES_OF_THE_OVERWORLD,
252.  	MH_HUMAN|MH_HOBBIT | ROLE_MALE|ROLE_FEMALE |
253.  	  ROLE_LAWFUL|ROLE_NEUTRAL|ROLE_CHAOTIC,
254.  	/* Str Int Wis Dex Con Cha */
255.  	{  10,  7,  8,  8,  7,  7 },
256.  	{  25, 10, 20, 20, 15, 10 },
257.  	/* Init   Lower  Higher */
258.  	{ 12, 0,  0, 8,  1, 0 },	/* Hit points */
259.  	{  2, 2,  0, 2,  0, 2 },10,	/* Energy */
260.  	10, 8,-2, 2, 20, A_WIS, SPE_RESTORE_ABILITY, -4
261.  },
262.  {	{"Necromancer", 0}, {
263.  	{"Gravedigger",  0},
264.  	{"Embalmer", 0},
265.  	{"Mortician", 0},
266.  	{"Zombie Lord", 0},
267.  	{"Ghoul Master",0},
268.  	{"Necromancer", 0},
269.  	{"Necromancer", 0},
270.  	{"Undead Master", 0},
271.  	{"Lich Lord", 0} },
272.  	"Nharlotep", "Zugguthobal", "Gothuulbe", /* Assorted slimy things */
273.  	"Nec", "the Tower of the Dark Lord", "the Lair of Maugneshaagar",
274.  	PM_NECROMANCER, NON_PM, PM_GHOUL,
275.  	PM_DARK_LORD, PM_EMBALMER, PM_MAUGNESHAAGAR,
276.  	PM_NUPPERIBO, PM_MONGBAT, S_BAT, S_IMP,
277.  #if 0
278.  	ART_SERPENT_S_TONGUE, ART_GRIMTOOTH,
279.  #endif
280.  	ART_GREAT_DAGGER_OF_GLAURGNAA,
281.  	MH_HUMAN|MH_ELF|MH_ORC|MH_VAMPIRE | ROLE_MALE|ROLE_FEMALE|ROLE_CHAOTIC,
282.  	/* Str Int Wis Dex Con Cha */  /* Direct copy from Wizard */
283.  	{   7, 10,  7,  7,  7,  7 },
284.  	{  10, 30, 10, 20, 20, 10 },
285.  	/* Init   Lower  Higher */
286.  	{ 10, 0,  0, 8,  1, 0 },	/* Hit points */
287.  	{  4, 3,  0, 2,  0, 3 },12,	/* Energy */
288.  	0, 1, 0, 
289.  	2, 10, A_INT, SPE_SUMMON_UNDEAD,   -4
290.  },
291.  {	{"Priest", "Priestess"}, {
292.  	{"Aspirant",    0},
293.  	{"Acolyte",     0},
294.  	{"Adept",       0},
295.  	{"Priest",      "Priestess"},
296.  	{"Curate",      0},
297.  	{"Canon",       "Canoness"},
298.  	{"Lama",        0},
299.  	{"Patriarch",   "Matriarch"},
300.  	{"High Priest", "High Priestess"} },
301.  	0, 0, 0,	/* chosen randomly from among the other roles */
302.  	"Pri", "the Great Temple", "the Temple of Nalzok",
303.  	PM_PRIEST, PM_PRIESTESS, NON_PM,
304.  	PM_ARCH_PRIEST, PM_ACOLYTE, PM_NALZOK,
305.  	PM_HUMAN_ZOMBIE, PM_WRAITH, S_ZOMBIE, S_WRAITH,
306.  #if 0
307.  	ART_DISRUPTER, ART_SUNSWORD,
308.  #endif
309.  	ART_MITRE_OF_HOLINESS,
310.  	MH_HUMAN|MH_ELF|MH_HOBBIT | ROLE_MALE|ROLE_FEMALE |
311.  	  ROLE_LAWFUL|ROLE_NEUTRAL|ROLE_CHAOTIC,
312.  	/* Str Int Wis Dex Con Cha */
313.  	{   7,  7, 10,  7,  7,  7 },
314.  	{  15, 10, 30, 15, 20, 10 },
315.  	/* Init   Lower  Higher */
316.  	{ 12, 0,  0, 8,  1, 0 },	/* Hit points */
317.  	{  4, 3,  0, 2,  0, 2 },10,	/* Energy */
318.  	0, 3,-2, 2, 10, A_WIS, SPE_REMOVE_CURSE,    -4
319.  },
320.    /* Note:  Rogue precedes Ranger so that use of `-R' on the command line
321.       retains its traditional meaning. */
322.  {	{"Rogue", 0}, {
323.  	{"Footpad",     0},
324.  	{"Cutpurse",    0},
325.  	{"Rogue",       0},
326.  	{"Pilferer",    0},
327.  	{"Robber",      0},
328.  	{"Burglar",     0},
329.  	{"Filcher",     0},
330.  	{"Magsman",     "Magswoman"},
331.  	{"Thief",       0} },
332.  	"Issek", "Mog", "Kos", /* Nehwon */
333.  	"Rog", "the Thieves' Guild Hall", "the Assassins' Guild Hall",
334.  	PM_ROGUE, NON_PM, NON_PM,
335.  	PM_MASTER_OF_THIEVES, PM_THUG, PM_MASTER_ASSASSIN,
336.  	PM_LEPRECHAUN, PM_GUARDIAN_NAGA, S_NYMPH, S_NAGA,
337.  #if 0
338.  	ART_DOOMBLADE, ART_BAT_FROM_HELL,
339.  #endif
340.  	ART_MASTER_KEY_OF_THIEVERY,
341.  	MH_HUMAN|MH_ORC|MH_WERE|MH_VAMPIRE | ROLE_MALE|ROLE_FEMALE |
342.  	  ROLE_CHAOTIC,
343.  	/* Str Int Wis Dex Con Cha */
344.  	{   7,  7,  7, 10,  7,  6 },
345.  	{  20, 10, 10, 30, 20, 10 },
346.  	/* Init   Lower  Higher */
347.  	{ 10, 0,  0, 8,  1, 0 },	/* Hit points */
348.  	{  1, 0,  0, 1,  0, 1 },11,	/* Energy */
349.  	10, 8, 0, 1,  9, A_INT, SPE_DETECT_TREASURE, -4
350.  },
351.  {	{"Ranger", 0}, {
352.  #if 0	/* OBSOLETE */
353.  	{"Edhel",       "Elleth"},
354.  	{"Edhel",       "Elleth"},      /* elf-maid */
355.  	{"Ohtar",       "Ohtie"},       /* warrior */
356.  	{"Kano",			/* commander (Q.) ['a] */
357.  			"Kanie"},	/* educated guess, until further research- SAC */
358.  	{"Arandur",			/* king's servant, minister (Q.) - guess */
359.  			"Aranduriel"},	/* educated guess */
360.  	{"Hir",         "Hiril"},       /* lord, lady (S.) ['ir] */
361.  	{"Aredhel",     "Arwen"},       /* noble elf, maiden (S.) */
362.  	{"Ernil",       "Elentariel"},  /* prince (S.), elf-maiden (Q.) */
363.  	{"Elentar",     "Elentari"},	/* Star-king, -queen (Q.) */
364.  	"Solonor Thelandira", "Aerdrie Faenya", "Lolth", /* Elven */
365.  #endif
366.  	{"Tenderfoot",    0},
367.  	{"Lookout",       0},
368.  	{"Trailblazer",   0},
369.  	{"Reconnoiterer", "Reconnoiteress"},
370.  	{"Scout",         0},
371.  	{"Arbalester",    0},	/* One skilled at crossbows */
372.  	{"Archer",        0},
373.  	{"Sharpshooter",  0},
374.  	{"Marksman",      "Markswoman"} },
375.  	"Mercury", "_Venus", "Mars", /* Roman/planets */
376.  	"Ran", "Orion's camp", "the cave of the wumpus",
377.  	PM_RANGER, NON_PM, PM_LITTLE_DOG /* Orion & canis major */,
378.  	PM_ORION, PM_HUNTER, PM_SCORPIUS,
379.  	PM_FOREST_CENTAUR, PM_SCORPION, S_CENTAUR, S_SPIDER,
380.  #if 0
381.  	0, 0,
382.  #endif
383.  	ART_LONGBOW_OF_DIANA,
384.  	MH_HUMAN|MH_ELF|MH_GNOME|MH_ORC|MH_WERE|MH_HOBBIT |
385.  	ROLE_MALE|ROLE_FEMALE | ROLE_NEUTRAL|ROLE_CHAOTIC,
386.  	/* Str Int Wis Dex Con Cha */
387.  	{  13, 13, 13,  9, 13,  7 },
388.  	{  30, 10, 10, 20, 20, 10 },
389.  	/* Init   Lower  Higher */
390.  	{ 13, 0,  0, 6,  1, 0 },	/* Hit points */
391.  	{  1, 0,  0, 1,  0, 1 },12,	/* Energy */
392.  	10, 9, 2, 1, 10, A_INT, SPE_INVISIBILITY,   -4
393.  },
394.  {	{"Samurai", 0}, {
395.  	{"Hatamoto",    0},  /* Banner Knight */
396.  	{"Ronin",       0},  /* no allegiance */
397.  	{"Ninja",       "Kunoichi"},  /* secret society */
398.  	{"Joshu",       0},  /* heads a castle */
399.  	{"Ryoshu",      0},  /* has a territory */
400.  	{"Kokushu",     0},  /* heads a province */
401.  	{"Daimyo",      0},  /* a samurai lord */
402.  	{"Kuge",        0},  /* Noble of the Court */
403.  	{"Shogun",      0} },/* supreme commander, warlord */
404.  	"_Amaterasu Omikami", "Raijin", "Susanowo", /* Japanese */
405.  	"Sam", "the Castle of the Taro Clan", "the Shogun's Castle",
406.  	PM_SAMURAI, NON_PM, PM_LITTLE_DOG,
407.  	PM_LORD_SATO, PM_ROSHI, PM_ASHIKAGA_TAKAUJI,
408.  	PM_WOLF, PM_STALKER, S_DOG, S_ELEMENTAL,
409.  #if 0
410.  	ART_SNICKERSNEE, ART_DRAGONBANE,
411.  #endif
412.  	ART_TSURUGI_OF_MURAMASA,
413.  	MH_HUMAN | ROLE_MALE|ROLE_FEMALE | ROLE_LAWFUL,
414.  	/* Str Int Wis Dex Con Cha */
415.  	{  10,  8,  7, 10, 17,  6 },
416.  	{  30, 10,  8, 30, 14,  8 },
417.  	/* Init   Lower  Higher */
418.  	{ 13, 0,  0, 8,  1, 0 },	/* Hit points */
419.  	{  1, 0,  0, 1,  0, 1 },11,	/* Energy */
420.  	10, 10, 0, 0,  8, A_INT, SPE_CLAIRVOYANCE,    -4
421.  },
422.  #ifdef TOURIST
423.  {	{"Tourist", 0}, {
424.  	{"Rambler",     0},
425.  	{"Sightseer",   0},
426.  	{"Excursionist",0},
427.  	{"Peregrinator","Peregrinatrix"},
428.  	{"Traveler",    0},
429.  	{"Journeyer",   0},
430.  	{"Voyager",     0},
431.  	{"Explorer",    0},
432.  	{"Adventurer",  0} },
433.  	"Blind Io", "_The Lady", "Offler", /* Discworld */
434.  	"Tou", "Ankh-Morpork", "the Thieves' Guild Hall",
435.  	PM_TOURIST, NON_PM, NON_PM,
436.  	PM_TWOFLOWER, PM_GUIDE, PM_MASTER_OF_THIEVES,
437.  	PM_GIANT_SPIDER, PM_FOREST_CENTAUR, S_SPIDER, S_CENTAUR,
438.  #if 0
439.  	ART_WHISPERFEET, ART_LUCKBLADE,
440.  #endif
441.  	ART_YENDORIAN_EXPRESS_CARD,
442.  	MH_HUMAN|MH_HOBBIT | ROLE_MALE|ROLE_FEMALE | ROLE_NEUTRAL,
443.  	/* Str Int Wis Dex Con Cha */
444.  	{   7, 10,  6,  7,  7, 10 },
445.  	{  15, 10, 10, 15, 30, 20 },
446.  	/* Init   Lower  Higher */
447.  	{  8, 0,  0, 8,  0, 0 },	/* Hit points */
448.  	{  1, 0,  0, 1,  0, 1 },14,	/* Energy */
449.  	0, 5, 1, 2, 10, A_INT, SPE_CHARM_MONSTER,   -4
450.  },
451.  #endif
452.  {	{"Undead Slayer", 0}, {
453.  	{"Assistant",    0},
454.  	{"Eliminator",   0},
455.  	{"Eliminator",   0},
456.  	{"Exterminator", 0},
457.  	{"Exterminator", 0},
458.  	{"Destroyer",   0},
459.  	{"Vindicator",  0},
460.  	{"Vindicator",  0},
461.  	{"Undead Slayer", 0} },
462.  	"Seeker", "Osiris", "Seth", /* Egyptian */
463.  	"Und", "the Temple of Light", "the Crypt of Dracula",
464.  	PM_UNDEAD_SLAYER, NON_PM, NON_PM,
465.  	PM_VAN_HELSING, PM_EXTERMINATOR, PM_COUNT_DRACULA,
466.  	PM_HUMAN_MUMMY, PM_VAMPIRE, S_MUMMY, S_VAMPIRE,
467.  #if 0
468.  	ART_HOLY_SPEAR_OF_LIGHT, ART_SUNSWORD,
469.  #endif
470.  	ART_STAKE_OF_VAN_HELSING,
471.  	MH_HUMAN|MH_ELF|MH_GNOME|MH_ORC|MH_WERE|MH_HOBBIT |
472.  	ROLE_MALE|ROLE_FEMALE | ROLE_LAWFUL|ROLE_NEUTRAL|ROLE_CHAOTIC,
473.  	/* Str Int Wis Dex Con Cha */ /* Modified from Knight */
474.  	{  13,  7, 14,  8, 10, 10 },
475.  	{  20, 15, 15, 10, 20, 10 },
476.  	/* Init   Lower  Higher */
477.  	{ 14, 0,  0, 8,  2, 0 },	/* Hit points */
478.  	{  1, 4,  0, 1,  0, 2 },10,	/* Energy */
479.  	10, 8,-2, 0,  9, A_WIS, SPE_TURN_UNDEAD,     -4
480.  },
481.  {	{"Valkyrie", 0}, {
482.  	{"Stripling",   0},
483.  	{"Skirmisher",  0},
484.  	{"Fighter",     0},
485.  	{"Man-at-arms", "Woman-at-arms"},
486.  	{"Warrior",     0},
487.  	{"Swashbuckler",0},
488.  	{"Hero",        "Heroine"},
489.  	{"Champion",    0},
490.  	{"Lord",        "Lady"} },
491.  	"Tyr", "Odin", "Loki", /* Norse */
492.  	"Val", "the Shrine of Destiny", "the cave of Surtur",
493.  	PM_VALKYRIE, NON_PM, NON_PM /*PM_WINTER_WOLF_CUB*/,
494.  	PM_NORN, PM_WARRIOR, PM_LORD_SURTUR,
495.  	PM_FIRE_ANT, PM_FIRE_GIANT, S_ANT, S_GIANT,
496.  #if 0
497.  	ART_MJOLLNIR, ART_FROST_BRAND,
498.  #endif
499.  	ART_ORB_OF_FATE,
500.  	MH_HUMAN|MH_DWARF | ROLE_FEMALE | ROLE_LAWFUL|ROLE_NEUTRAL,
501.  	/* Str Int Wis Dex Con Cha */
502.  	{  10,  7,  7,  7, 12,  7 },
503.  	{  30,  6,  7, 20, 30,  7 },
504.  	/* Init   Lower  Higher */
505.  	{ 14, 0,  0, 8,  2, 0 },	/* Hit points */
506.  	{  1, 0,  0, 1,  0, 1 },10,	/* Energy */
507.  	0, 10,-2, 0,  9, A_WIS, SPE_LIGHTNING,    -4
508.  },
509.  {	{"Wizard", 0}, {
510.  	{"Evoker",      0},
511.  	{"Conjurer",    0},
512.  	{"Thaumaturge", 0},
513.  	{"Magician",    0},
514.  	{"Warlock",     "Witch"},
515.  	{"Enchanter",   "Enchantress"},
516.  	{"Sorcerer",    "Sorceress"},
517.  	{"Wizard",      0},
518.  	{"Mage",        0} },
519.  	"Ptah", "Thoth", "Anhur", /* Egyptian */
520.  	"Wiz", "the Lonely Tower", "the Tower of Darkness",
521.  	PM_WIZARD, NON_PM, PM_KITTEN,
522.  	PM_NEFERET_THE_GREEN, PM_APPRENTICE, PM_DARK_ONE,
523.  	PM_VAMPIRE_BAT, PM_XORN, S_BAT, S_WRAITH,
524.  #if 0
525.  	ART_MAGICBANE, ART_DELUDER,
526.  #endif
527.  	ART_EYE_OF_THE_AETHIOPICA,
528.  	MH_HUMAN|MH_ELF|MH_GNOME|MH_ORC|MH_HOBBIT|MH_VAMPIRE | ROLE_MALE|ROLE_FEMALE |
529.  	  ROLE_NEUTRAL|ROLE_CHAOTIC,
530.  	/* Str Int Wis Dex Con Cha */
531.  	{   7, 10,  7,  7,  7,  7 },
532.  	{  10, 30, 10, 20, 20, 10 },
533.  	/* Init   Lower  Higher */
534.  	{ 10, 0,  0, 8,  1, 0 },	/* Hit points */
535.  	{  4, 3,  0, 2,  0, 3 },12,	/* Energy */
536.  	0, 1, 0, 3, 10, A_INT, SPE_MAGIC_MISSILE,   -4
537.  },
538.  #ifdef YEOMAN
539.  {	{"Yeoman", 0}, {
540.  	/* Landowner titles, naval ranks and positions */
541.  	/* We intentionally avoid Lieutenant and Captain */
542.  	{"Usher",          0},
543.  	{"Steward",        "Stewardess"},
544.  	{"Keeper",         0},
545.  	{"Marshal",        0},
546.  	{"Master Steward", "Master Stewardess"},
547.  	{"Chamberlain",    0},
548.  	{"Constable",      0},
549.  	{"Chancellor",     0},
550.  	{"Regent",         0} },
551.  	"His Majesty", "His Holiness", "The Commons", /* The three estates */
552.  	"Yeo", "London", "the inner ward",
553.  	PM_YEOMAN, NON_PM, PM_PONY,
554.  	PM_CHIEF_YEOMAN_WARDER, PM_YEOMAN_WARDER, PM_COLONEL_BLOOD,
555.  	PM_RAVEN, PM_WEREWOLF, S_RODENT, S_DOG,
556.  #if 0
557.  	ART_REAPER, ART_SWORD_OF_JUSTICE,
558.  #endif
559.  	ART_CROWN_OF_SAINT_EDWARD,
560.  	MH_HUMAN|MH_ELF|MH_HOBBIT | ROLE_MALE|ROLE_LAWFUL,
561.  	/* Str Int Wis Dex Con Cha */
562.  	{  12,  7, 10, 12, 12,  7 },
563.  	{  20, 15, 15, 10, 20, 10 },
564.  	/* Init   Lower  Higher */
565.  	{ 14, 0,  0, 8,  2, 0 },	/* Hit points */
566.  	{  1, 4,  0, 1,  0, 2 },10,	/* Energy */
567.  	10, 8,-2, 0,  9, A_WIS, SPE_KNOCK,     -4
568.  },
569.  #endif
570.  /* Array terminator */
571.  {{0, 0}}
572.  };
573.  
574.  
575.  /* The player's role, created at runtime from initial
576.   * choices.  This may be munged in role_init().
577.   */
578.  struct Role urole =
579.  {	{"Undefined", 0}, { {0, 0}, {0, 0}, {0, 0},
580.  	{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0} },
581.  	"L", "N", "C", "Xxx", "home", "locate",
582.  	NON_PM, NON_PM, NON_PM, NON_PM, NON_PM, NON_PM,
583.  	NON_PM, NON_PM, 0, 0, 
584.  #if 0
585.  	0, 0,
586.  #endif
587.  	0, 0,
588.  	/* Str Int Wis Dex Con Cha */
589.  	{   7,  7,  7,  7,  7,  7 },
590.  	{  20, 15, 15, 20, 20, 10 },
591.  	/* Init   Lower  Higher */
592.  	{ 10, 0,  0, 8,  1, 0 },	/* Hit points */
593.  	{  2, 0,  0, 2,  0, 3 },14,	/* Energy */
594.  	0, 10, 0, 0,  4, A_INT, 0, -3
595.  };
596.  
597.  /* Table of all races */
598.  const struct Race races[] = {
599.  {	"doppelganger", "doppelganger", "doppelganger-kind", "Dop",
600.  	{0, 0},
601.  	PM_DOPPELGANGER, NON_PM, PM_HUMAN_MUMMY, PM_HUMAN_ZOMBIE,
602.  	MH_HUMAN | ROLE_MALE|ROLE_FEMALE | ROLE_NEUTRAL|ROLE_CHAOTIC,
603.  	MH_HUMAN, MH_WERE, MH_ELF|MH_GNOME|MH_DWARF,
604.  	/*    Str     Int Wis Dex Con Cha */
605.  	{      1,      3,  3,  1,  1,  1 },
606.  	{ STR18(100), 20, 20, 20, 20, 15 },
607.  	/* Init   Lower  Higher */
608.  	{  0, 0,  0, 1,  1, 0 },	/* Hit points */
609.  	{  7, 0,  5, 0,  5, 0 }		/* Energy */
610.  },
611.  {	"drow", "droven", "drovenkind", "Dro",
612.  	{0, 0},
613.  	PM_DROW, NON_PM, PM_ELF_MUMMY, PM_ELF_ZOMBIE,
614.  	MH_ELF | ROLE_MALE|ROLE_FEMALE | ROLE_CHAOTIC,
615.  	MH_ELF, MH_ELF, MH_ORC,
616.  	/*  Str    Int Wis Dex Con Cha */
617.  	{    3,     3,  3,  3,  3,  3 },
618.  	{   18,    20, 20, 18, 16, 18 },
619.  	/* Init   Lower  Higher */
620.  	{  1, 0,  0, 1,  1, 0 },	/* Hit points */
621.  	{  2, 0,  3, 0,  3, 0 }		/* Energy */
622.  },
623.  {	"dwarf", "dwarven", "dwarvenkind", "Dwa",
624.  	{0, 0},
625.  	PM_DWARF, NON_PM, PM_DWARF_MUMMY, PM_DWARF_ZOMBIE,
626.  	MH_DWARF | ROLE_MALE|ROLE_FEMALE | ROLE_LAWFUL,
627.  	MH_DWARF, MH_DWARF|MH_GNOME, MH_ORC,
628.  	/*    Str     Int Wis Dex Con Cha */
629.  	{      3,      3,  3,  3,  3,  3 },
630.  	{ STR18(100), 16, 16, 20, 20, 16 },
631.  	/* Init   Lower  Higher */
632.  	{  4, 0,  0, 3,  2, 0 },	/* Hit points */
633.  	{  0, 0,  0, 0,  0, 0 }		/* Energy */
634.  },
635.  {	"elf", "elven", "elvenkind", "Elf",
636.  	{0, 0},
637.  	PM_ELF, NON_PM, PM_ELF_MUMMY, PM_ELF_ZOMBIE,
638.  	MH_ELF | ROLE_MALE|ROLE_FEMALE | ROLE_LAWFUL|ROLE_NEUTRAL,
639.  	MH_ELF, MH_ELF, MH_ORC,
640.  	/*  Str    Int Wis Dex Con Cha */
641.  	{    3,     3,  3,  3,  3,  3 },
642.  	{   18,    20, 20, 18, 16, 18 },
643.  	/* Init   Lower  Higher */
644.  	{  1, 0,  0, 1,  1, 0 },	/* Hit points */
645.  	{  2, 0,  3, 0,  3, 0 }		/* Energy */
646.  },
647.  {	"gnome", "gnomish", "gnomehood", "Gno",
648.  	{0, 0},
649.  	PM_GNOME, NON_PM, PM_GNOME_MUMMY, PM_GNOME_ZOMBIE,
650.  	MH_GNOME | ROLE_MALE|ROLE_FEMALE | ROLE_NEUTRAL,
651.  	MH_GNOME, MH_DWARF|MH_GNOME, MH_HUMAN|MH_HOBBIT,
652.  	/*  Str    Int Wis Dex Con Cha */
653.  	{    3,     3,  3,  3,  3,  3 },
654.  	{STR18(50),19, 18, 18, 18, 18 },
655.  	/* Init   Lower  Higher */
656.  	{  1, 0,  0, 1,  0, 0 },	/* Hit points */
657.  	{  2, 0,  2, 0,  2, 0 }		/* Energy */
658.  },
659.  {	"hobbit", "hobbit", "hobbit-kind", "Hob",
660.  	{0, 0},
661.  	PM_HOBBIT, NON_PM, NON_PM, NON_PM,
662.  	MH_HOBBIT | ROLE_MALE|ROLE_FEMALE | ROLE_LAWFUL|ROLE_NEUTRAL,
663.  	MH_HOBBIT, MH_HOBBIT, MH_GNOME|MH_ORC,
664.  	/*  Str    Int Wis Dex Con Cha */
665.  	{   3,      3,  3,  3,  3,  3 },
666.  	{  18,     16, 18, 18, 20, 20 },
667.  	/* Init   Lower  Higher */
668.  	{  2, 0,  0, 2,  1, 0 },	/* Hit points */
669.  	{  2, 0,  2, 1,  2, 0 }		/* Energy */
670.  },
671.  {	"human", "human", "humanity", "Hum",
672.  	{"man", "woman"},
673.  	PM_HUMAN, NON_PM, PM_HUMAN_MUMMY, PM_HUMAN_ZOMBIE,
674.  	MH_HUMAN | ROLE_MALE|ROLE_FEMALE |
675.  	  ROLE_LAWFUL|ROLE_NEUTRAL|ROLE_CHAOTIC,
676.  	MH_HUMAN, 0, MH_GNOME|MH_ORC,
677.  	/*    Str     Int Wis Dex Con Cha */
678.  	{      3,      3,  3,  3,  3,  3 },
679.  	{ STR18(100), 18, 18, 18, 18, 18 },
680.  	/* Init   Lower  Higher */
681.  	{  2, 0,  0, 2,  1, 0 },	/* Hit points */
682.  	{  1, 0,  2, 0,  2, 0 }		/* Energy */
683.  },
684.  {	"lycanthrope", "lycanthropic", "lycanthropehood", "Lyc",
685.  	{0, 0},
686.  	PM_HUMAN_WEREWOLF, NON_PM, PM_HUMAN_MUMMY, PM_HUMAN_ZOMBIE,
687.  	MH_WERE | ROLE_MALE|ROLE_FEMALE | ROLE_CHAOTIC,
688.  	MH_WERE, 0, MH_ELF|MH_GNOME|MH_DWARF,
689.  	/*    Str     Int Wis Dex Con Cha */
690.  	{      4,      1,  1,  4,  4,  2 },
691.  	{ STR19(19), 15, 15, 20, 19, 15 },
692.  	/* Init   Lower  Higher */
693.  	{  4, 0,  0, 2,  2, 0 },	/* Hit points */
694.  	{  5, 0,  4, 0,  4, 0 }		/* Energy */
695.  },
696.  {	"orc", "orcish", "orcdom", "Orc",
697.  	{0, 0},
698.  	PM_ORC, NON_PM, PM_ORC_MUMMY, PM_ORC_ZOMBIE,
699.  	MH_ORC | ROLE_MALE|ROLE_FEMALE | ROLE_CHAOTIC,
700.  	MH_ORC, 0, MH_HUMAN|MH_ELF|MH_DWARF|MH_HOBBIT,
701.  	/*  Str    Int Wis Dex Con Cha */
702.  	{   3,      3,  3,  3,  3,  3 },
703.  	{STR18(50),16, 16, 18, 18, 16 },
704.  	/* Init   Lower  Higher */
705.  	{  1, 0,  0, 1,  0, 0 },	/* Hit points */
706.  	{  1, 0,  1, 0,  1, 0 }		/* Energy */
707.  },
708.  {	"vampire", "vampiric", "vampirehood", "Vam",
709.  	{0, 0},
710.  	PM_VAMPIRE, NON_PM, PM_HUMAN_MUMMY, PM_HUMAN_ZOMBIE,
711.  	MH_VAMPIRE | ROLE_MALE|ROLE_FEMALE | ROLE_CHAOTIC,
712.  	MH_VAMPIRE, 0, MH_ELF|MH_GNOME|MH_HOBBIT|MH_DWARF|MH_ORC,
713.  	/*    Str     Int Wis Dex Con Cha */
714.  	{      4,      0,  0,  4,  3,  4 },
715.  	{ STR19(19), 18, 18, 20, 20, 20 },
716.  	/* Init   Lower  Higher */
717.  	{  3, 0,  0, 3,  2, 0 },	/* Hit points */
718.  	{  3, 0,  4, 0,  4, 0 }		/* Energy */
719.  },
720.  /* Array terminator */
721.  { 0, 0, 0, 0 }};
722.  
723.  
724.  /* The player's race, created at runtime from initial
725.   * choices.  This may be munged in role_init().
726.   */
727.  struct Race urace =
728.  {	"something", "undefined", "something", "Xxx",
729.  	{0, 0},
730.  	NON_PM, NON_PM, NON_PM, NON_PM,
731.  	0, 0, 0, 0,
732.  	/*    Str     Int Wis Dex Con Cha */
733.  	{      3,      3,  3,  3,  3,  3 },
734.  	{ STR18(100), 18, 18, 18, 18, 18 },
735.  	/* Init   Lower  Higher */
736.  	{  2, 0,  0, 2,  1, 0 },	/* Hit points */
737.  	{  1, 0,  2, 0,  2, 0 }		/* Energy */
738.  };
739.  
740.  /* Table of all genders */
741.  const struct Gender genders[] = {
742.  	{"male",	"he",	"him",	"his",	"Mal",	ROLE_MALE},
743.  	{"female",	"she",	"her",	"her",	"Fem",	ROLE_FEMALE},
744.  	{"neuter",	"it",	"it",	"its",	"Ntr",	ROLE_NEUTER}
745.  };
746.  
747.  #ifdef MAC_MPW
748.  const size_t maxGender = sizeof genders/sizeof genders[0];
749.  #endif /* MAC_MPW */
750.  
751.  /* Table of all alignments */
752.  const struct Align aligns[] = {
753.  	{"law",		"lawful",	"Law",	ROLE_LAWFUL,	A_LAWFUL},
754.  	{"balance",	"neutral",	"Neu",	ROLE_NEUTRAL,	A_NEUTRAL},
755.  	{"chaos",	"chaotic",	"Cha",	ROLE_CHAOTIC,	A_CHAOTIC},
756.  	{"evil",	"unaligned",	"Una",	0,		A_NONE}
757.  };
758.  
759.  STATIC_DCL char * FDECL(promptsep, (char *, int));
760.  STATIC_DCL int FDECL(role_gendercount, (int));
761.  STATIC_DCL int FDECL(race_alignmentcount, (int));
762.  
763.  /* used by str2XXX() */
764.  static char NEARDATA randomstr[] = "random";
765.  
766.  #ifdef MAC_MPW
767.  const size_t maxAlign = sizeof aligns/sizeof aligns[0];
768.  #endif /* MAC_MPW */
769.  
770.  boolean
771.  validrole(rolenum)
772.  	int rolenum;
773.  {
774.  	return (rolenum >= 0 && rolenum < SIZE(roles)-1);
775.  }
776.  
777.  
778.  int
779.  randrole()
780.  {
781.  	return (rn2(SIZE(roles)-1));
782.  }
783.  
784.  
785.  int
786.  str2role(str)
787.  	char *str;
788.  {
789.  	int i, len;
790.  
791.  	/* Is str valid? */
792.  	if (!str || !str[0])
793.  	    return ROLE_NONE;
794.  
795.  	/* Match as much of str as is provided */
796.  	len = strlen(str);
797.  	for (i = 0; roles[i].name.m; i++) {
798.  	    /* Does it match the male name? */
799.  	    if (!strncmpi(str, roles[i].name.m, len))
800.  		return i;
801.  	    /* Or the female name? */
802.  	    if (roles[i].name.f && !strncmpi(str, roles[i].name.f, len))
803.  		return i;
804.  	    /* Or the filecode? */
805.  	    if (!strcmpi(str, roles[i].filecode))
806.  		return i;
807.  	}
808.  
809.  	if ((len == 1 && (*str == '*' || *str == '@')) ||
810.  		!strncmpi(str, randomstr, len))
811.  	    return ROLE_RANDOM;
812.  
813.  	/* Couldn't find anything appropriate */
814.  	return ROLE_NONE;
815.  }
816.  
817.  
818.  boolean
819.  validrace(rolenum, racenum)
820.  	int rolenum, racenum;
821.  {
822.  	/* Assumes validrole */
823.  	/* WAC -- checks ROLE_GENDMASK and ROLE_ALIGNMASK as well (otherwise, there 
824.  	 * might not be an allowed gender or alignment for that role
825.  	 */
826.  	return (racenum >= 0 && racenum < SIZE(races)-1 &&
827.  		(roles[rolenum].allow & races[racenum].allow & ROLE_RACEMASK) &&
828.  		(roles[rolenum].allow & races[racenum].allow & ROLE_GENDMASK) &&
829.  		(roles[rolenum].allow & races[racenum].allow & ROLE_ALIGNMASK));
830.  }
831.  
832.  
833.  int
834.  randrace(rolenum)
835.  	int rolenum;
836.  {
837.  	int i, n = 0;
838.  
839.  	/* Count the number of valid races */
840.  	for (i = 0; races[i].noun; i++)
841.  /*	    if (roles[rolenum].allow & races[i].allow & ROLE_RACEMASK)*/
842.  	    if (validrace(rolenum,i))
843.  	    	n++;
844.  
845.  	/* Pick a random race */
846.  	/* Use a factor of 100 in case of bad random number generators */
847.  	if (n) n = rn2(n*100)/100;
848.  	for (i = 0; races[i].noun; i++)
849.  /*	    if (roles[rolenum].allow & races[i].allow & ROLE_RACEMASK) {*/
850.  	    if (validrace(rolenum,i)) {
851.  	    	if (n) n--;
852.  	    	else return (i);
853.  	    }
854.  
855.  	/* This role has no permitted races? */
856.  	return (rn2(SIZE(races)-1));
857.  }
858.  
859.  /*
860.   * [ALI] Find the player equivalent race for a monster from its M2 flags.
861.   */
862.  
863.  int
864.  mrace2race(mflags2)
865.  	int mflags2;
866.  {
867.  	int i;
868.  
869.  	/* Look for a race with the correct selfmask */
870.  	for (i = 0; races[i].noun; i++)
871.  	    if (mflags2 & races[i].selfmask) {
872.  		/* Where more than one player race has the same monster race,
873.  		 * return the base race.
874.  		 */
875.  		if (mflags2 & MH_HUMAN && races[i].malenum != PM_HUMAN)
876.  		    continue;
877.  		if (mflags2 & MH_ELF && races[i].malenum != PM_ELF)
878.  		    continue;
879.  		return i;
880.  	    }
881.  	return ROLE_NONE;
882.  }
883.  
884.  int
885.  str2race(str)
886.  	char *str;
887.  {
888.  	int i, len;
889.  
890.  	/* Is str valid? */
891.  	if (!str || !str[0])
892.  	    return ROLE_NONE;
893.  
894.  	/* Match as much of str as is provided */
895.  	len = strlen(str);
896.  	for (i = 0; races[i].noun; i++) {
897.  	    /* Does it match the noun? */
898.  	    if (!strncmpi(str, races[i].noun, len))
899.  		return i;
900.  	    /* Or the filecode? */
901.  	    if (!strcmpi(str, races[i].filecode))
902.  		return i;
903.  	}
904.  
905.  	if ((len == 1 && (*str == '*' || *str == '@')) ||
906.  		!strncmpi(str, randomstr, len))
907.  	    return ROLE_RANDOM;
908.  
909.  	/* Couldn't find anything appropriate */
910.  	return ROLE_NONE;
911.  }
912.  
913.  
914.  boolean
915.  validgend(rolenum, racenum, gendnum)
916.  	int rolenum, racenum, gendnum;
917.  {
918.  	/* Assumes validrole and validrace */
919.  	return (gendnum >= 0 && gendnum < ROLE_GENDERS &&
920.  		(roles[rolenum].allow & races[racenum].allow &
921.  		 genders[gendnum].allow & ROLE_GENDMASK));
922.  }
923.  
924.  
925.  int
926.  randgend(rolenum, racenum)
927.  	int rolenum, racenum;
928.  {
929.  	int i, n = 0;
930.  
931.  	/* Count the number of valid genders */
932.  	for (i = 0; i < ROLE_GENDERS; i++)
933.  /*	    if (roles[rolenum].allow & races[racenum].allow &
934.  	    		genders[i].allow & ROLE_GENDMASK) */
935.  	    if (validgend(rolenum, racenum, i))
936.  	    	n++;
937.  
938.  	/* Pick a random gender */
939.  	if (n) n = rn2(n);
940.  	for (i = 0; i < ROLE_GENDERS; i++)
941.  /*	    if (roles[rolenum].allow & races[racenum].allow &
942.  	    		genders[i].allow & ROLE_GENDMASK) {*/
943.  	    if (validgend(rolenum, racenum, i)) {
944.  	    	if (n) n--;
945.  	    	else return (i);
946.  	    }
947.  
948.  	/* This role/race has no permitted genders? */
949.  	return (rn2(ROLE_GENDERS));
950.  }
951.  
952.  
953.  int
954.  str2gend(str)
955.  	char *str;
956.  {
957.  	int i, len;
958.  
959.  	/* Is str valid? */
960.  	if (!str || !str[0])
961.  	    return ROLE_NONE;
962.  
963.  	/* Match as much of str as is provided */
964.  	len = strlen(str);
965.  	for (i = 0; i < ROLE_GENDERS; i++) {
966.  	    /* Does it match the adjective? */
967.  	    if (!strncmpi(str, genders[i].adj, len))
968.  		return i;
969.  	    /* Or the filecode? */
970.  	    if (!strcmpi(str, genders[i].filecode))
971.  		return i;
972.  	}
973.  	if ((len == 1 && (*str == '*' || *str == '@')) ||
974.  		!strncmpi(str, randomstr, len))
975.  	    return ROLE_RANDOM;
976.  
977.  	/* Couldn't find anything appropriate */
978.  	return ROLE_NONE;
979.  }
980.  
981.  
982.  boolean
983.  validalign(rolenum, racenum, alignnum)
984.  	int rolenum, racenum, alignnum;
985.  {
986.  	/* Assumes validrole and validrace */
987.  	return (alignnum >= 0 && alignnum < ROLE_ALIGNS &&
988.  		(roles[rolenum].allow & races[racenum].allow &
989.  		 aligns[alignnum].allow & ROLE_ALIGNMASK));
990.  }
991.  
992.  
993.  int
994.  randalign(rolenum, racenum)
995.  	int rolenum, racenum;
996.  {
997.  	int i, n = 0;
998.  
999.  	/* Count the number of valid alignments */
1000. 	for (i = 0; i < ROLE_ALIGNS; i++)
1001. 	    if (roles[rolenum].allow & races[racenum].allow &
1002. 	    		aligns[i].allow & ROLE_ALIGNMASK)
1003. 	    	n++;
1004. 
1005. 	/* Pick a random alignment */
1006. 	if (n) n = rn2(n);
1007. 	for (i = 0; i < ROLE_ALIGNS; i++)
1008. 	    if (roles[rolenum].allow & races[racenum].allow &
1009. 	    		aligns[i].allow & ROLE_ALIGNMASK) {
1010. 	    	if (n) n--;
1011. 	    	else return (i);
1012. 	    }
1013. 
1014. 	/* This role/race has no permitted alignments? */
1015. 	return (rn2(ROLE_ALIGNS));
1016. }
1017. 
1018. 
1019. int
1020. str2align(str)
1021. 	char *str;
1022. {
1023. 	int i, len;
1024. 
1025. 	/* Is str valid? */
1026. 	if (!str || !str[0])
1027. 	    return ROLE_NONE;
1028. 
1029. 	/* Match as much of str as is provided */
1030. 	len = strlen(str);
1031. 	for (i = 0; i < ROLE_ALIGNS; i++) {
1032. 	    /* Does it match the adjective? */
1033. 	    if (!strncmpi(str, aligns[i].adj, len))
1034. 		return i;
1035. 	    /* Or the filecode? */
1036. 	    if (!strcmpi(str, aligns[i].filecode))
1037. 		return i;
1038. 	}
1039. 	if ((len == 1 && (*str == '*' || *str == '@')) ||
1040. 		!strncmpi(str, randomstr, len))
1041. 	    return ROLE_RANDOM;
1042. 
1043. 	/* Couldn't find anything appropriate */
1044. 	return ROLE_NONE;
1045. }
1046. 
1047. /* is rolenum compatible with any racenum/gendnum/alignnum constraints? */
1048. boolean
1049. ok_role(rolenum, racenum, gendnum, alignnum)
1050. int rolenum, racenum, gendnum, alignnum;
1051. {
1052.     int i;
1053.     short allow;
1054. 
1055.     if (rolenum >= 0 && rolenum < SIZE(roles)-1) {
1056. 	allow = roles[rolenum].allow;
1057. 
1058. 	if (racenum >= 0 && racenum < SIZE(races)-1)
1059. 	    allow &= races[racenum].allow;
1060. 	if (gendnum >= 0 && gendnum < ROLE_GENDERS &&
1061. 		!(allow & genders[gendnum].allow & ROLE_GENDMASK))
1062. 	    return FALSE;
1063. 	if (alignnum >= 0 && alignnum < ROLE_ALIGNS &&
1064. 		!(allow & aligns[alignnum].allow & ROLE_ALIGNMASK))
1065. 	    return FALSE;
1066. 
1067. 	if (!(allow & ROLE_RACEMASK) || !(allow & ROLE_GENDMASK) ||
1068. 		!(allow & ROLE_ALIGNMASK))
1069. 	    return FALSE;
1070. 	return TRUE;
1071.     } else {
1072. 	for (i = 0; i < SIZE(roles)-1; i++) {
1073. 	    allow = roles[i].allow;
1074. 	    if (racenum >= 0 && racenum < SIZE(races)-1)
1075. 		allow &= races[racenum].allow;
1076. 	    if (gendnum >= 0 && gendnum < ROLE_GENDERS &&
1077. 		    !(allow & genders[gendnum].allow & ROLE_GENDMASK))
1078. 		continue;
1079. 	    if (alignnum >= 0 && alignnum < ROLE_ALIGNS &&
1080. 		    !(allow & aligns[alignnum].allow & ROLE_ALIGNMASK))
1081. 		continue;
1082. 	    if (!(allow & ROLE_RACEMASK) || !(allow & ROLE_GENDMASK) ||
1083. 		    !(allow & ROLE_ALIGNMASK))
1084. 		continue;
1085. 	    return TRUE;
1086. 	}
1087. 	return FALSE;
1088.     }
1089. }
1090. 
1091. /* pick a random role subject to any racenum/gendnum/alignnum constraints */
1092. /* If pickhow == PICK_RIGID a role is returned only if there is  */
1093. /* a single possibility */
1094. int
1095. pick_role(racenum, gendnum, alignnum, pickhow)
1096. int racenum, gendnum, alignnum, pickhow;
1097. {
1098.     int i;
1099.     int roles_ok = 0;
1100. 
1101.     for (i = 0; i < SIZE(roles)-1; i++) {
1102. 	if (ok_role(i, racenum, gendnum, alignnum))
1103. 	    roles_ok++;
1104.     }
1105.     if (roles_ok == 0 || (roles_ok > 1 && pickhow == PICK_RIGID))
1106. 	return ROLE_NONE;
1107.     roles_ok = rn2(roles_ok);
1108.     for (i = 0; i < SIZE(roles)-1; i++) {
1109. 	if (ok_role(i, racenum, gendnum, alignnum)) {
1110. 	    if (roles_ok == 0)
1111. 		return i;
1112. 	    else
1113. 		roles_ok--;
1114. 	}
1115.     }
1116.     return ROLE_NONE;
1117. }
1118. 
1119. /* is racenum compatible with any rolenum/gendnum/alignnum constraints? */
1120. boolean
1121. ok_race(rolenum, racenum, gendnum, alignnum)
1122. int rolenum, racenum, gendnum, alignnum;
1123. {
1124.     int i;
1125.     short allow;
1126. 
1127.     if (racenum >= 0 && racenum < SIZE(races)-1) {
1128. 	allow = races[racenum].allow;
1129. 
1130. 	if (rolenum >= 0 && rolenum < SIZE(roles)-1)
1131. 	    allow &= roles[rolenum].allow;
1132. 	if (gendnum >= 0 && gendnum < ROLE_GENDERS &&
1133. 		!(allow & genders[gendnum].allow & ROLE_GENDMASK))
1134. 	    return FALSE;
1135. 	if (alignnum >= 0 && alignnum < ROLE_ALIGNS &&
1136. 		!(allow & aligns[alignnum].allow & ROLE_ALIGNMASK))
1137. 	    return FALSE;
1138. 
1139. 	if (!(allow & ROLE_RACEMASK) || !(allow & ROLE_GENDMASK) ||
1140. 		!(allow & ROLE_ALIGNMASK))
1141. 	    return FALSE;
1142. 	return TRUE;
1143.     } else {
1144. 	for (i = 0; i < SIZE(races)-1; i++) {
1145. 	    allow = races[i].allow;
1146. 	    if (rolenum >= 0 && rolenum < SIZE(roles)-1)
1147. 		allow &= roles[rolenum].allow;
1148. 	    if (gendnum >= 0 && gendnum < ROLE_GENDERS &&
1149. 		    !(allow & genders[gendnum].allow & ROLE_GENDMASK))
1150. 		continue;
1151. 	    if (alignnum >= 0 && alignnum < ROLE_ALIGNS &&
1152. 		    !(allow & aligns[alignnum].allow & ROLE_ALIGNMASK))
1153. 		continue;
1154. 	    if (!(allow & ROLE_RACEMASK) || !(allow & ROLE_GENDMASK) ||
1155. 		    !(allow & ROLE_ALIGNMASK))
1156. 		continue;
1157. 	    return TRUE;
1158. 	}
1159. 	return FALSE;
1160.     }
1161. }
1162. 
1163. /* pick a random race subject to any rolenum/gendnum/alignnum constraints */
1164. /* If pickhow == PICK_RIGID a race is returned only if there is  */
1165. /* a single possibility */
1166. int
1167. pick_race(rolenum, gendnum, alignnum, pickhow)
1168. int rolenum, gendnum, alignnum, pickhow;
1169. {
1170.     int i;
1171.     int races_ok = 0;
1172. 
1173.     for (i = 0; i < SIZE(races)-1; i++) {
1174. 	if (ok_race(rolenum, i, gendnum, alignnum))
1175. 	    races_ok++;
1176.     }
1177.     if (races_ok == 0 || (races_ok > 1 && pickhow == PICK_RIGID))
1178. 	return ROLE_NONE;
1179.     races_ok = rn2(races_ok);
1180.     for (i = 0; i < SIZE(races)-1; i++) {
1181. 	if (ok_race(rolenum, i, gendnum, alignnum)) {
1182. 	    if (races_ok == 0)
1183. 		return i;
1184. 	    else
1185. 		races_ok--;
1186. 	}
1187.     }
1188.     return ROLE_NONE;
1189. }
1190. 
1191. /* is gendnum compatible with any rolenum/racenum/alignnum constraints? */
1192. /* gender and alignment are not comparable (and also not constrainable) */
1193. boolean
1194. ok_gend(rolenum, racenum, gendnum, alignnum)
1195. int rolenum, racenum, gendnum, alignnum;
1196. {
1197.     int i;
1198.     short allow;
1199. 
1200.     if (gendnum >= 0 && gendnum < ROLE_GENDERS) {
1201. 	allow = genders[gendnum].allow;
1202. 
1203. 	if (rolenum >= 0 && rolenum < SIZE(roles)-1)
1204. 	    allow &= roles[rolenum].allow;
1205. 	if (racenum >= 0 && racenum < SIZE(races)-1)
1206. 	    allow &= races[racenum].allow;
1207. 		    
1208. 	if (!(allow & ROLE_GENDMASK))
1209. 	    return FALSE;
1210. 	return TRUE;
1211.     } else {
1212. 	for (i = 0; i < ROLE_GENDERS; i++) {
1213. 	    allow = genders[i].allow;
1214. 	    if (rolenum >= 0 && rolenum < SIZE(roles)-1)
1215. 		allow &= roles[rolenum].allow;
1216. 	    if (racenum >= 0 && racenum < SIZE(races)-1)
1217. 		allow &= races[racenum].allow;
1218. 	    if (allow & ROLE_GENDMASK)
1219. 	    return TRUE;
1220. 	}
1221. 	return FALSE;
1222.     }
1223. }
1224. 
1225. /* pick a random gender subject to any rolenum/racenum/alignnum constraints */
1226. /* gender and alignment are not comparable (and also not constrainable) */
1227. /* If pickhow == PICK_RIGID a gender is returned only if there is  */
1228. /* a single possibility */
1229. int
1230. pick_gend(rolenum, racenum, alignnum, pickhow)
1231. int rolenum, racenum, alignnum, pickhow;
1232. {
1233.     int i;
1234.     int gends_ok = 0;
1235. 
1236.     for (i = 0; i < ROLE_GENDERS; i++) {
1237. 	if (ok_gend(rolenum, racenum, i, alignnum))
1238. 	    gends_ok++;
1239.     }
1240.     if (gends_ok == 0 || (gends_ok > 1 && pickhow == PICK_RIGID))
1241. 	return ROLE_NONE;
1242.     gends_ok = rn2(gends_ok);
1243.     for (i = 0; i < ROLE_GENDERS; i++) {
1244. 	if (ok_gend(rolenum, racenum, i, alignnum)) {
1245. 	    if (gends_ok == 0)
1246. 		return i;
1247. 	    else
1248. 		gends_ok--;
1249. 	}
1250.     }
1251.     return ROLE_NONE;
1252. }
1253. 
1254. /* is alignnum compatible with any rolenum/racenum/gendnum constraints? */
1255. /* alignment and gender are not comparable (and also not constrainable) */
1256. boolean
1257. ok_align(rolenum, racenum, gendnum, alignnum)
1258. int rolenum, racenum, gendnum, alignnum;
1259. {
1260.     int i;
1261.     short allow;
1262. 
1263.     if (alignnum >= 0 && alignnum < ROLE_ALIGNS) {
1264. 	allow = aligns[alignnum].allow;
1265. 
1266. 	if (rolenum >= 0 && rolenum < SIZE(roles)-1)
1267. 	    allow &= roles[rolenum].allow;
1268. 	if (racenum >= 0 && racenum < SIZE(races)-1)
1269. 	    allow &= races[racenum].allow;
1270. 		    
1271. 	if (!(allow & ROLE_ALIGNMASK))
1272. 	    return FALSE;
1273. 	return TRUE;
1274.     } else {
1275. 	for (i = 0; i < ROLE_ALIGNS; i++) {
1276. 	    allow = races[i].allow;
1277. 	    if (rolenum >= 0 && rolenum < SIZE(roles)-1)
1278. 		allow &= roles[rolenum].allow;
1279. 	    if (racenum >= 0 && racenum < SIZE(races)-1)
1280. 		allow &= races[racenum].allow;
1281. 	    if (allow & ROLE_ALIGNMASK)
1282. 	    return TRUE;
1283. 	}
1284. 	return FALSE;
1285.     }
1286. }
1287. 
1288. /* pick a random alignment subject to any rolenum/racenum/gendnum constraints */
1289. /* alignment and gender are not comparable (and also not constrainable) */
1290. /* If pickhow == PICK_RIGID an alignment is returned only if there is  */
1291. /* a single possibility */
1292. int
1293. pick_align(rolenum, racenum, gendnum, pickhow)
1294. int rolenum, racenum, gendnum, pickhow;
1295. {
1296.     int i;
1297.     int aligns_ok = 0;
1298. 
1299.     for (i = 0; i < ROLE_ALIGNS; i++) {
1300. 	if (ok_align(rolenum, racenum, gendnum, i))
1301. 	    aligns_ok++;
1302.     }
1303.     if (aligns_ok == 0 || (aligns_ok > 1 && pickhow == PICK_RIGID))
1304. 	return ROLE_NONE;
1305.     aligns_ok = rn2(aligns_ok);
1306.     for (i = 0; i < ROLE_ALIGNS; i++) {
1307. 	if (ok_align(rolenum, racenum, gendnum, i)) {
1308. 	    if (aligns_ok == 0)
1309. 		return i;
1310. 	    else
1311. 		aligns_ok--;
1312. 	}
1313.     }
1314.     return ROLE_NONE;
1315. }
1316. 
1317. void
1318. rigid_role_checks()
1319. {
1320.     /* Some roles are limited to a single race, alignment, or gender and
1321.      * calling this routine prior to XXX_player_selection() will help
1322.      * prevent an extraneous prompt that actually doesn't allow
1323.      * you to choose anything further. Note the use of PICK_RIGID which
1324.      * causes the pick_XX() routine to return a value only if there is one
1325.      * single possible selection, otherwise it returns ROLE_NONE.
1326.      *
1327.      */
1328.     if (flags.initrole == ROLE_RANDOM) {
1329. 	/* If the role was explicitly specified as ROLE_RANDOM
1330. 	 * via -uXXXX-@ then choose the role in here to narrow down
1331. 	 * later choices. Pick a random role in this case.
1332. 	 */
1333. 	flags.initrole = pick_role(flags.initrace, flags.initgend,
1334. 					flags.initalign, PICK_RANDOM);
1335. 	if (flags.initrole < 0)
1336. 	    flags.initrole = randrole();
1337.     }
1338.     if (flags.initrole != ROLE_NONE) {
1339. 	if (flags.initrace == ROLE_NONE)
1340. 	     flags.initrace = pick_race(flags.initrole, flags.initgend,
1341. 						flags.initalign, PICK_RIGID);
1342. 	if (flags.initalign == ROLE_NONE)
1343. 	     flags.initalign = pick_align(flags.initrole, flags.initrace,
1344. 						flags.initgend, PICK_RIGID);
1345. 	if (flags.initgend == ROLE_NONE)
1346. 	     flags.initgend = pick_gend(flags.initrole, flags.initrace,
1347. 						flags.initalign, PICK_RIGID);
1348.     }
1349. }
1350. 
1351. #define BP_ALIGN	0
1352. #define BP_GEND		1
1353. #define BP_RACE		2
1354. #define BP_ROLE		3
1355. #define NUM_BP		4
1356. 
1357. STATIC_VAR char pa[NUM_BP], post_attribs;
1358. 
1359. STATIC_OVL char *
1360. promptsep(buf, num_post_attribs)
1361. char *buf;
1362. int num_post_attribs;
1363. {
1364. 	const char *conj = "and ";
1365. 	if (num_post_attribs > 1
1366. 	    && post_attribs < num_post_attribs && post_attribs > 1)
1367. 	 	Strcat(buf, ","); 
1368. 	Strcat(buf, " ");
1369. 	--post_attribs;
1370. 	if (!post_attribs && num_post_attribs > 1) Strcat(buf, conj);
1371. 	return buf;
1372. }
1373. 
1374. STATIC_OVL int
1375. role_gendercount(rolenum)
1376. int rolenum;
1377. {
1378. 	int gendcount = 0;
1379. 	if (validrole(rolenum)) {
1380. 		if (roles[rolenum].allow & ROLE_MALE) ++gendcount;
1381. 		if (roles[rolenum].allow & ROLE_FEMALE) ++gendcount;
1382. 		if (roles[rolenum].allow & ROLE_NEUTER) ++gendcount;
1383. 	}
1384. 	return gendcount;
1385. }
1386. 
1387. STATIC_OVL int
1388. race_alignmentcount(racenum)
1389. int racenum;
1390. {
1391. 	int aligncount = 0;
1392. 	if (racenum != ROLE_NONE && racenum != ROLE_RANDOM) {
1393. 		if (races[racenum].allow & ROLE_CHAOTIC) ++aligncount;
1394. 		if (races[racenum].allow & ROLE_LAWFUL) ++aligncount;
1395. 		if (races[racenum].allow & ROLE_NEUTRAL) ++aligncount;
1396. 	}
1397. 	return aligncount;
1398. }
1399. 
1400. char *
1401. root_plselection_prompt(suppliedbuf, buflen, rolenum, racenum, gendnum, alignnum)
1402. char *suppliedbuf;
1403. int buflen, rolenum, racenum, gendnum, alignnum;
1404. {
1405. 	int k, gendercount = 0, aligncount = 0;
1406. 	char buf[BUFSZ];
1407. 	static char err_ret[] = " character's";
1408. 	boolean donefirst = FALSE;
1409. 
1410. 	if (!suppliedbuf || buflen < 1) return err_ret;
1411. 
1412. 	/* initialize these static variables each time this is called */
1413. 	post_attribs = 0;
1414. 	for (k=0; k < NUM_BP; ++k)
1415. 		pa[k] = 0;
1416. 	buf[0] = '\0';
1417. 	*suppliedbuf = '\0';
1418. 	
1419. 	/* How many alignments are allowed for the desired race? */
1420. 	if (racenum != ROLE_NONE && racenum != ROLE_RANDOM)
1421. 		aligncount = race_alignmentcount(racenum);
1422. 
1423. 	if (alignnum != ROLE_NONE && alignnum != ROLE_RANDOM) {
1424. 		/* if race specified, and multiple choice of alignments for it */
1425. 		if ((racenum >= 0) && (aligncount > 1)) {
1426. 			if (donefirst) Strcat(buf, " ");
1427. 			Strcat(buf, aligns[alignnum].adj);
1428. 			donefirst = TRUE;
1429. 		} else {
1430. 			if (donefirst) Strcat(buf, " ");
1431. 			Strcat(buf, aligns[alignnum].adj);
1432. 			donefirst = TRUE;
1433. 		}
1434. 	} else {
1435. 		/* if alignment not specified, but race is specified
1436. 			and only one choice of alignment for that race then
1437. 			don't include it in the later list */
1438. 		if ((((racenum != ROLE_NONE && racenum != ROLE_RANDOM) &&
1439. 			ok_race(rolenum, racenum, gendnum, alignnum))
1440. 		      && (aligncount > 1))
1441. 		     || (racenum == ROLE_NONE || racenum == ROLE_RANDOM)) {
1442. 			pa[BP_ALIGN] = 1;
1443. 			post_attribs++;
1444. 		}
1445. 	}
1446. 	/* <your lawful> */
1447. 
1448. 	/* How many genders are allowed for the desired role? */
1449. 	if (validrole(rolenum))
1450. 		gendercount = role_gendercount(rolenum);
1451. 
1452. 	if (gendnum != ROLE_NONE  && gendnum != ROLE_RANDOM) {
1453. 		if (validrole(rolenum)) {
1454. 		     /* if role specified, and multiple choice of genders for it,
1455. 			and name of role itself does not distinguish gender */
1456. 			if ((rolenum != ROLE_NONE) && (gendercount > 1)
1457. 						&& !roles[rolenum].name.f) {
1458. 				if (donefirst) Strcat(buf, " ");
1459. 				Strcat(buf, genders[gendnum].adj);
1460. 				donefirst = TRUE;
1461. 			}
1462. 	        } else {
1463. 			if (donefirst) Strcat(buf, " ");
1464. 	        	Strcat(buf, genders[gendnum].adj);
1465. 			donefirst = TRUE;
1466. 	        }
1467. 	} else {
1468. 		/* if gender not specified, but role is specified
1469. 			and only one choice of gender then
1470. 			don't include it in the later list */
1471. 		if ((validrole(rolenum) && (gendercount > 1)) || !validrole(rolenum)) {
1472. 			pa[BP_GEND] = 1;
1473. 			post_attribs++;
1474. 		}
1475. 	}
1476. 	/* <your lawful female> */
1477. 
1478. 	if (racenum != ROLE_NONE && racenum != ROLE_RANDOM) {
1479. 		if (validrole(rolenum) && ok_race(rolenum, racenum, gendnum, alignnum)) {
1480. 			if (donefirst) Strcat(buf, " "); 
1481. 			Strcat(buf, (rolenum == ROLE_NONE) ?
1482. 				races[racenum].noun :
1483. 				races[racenum].adj);
1484. 			donefirst = TRUE;
1485. 		} else if (!validrole(rolenum)) {
1486. 			if (donefirst) Strcat(buf, " ");
1487. 			Strcat(buf, races[racenum].noun);
1488. 			donefirst = TRUE;
1489. 		} else {
1490. 			pa[BP_RACE] = 1;
1491. 			post_attribs++;
1492. 		}
1493. 	} else {
1494. 		pa[BP_RACE] = 1;
1495. 		post_attribs++;
1496. 	}
1497. 	/* <your lawful female gnomish> || <your lawful female gnome> */
1498. 
1499. 	if (validrole(rolenum)) {
1500. 		if (donefirst) Strcat(buf, " ");
1501. 		if (gendnum != ROLE_NONE) {
1502. 		    if (gendnum == 1  && roles[rolenum].name.f)
1503. 			Strcat(buf, roles[rolenum].name.f);
1504. 		    else
1505.   			Strcat(buf, roles[rolenum].name.m);
1506. 		} else {
1507. 			if (roles[rolenum].name.f) {
1508. 				Strcat(buf, roles[rolenum].name.m);
1509. 				Strcat(buf, "/");
1510. 				Strcat(buf, roles[rolenum].name.f);
1511. 			} else 
1512. 				Strcat(buf, roles[rolenum].name.m);
1513. 		}
1514. 		donefirst = TRUE;
1515. 	} else if (rolenum == ROLE_NONE) {
1516. 		pa[BP_ROLE] = 1;
1517. 		post_attribs++;
1518. 	}
1519. 	
1520. 	if ((racenum == ROLE_NONE || racenum == ROLE_RANDOM) && !validrole(rolenum)) {
1521. 		if (donefirst) Strcat(buf, " ");
1522. 		Strcat(buf, "character");
1523. 		donefirst = TRUE;
1524. 	}
1525. 	/* <your lawful female gnomish cavewoman> || <your lawful female gnome>
1526. 	 *    || <your lawful female character>
1527. 	 */
1528. 	if (buflen > (int) (strlen(buf) + 1)) {
1529. 		Strcpy(suppliedbuf, buf);
1530. 		return suppliedbuf;
1531. 	} else
1532. 		return err_ret;
1533. }
1534. 
1535. char *
1536. build_plselection_prompt(buf, buflen, rolenum, racenum, gendnum, alignnum)
1537. char *buf;
1538. int buflen, rolenum, racenum, gendnum, alignnum;
1539. {
1540. 	const char *defprompt = "Shall I pick a character for you? [ynq] ";
1541. 	int num_post_attribs = 0;
1542. 	char tmpbuf[BUFSZ];
1543. 	
1544. 	if (buflen < QBUFSZ)
1545. 		return (char *)defprompt;
1546. 
1547. 	Strcpy(tmpbuf, "Shall I pick ");
1548. 	if (racenum != ROLE_NONE || validrole(rolenum))
1549. 		Strcat(tmpbuf, "your ");
1550. 	else {
1551. 		Strcat(tmpbuf, "a ");
1552. 	}
1553. 	/* <your> */
1554. 
1555. 	(void)  root_plselection_prompt(eos(tmpbuf), buflen - strlen(tmpbuf),
1556. 					rolenum, racenum, gendnum, alignnum);
1557. 	Sprintf(buf, "%s", s_suffix(tmpbuf));
1558. 
1559. 	/* buf should now be:
1560. 	 * < your lawful female gnomish cavewoman's> || <your lawful female gnome's>
1561. 	 *    || <your lawful female character's>
1562. 	 *
1563.          * Now append the post attributes to it
1564. 	 */
1565. 
1566. 	num_post_attribs = post_attribs;
1567. 	if (post_attribs) {
1568. 		if (pa[BP_RACE]) {
1569. 			(void) promptsep(eos(buf), num_post_attribs);
1570. 			Strcat(buf, "race");
1571. 		}
1572. 		if (pa[BP_ROLE]) {
1573. 			(void) promptsep(eos(buf), num_post_attribs);
1574. 			Strcat(buf, "role");
1575. 		}
1576. 		if (pa[BP_GEND]) {
1577. 			(void) promptsep(eos(buf), num_post_attribs);
1578. 			Strcat(buf, "gender");
1579. 		}
1580. 		if (pa[BP_ALIGN]) {
1581. 			(void) promptsep(eos(buf), num_post_attribs);
1582. 			Strcat(buf, "alignment");
1583. 		}
1584. 	}
1585. 	Strcat(buf, " for you? [ynq] ");
1586. 	return buf;
1587. }
1588. 
1589. #undef BP_ALIGN
1590. #undef BP_GEND
1591. #undef BP_RACE
1592. #undef BP_ROLE
1593. #undef NUM_BP
1594. 
1595. void
1596. plnamesuffix()
1597. {
1598. 	char *sptr, *eptr;
1599. 	int i;
1600. 
1601. 	/* Look for tokens delimited by '-' */
1602. 	if ((eptr = index(plname, '-')) != (char *) 0)
1603. 	    *eptr++ = '\0';
1604. 	while (eptr) {
1605. 	    /* Isolate the next token */
1606. 	    sptr = eptr;
1607. 	    if ((eptr = index(sptr, '-')) != (char *)0)
1608. 		*eptr++ = '\0';
1609. 
1610. 	    /* Try to match it to something */
1611. 	    if ((i = str2role(sptr)) != ROLE_NONE)
1612. 		flags.initrole = i;
1613. 	    else if ((i = str2race(sptr)) != ROLE_NONE)
1614. 		flags.initrace = i;
1615. 	    else if ((i = str2gend(sptr)) != ROLE_NONE)
1616. 		flags.initgend = i;
1617. 	    else if ((i = str2align(sptr)) != ROLE_NONE)
1618. 		flags.initalign = i;
1619. 	}
1620. 	if(!plname[0]) {
1621. 	    askname();
1622. 	    plnamesuffix();
1623. 	}
1624. 
1625. 	/* commas in the plname confuse the record file, convert to spaces */
1626. 	for (sptr = plname; *sptr; sptr++) {
1627. 		if (*sptr == ',') *sptr = ' ';
1628. 	}
1629. }
1630. 
1631. 
1632. /*
1633.  *	Special setup modifications here:
1634.  *
1635.  *	Unfortunately, this is going to have to be done
1636.  *	on each newgame or restore, because you lose the permonst mods
1637.  *	across a save/restore.  :-)
1638.  *
1639.  *	1 - The Rogue Leader is the Tourist Nemesis.
1640.  *	2 - Priests start with a random alignment - convert the leader and
1641.  *	    guardians here.
1642.  *	3 - Elves can have one of two different leaders, but can't work it
1643.  *	    out here because it requires hacking the level file data (see
1644.  *	    sp_lev.c).
1645.  *
1646.  * This code also replaces quest_init().
1647.  */
1648. void
1649. role_init()
1650. {
1651. 	int alignmnt;
1652. 
1653. 	/* Strip the role letter out of the player name.
1654. 	 * This is included for backwards compatibility.
1655. 	 */
1656. 	plnamesuffix();
1657. 
1658. 	/* Check for a valid role.  Try flags.initrole first. */
1659. 	if (!validrole(flags.initrole)) {
1660. 	    /* Try the player letter second */
1661. 	    if ((flags.initrole = str2role(pl_character)) < 0)
1662. 	    	/* None specified; pick a random role */
1663. 	    	flags.initrole = randrole();
1664. 	}
1665. 
1666. 	/* We now have a valid role index.  Copy the role name back. */
1667. 	/* This should become OBSOLETE */
1668. 	Strcpy(pl_character, roles[flags.initrole].name.m);
1669. 	pl_character[PL_CSIZ-1] = '\0';
1670. 
1671. 	/* Check for a valid race */
1672. 	if (!validrace(flags.initrole, flags.initrace))
1673. 	    flags.initrace = randrace(flags.initrole);
1674. 
1675. 	/* Check for a valid gender.  If new game, check both initgend
1676. 	 * and female.  On restore, assume flags.female is correct. */
1677. 	if (flags.pantheon == -1) {	/* new game */
1678. 	    if (!validgend(flags.initrole, flags.initrace, flags.female))
1679. 		flags.female = !flags.female;
1680. 	}
1681. 	if (!validgend(flags.initrole, flags.initrace, flags.initgend))
1682. 	    /* Note that there is no way to check for an unspecified gender. */
1683. 	    flags.initgend = flags.female;
1684. 
1685. 	/* Check for a valid alignment */
1686. 	if (!validalign(flags.initrole, flags.initrace, flags.initalign))
1687. 	    /* Pick a random alignment */
1688. 	    flags.initalign = randalign(flags.initrole, flags.initrace);
1689. 	alignmnt = aligns[flags.initalign].value;
1690. 
1691. 	/* Initialize urole and urace */
1692. 	urole = roles[flags.initrole];
1693. 	urace = races[flags.initrace];
1694. 
1695. 	/* Fix up the quest leader */
1696. 	if (urole.ldrnum != NON_PM) {
1697. 	    mons[urole.ldrnum].msound = MS_LEADER;
1698. 	    mons[urole.ldrnum].mflags2 |= (M2_PEACEFUL);
1699. 	    mons[urole.ldrnum].mflags3 |= M3_CLOSE;
1700. 	    mons[urole.ldrnum].maligntyp = alignmnt * 3;
1701. 	}
1702. 
1703. 	/* Fix up the quest guardians */
1704. 	if (urole.guardnum != NON_PM) {
1705. 	    mons[urole.guardnum].mflags2 |= (M2_PEACEFUL);
1706. 	    mons[urole.guardnum].maligntyp = alignmnt * 3;
1707. 	}
1708. 
1709. 	/* Fix up the quest nemesis */
1710. 	if (urole.neminum != NON_PM) {
1711. 	    mons[urole.neminum].msound = MS_NEMESIS;
1712. 	    mons[urole.neminum].mflags2 &= ~(M2_PEACEFUL);
1713. 	    mons[urole.neminum].mflags2 |= (M2_NASTY|M2_STALK|M2_HOSTILE);
1714. 	    mons[urole.neminum].mflags3 |= M3_WANTSARTI | M3_WAITFORU;
1715. 	}
1716. 
1717. 	/* Fix up the god names */
1718. 	if (flags.pantheon == -1) {		/* new game */
1719. 	    flags.pantheon = flags.initrole;	/* use own gods */
1720. 	    while (!roles[flags.pantheon].lgod)	/* unless they're missing */
1721. 		flags.pantheon = randrole();
1722. 	}
1723. 	if (!urole.lgod) {
1724. 	    urole.lgod = roles[flags.pantheon].lgod;
1725. 	    urole.ngod = roles[flags.pantheon].ngod;
1726. 	    urole.cgod = roles[flags.pantheon].cgod;
1727. 	}
1728. 
1729. #if 0 /* Now in polyself.c, init_uasmon() */
1730. 	/* Fix up infravision */
1731. 	if (mons[urace.malenum].mflags3 & M3_INFRAVISION) {
1732. 	    /* although an infravision intrinsic is possible, infravision
1733. 	     * is purely a property of the physical race.  This means that we
1734. 	     * must put the infravision flag in the player's current race
1735. 	     * (either that or have separate permonst entries for
1736. 	     * elven/non-elven members of each class).  The side effect is that
1737. 	     * all NPCs of that class will have (probably bogus) infravision,
1738. 	     * but since infravision has no effect for NPCs anyway we can
1739. 	     * ignore this.
1740. 	     */
1741. 	    mons[urole.malenum].mflags3 |= M3_INFRAVISION;
1742. 	    if (urole.femalenum != NON_PM)
1743. 	    	mons[urole.femalenum].mflags3 |= M3_INFRAVISION;
1744. 	}
1745. #endif
1746. 
1747. 	/* Artifacts are fixed in hack_artifacts() */
1748. 
1749. 	/* Success! */
1750. 	return;
1751. }
1752. 
1753. const char *
1754. Hello(mtmp)
1755. struct monst *mtmp;
1756. {
1757. 	switch (Role_switch) {
1758. 	case PM_KNIGHT:
1759. 	    return ("Salutations"); /* Olde English */
1760. 	case PM_SAMURAI:
1761. 	    return (mtmp && mtmp->data == &mons[PM_SHOPKEEPER] ?
1762. 	    		"Irasshaimase" : "Konnichi wa"); /* Japanese */
1763. #ifdef TOURIST
1764. 	case PM_TOURIST:
1765. 	    return ("Aloha");       /* Hawaiian */
1766. #endif
1767. 	case PM_VALKYRIE:
1768. 	    return (
1769. #ifdef MAIL
1770. 	    		mtmp && mtmp->data == &mons[PM_MAIL_DAEMON] ? "Hallo" :
1771. #endif
1772. 	    		"Velkommen");   /* Norse */
1773. 	default:
1774. 	    return ("Hello");
1775. 	}
1776. }
1777. 
1778. const char *
1779. Goodbye()
1780. {
1781. 	switch (Role_switch) {
1782. 	case PM_KNIGHT:
1783. 	    return ("Fare thee well");  /* Olde English */
1784. 	case PM_SAMURAI:
1785. 	    return ("Sayonara");        /* Japanese */
1786. #ifdef TOURIST
1787. 	case PM_TOURIST:
1788. 	    return ("Aloha");           /* Hawaiian */
1789. #endif
1790. 	case PM_VALKYRIE:
1791. 	    return ("Farvel");          /* Norse */
1792. 	default:
1793. 	    return ("Goodbye");
1794. 	}
1795. }
1796. 
1797. /* role.c */

Ad blocker interference detected!


Wikia is a free-to-use site that makes money from advertising. We have a modified experience for viewers using ad blockers

Wikia is not accessible if you’ve made further modifications. Remove the custom ad blocker rule(s) and the page will load as expected.