Wikihack
Advertisement

Below is the full text to src/role.c from NetHack 3.4.3. To link to a particular line, write [[role.c#line123]], for example.

Top of file[]

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.    
The NetHack General Public License applies to screenshots, source code and other content from NetHack.
5.    #include "hack.h"
6.    
7.    

Roles[]

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.    */

Archeologist[]

27.   const struct Role roles[] = {
28.   {	{"Archeologist", 0}, {
29.   	{"Digger",      0},
30.   	{"Field Worker",0},
31.   	{"Investigator",0},
32.   	{"Exhumer",     0},
33.   	{"Excavator",   0},
34.   	{"Spelunker",   0},
35.   	{"Speleologist",0},
36.   	{"Collector",   0},
37.   	{"Curator",     0} },
38.   	"Quetzalcoatl", "Camaxtli", "Huhetotl", /* Central American */
39.   	"Arc", "the College of Archeology", "the Tomb of the Toltec Kings",
40.   	PM_ARCHEOLOGIST, NON_PM, NON_PM,
41.   	PM_LORD_CARNARVON, PM_STUDENT, PM_MINION_OF_HUHETOTL,
42.   	NON_PM, PM_HUMAN_MUMMY, S_SNAKE, S_MUMMY,
43.   	ART_ORB_OF_DETECTION,
44.   	MH_HUMAN|MH_DWARF|MH_GNOME | ROLE_MALE|ROLE_FEMALE |
45.   	  ROLE_LAWFUL|ROLE_NEUTRAL,
46.   	/* Str Int Wis Dex Con Cha */
47.   	{   7, 10, 10,  7,  7,  7 },
48.   	{  20, 20, 20, 10, 20, 10 },
49.   	/* Init   Lower  Higher */
50.   	{ 11, 0,  0, 8,  1, 0 },	/* Hit points */
51.   	{  1, 0,  0, 1,  0, 1 },14,	/* Energy */
52.   	10, 5, 0, 2, 10, A_INT, SPE_MAGIC_MAPPING,   -4
53.   },

Barbarian[]

54.   {	{"Barbarian", 0}, {
55.   	{"Plunderer",   "Plunderess"},
56.   	{"Pillager",    0},
57.   	{"Bandit",      0},
58.   	{"Brigand",     0},
59.   	{"Raider",      0},
60.   	{"Reaver",      0},
61.   	{"Slayer",      0},
62.   	{"Chieftain",   "Chieftainess"},
63.   	{"Conqueror",   "Conqueress"} },
64.   	"Mitra", "Crom", "Set", /* Hyborian */
65.   	"Bar", "the Camp of the Duali Tribe", "the Duali Oasis",
66.   	PM_BARBARIAN, NON_PM, NON_PM,
67.   	PM_PELIAS, PM_CHIEFTAIN, PM_THOTH_AMON,
68.   	PM_OGRE, PM_TROLL, S_OGRE, S_TROLL,
69.   	ART_HEART_OF_AHRIMAN,
70.   	MH_HUMAN|MH_ORC | ROLE_MALE|ROLE_FEMALE |
71.   	  ROLE_NEUTRAL|ROLE_CHAOTIC,
72.   	/* Str Int Wis Dex Con Cha */
73.   	{  16,  7,  7, 15, 16,  6 },
74.   	{  30,  6,  7, 20, 30,  7 },
75.   	/* Init   Lower  Higher */
76.   	{ 14, 0,  0,10,  2, 0 },	/* Hit points */
77.   	{  1, 0,  0, 1,  0, 1 },10,	/* Energy */
78.   	10, 14, 0, 0,  8, A_INT, SPE_HASTE_SELF,      -4
79.   },

Caveman[]

80.   {	{"Caveman", "Cavewoman"}, {
81.   	{"Troglodyte",  0},
82.   	{"Aborigine",   0},
83.   	{"Wanderer",    0},
84.   	{"Vagrant",     0},
85.   	{"Wayfarer",    0},
86.   	{"Roamer",      0},
87.   	{"Nomad",       0},
88.   	{"Rover",       0},
89.   	{"Pioneer",     0} },
90.   	"Anu", "_Ishtar", "Anshar", /* Babylonian */
91.   	"Cav", "the Caves of the Ancestors", "the Dragon's Lair",
92.   	PM_CAVEMAN, PM_CAVEWOMAN, PM_LITTLE_DOG,
93.   	PM_SHAMAN_KARNOV, PM_NEANDERTHAL, PM_CHROMATIC_DRAGON,
94.   	PM_BUGBEAR, PM_HILL_GIANT, S_HUMANOID, S_GIANT,
95.   	ART_SCEPTRE_OF_MIGHT,
96.   	MH_HUMAN|MH_DWARF|MH_GNOME | ROLE_MALE|ROLE_FEMALE |
97.   	  ROLE_LAWFUL|ROLE_NEUTRAL,
98.   	/* Str Int Wis Dex Con Cha */
99.   	{  10,  7,  7,  7,  8,  6 },
100.  	{  30,  6,  7, 20, 30,  7 },
101.  	/* Init   Lower  Higher */
102.  	{ 14, 0,  0, 8,  2, 0 },	/* Hit points */
103.  	{  1, 0,  0, 1,  0, 1 },10,	/* Energy */
104.  	0, 12, 0, 1,  8, A_INT, SPE_DIG,             -4
105.  },

Healer[]

106.  {	{"Healer", 0}, {
107.  	{"Rhizotomist",    0},
108.  	{"Empiric",        0},
109.  	{"Embalmer",       0},
110.  	{"Dresser",        0},
111.  	{"Medicus ossium", "Medica ossium"},
112.  	{"Herbalist",      0},
113.  	{"Magister",       "Magistra"},
114.  	{"Physician",      0},
115.  	{"Chirurgeon",     0} },
116.  	"_Athena", "Hermes", "Poseidon", /* Greek */
117.  	"Hea", "the Temple of Epidaurus", "the Temple of Coeus",
118.  	PM_HEALER, NON_PM, NON_PM,
119.  	PM_HIPPOCRATES, PM_ATTENDANT, PM_CYCLOPS,
120.  	PM_GIANT_RAT, PM_SNAKE, S_RODENT, S_YETI,
121.  	ART_STAFF_OF_AESCULAPIUS,
122.  	MH_HUMAN|MH_GNOME | ROLE_MALE|ROLE_FEMALE | ROLE_NEUTRAL,
123.  	/* Str Int Wis Dex Con Cha */
124.  	{   7,  7, 13,  7, 11, 16 },
125.  	{  15, 20, 20, 15, 25, 5 },
126.  	/* Init   Lower  Higher */
127.  	{ 11, 0,  0, 8,  1, 0 },	/* Hit points */
128.  	{  1, 4,  0, 1,  0, 2 },20,	/* Energy */
129.  	10, 3,-3, 2, 10, A_WIS, SPE_CURE_SICKNESS,   -4
130.  },

Knight[]

131.  {	{"Knight", 0}, {
132.  	{"Gallant",     0},
133.  	{"Esquire",     0},
134.  	{"Bachelor",    0},
135.  	{"Sergeant",    0},
136.  	{"Knight",      0},
137.  	{"Banneret",    0},
138.  	{"Chevalier",   "Chevaliere"},
139.  	{"Seignieur",   "Dame"},
140.  	{"Paladin",     0} },
141.  	"Lugh", "_Brigit", "Manannan Mac Lir", /* Celtic */
142.  	"Kni", "Camelot Castle", "the Isle of Glass",
143.  	PM_KNIGHT, NON_PM, PM_PONY,
144.  	PM_KING_ARTHUR, PM_PAGE, PM_IXOTH,
145.  	PM_QUASIT, PM_OCHRE_JELLY, S_IMP, S_JELLY,
146.  	ART_MAGIC_MIRROR_OF_MERLIN,
147.  	MH_HUMAN | ROLE_MALE|ROLE_FEMALE | ROLE_LAWFUL,
148.  	/* Str Int Wis Dex Con Cha */
149.  	{  13,  7, 14,  8, 10, 17 },
150.  	{  30, 15, 15, 10, 20, 10 },
151.  	/* Init   Lower  Higher */
152.  	{ 14, 0,  0, 8,  2, 0 },	/* Hit points */
153.  	{  1, 4,  0, 1,  0, 2 },10,	/* Energy */
154.  	10, 8,-2, 0,  9, A_WIS, SPE_TURN_UNDEAD,     -4
155.  },

Monk[]

156.  {	{"Monk", 0}, {
157.  	{"Candidate",         0},
158.  	{"Novice",            0},
159.  	{"Initiate",          0},
160.  	{"Student of Stones", 0},
161.  	{"Student of Waters", 0},
162.  	{"Student of Metals", 0},
163.  	{"Student of Winds",  0},
164.  	{"Student of Fire",   0},
165.  	{"Master",            0} },
166.  	"Shan Lai Ching", "Chih Sung-tzu", "Huan Ti", /* Chinese */
167.  	"Mon", "the Monastery of Chan-Sune",
168.  	  "the Monastery of the Earth-Lord",
169.  	PM_MONK, NON_PM, NON_PM,
170.  	PM_GRAND_MASTER, PM_ABBOT, PM_MASTER_KAEN,
171.  	PM_EARTH_ELEMENTAL, PM_XORN, S_ELEMENTAL, S_XORN,
172.  	ART_EYES_OF_THE_OVERWORLD,
173.  	MH_HUMAN | ROLE_MALE|ROLE_FEMALE |
174.  	  ROLE_LAWFUL|ROLE_NEUTRAL|ROLE_CHAOTIC,
175.  	/* Str Int Wis Dex Con Cha */
176.  	{  10,  7,  8,  8,  7,  7 },
177.  	{  25, 10, 20, 20, 15, 10 },
178.  	/* Init   Lower  Higher */
179.  	{ 12, 0,  0, 8,  1, 0 },	/* Hit points */
180.  	{  2, 2,  0, 2,  0, 2 },10,	/* Energy */
181.  	10, 8,-2, 2, 20, A_WIS, SPE_RESTORE_ABILITY, -4
182.  },

Priest[]

183.  {	{"Priest", "Priestess"}, {
184.  	{"Aspirant",    0},
185.  	{"Acolyte",     0},
186.  	{"Adept",       0},
187.  	{"Priest",      "Priestess"},
188.  	{"Curate",      0},
189.  	{"Canon",       "Canoness"},
190.  	{"Lama",        0},
191.  	{"Patriarch",   "Matriarch"},
192.  	{"High Priest", "High Priestess"} },
193.  	0, 0, 0,	/* chosen randomly from among the other roles */
194.  	"Pri", "the Great Temple", "the Temple of Nalzok",
195.  	PM_PRIEST, PM_PRIESTESS, NON_PM,
196.  	PM_ARCH_PRIEST, PM_ACOLYTE, PM_NALZOK,
197.  	PM_HUMAN_ZOMBIE, PM_WRAITH, S_ZOMBIE, S_WRAITH,
198.  	ART_MITRE_OF_HOLINESS,
199.  	MH_HUMAN|MH_ELF | ROLE_MALE|ROLE_FEMALE |
200.  	  ROLE_LAWFUL|ROLE_NEUTRAL|ROLE_CHAOTIC,
201.  	/* Str Int Wis Dex Con Cha */
202.  	{   7,  7, 10,  7,  7,  7 },
203.  	{  15, 10, 30, 15, 20, 10 },
204.  	/* Init   Lower  Higher */
205.  	{ 12, 0,  0, 8,  1, 0 },	/* Hit points */
206.  	{  4, 3,  0, 2,  0, 2 },10,	/* Energy */
207.  	0, 3,-2, 2, 10, A_WIS, SPE_REMOVE_CURSE,    -4
208.  },

Rogue[]

209.    /* Note:  Rogue precedes Ranger so that use of `-R' on the command line
210.       retains its traditional meaning. */
211.  {	{"Rogue", 0}, {
212.  	{"Footpad",     0},
213.  	{"Cutpurse",    0},
214.  	{"Rogue",       0},
215.  	{"Pilferer",    0},
216.  	{"Robber",      0},
217.  	{"Burglar",     0},
218.  	{"Filcher",     0},
219.  	{"Magsman",     "Magswoman"},
220.  	{"Thief",       0} },
221.  	"Issek", "Mog", "Kos", /* Nehwon */
222.  	"Rog", "the Thieves' Guild Hall", "the Assassins' Guild Hall",
223.  	PM_ROGUE, NON_PM, NON_PM,
224.  	PM_MASTER_OF_THIEVES, PM_THUG, PM_MASTER_ASSASSIN,
225.  	PM_LEPRECHAUN, PM_GUARDIAN_NAGA, S_NYMPH, S_NAGA,
226.  	ART_MASTER_KEY_OF_THIEVERY,
227.  	MH_HUMAN|MH_ORC | ROLE_MALE|ROLE_FEMALE |
228.  	  ROLE_CHAOTIC,
229.  	/* Str Int Wis Dex Con Cha */
230.  	{   7,  7,  7, 10,  7,  6 },
231.  	{  20, 10, 10, 30, 20, 10 },
232.  	/* Init   Lower  Higher */
233.  	{ 10, 0,  0, 8,  1, 0 },	/* Hit points */
234.  	{  1, 0,  0, 1,  0, 1 },11,	/* Energy */
235.  	10, 8, 0, 1,  9, A_INT, SPE_DETECT_TREASURE, -4
236.  },

Ranger[]

237.  {	{"Ranger", 0}, {
238.  #if 0	/* OBSOLETE */
239.  	{"Edhel",       "Elleth"},
240.  	{"Edhel",       "Elleth"},      /* elf-maid */
241.  	{"Ohtar",       "Ohtie"},       /* warrior */
242.  	{"Kano",			/* commander (Q.) ['a] */
243.  			"Kanie"},	/* educated guess, until further research- SAC */
244.  	{"Arandur",			/* king's servant, minister (Q.) - guess */
245.  			"Aranduriel"},	/* educated guess */
246.  	{"Hir",         "Hiril"},       /* lord, lady (S.) ['ir] */
247.  	{"Aredhel",     "Arwen"},       /* noble elf, maiden (S.) */
248.  	{"Ernil",       "Elentariel"},  /* prince (S.), elf-maiden (Q.) */
249.  	{"Elentar",     "Elentari"},	/* Star-king, -queen (Q.) */
250.  	"Solonor Thelandira", "Aerdrie Faenya", "Lolth", /* Elven */
251.  #endif
252.  	{"Tenderfoot",    0},
253.  	{"Lookout",       0},
254.  	{"Trailblazer",   0},
255.  	{"Reconnoiterer", "Reconnoiteress"},
256.  	{"Scout",         0},
257.  	{"Arbalester",    0},	/* One skilled at crossbows */
258.  	{"Archer",        0},
259.  	{"Sharpshooter",  0},
260.  	{"Marksman",      "Markswoman"} },
261.  	"Mercury", "_Venus", "Mars", /* Roman/planets */
262.  	"Ran", "Orion's camp", "the cave of the wumpus",
263.  	PM_RANGER, NON_PM, PM_LITTLE_DOG /* Orion & canis major */,
264.  	PM_ORION, PM_HUNTER, PM_SCORPIUS,
265.  	PM_FOREST_CENTAUR, PM_SCORPION, S_CENTAUR, S_SPIDER,
266.  	ART_LONGBOW_OF_DIANA,
267.  	MH_HUMAN|MH_ELF|MH_GNOME|MH_ORC | ROLE_MALE|ROLE_FEMALE |
268.  	  ROLE_NEUTRAL|ROLE_CHAOTIC,
269.  	/* Str Int Wis Dex Con Cha */
270.  	{  13, 13, 13,  9, 13,  7 },
271.  	{  30, 10, 10, 20, 20, 10 },
272.  	/* Init   Lower  Higher */
273.  	{ 13, 0,  0, 6,  1, 0 },	/* Hit points */
274.  	{  1, 0,  0, 1,  0, 1 },12,	/* Energy */
275.  	10, 9, 2, 1, 10, A_INT, SPE_INVISIBILITY,   -4
276.  },

Samurai[]

277.  {	{"Samurai", 0}, {
278.  	{"Hatamoto",    0},  /* Banner Knight */
279.  	{"Ronin",       0},  /* no allegiance */
280.  	{"Ninja",       "Kunoichi"},  /* secret society */
281.  	{"Joshu",       0},  /* heads a castle */
282.  	{"Ryoshu",      0},  /* has a territory */
283.  	{"Kokushu",     0},  /* heads a province */
284.  	{"Daimyo",      0},  /* a samurai lord */
285.  	{"Kuge",        0},  /* Noble of the Court */
286.  	{"Shogun",      0} },/* supreme commander, warlord */
287.  	"_Amaterasu Omikami", "Raijin", "Susanowo", /* Japanese */
288.  	"Sam", "the Castle of the Taro Clan", "the Shogun's Castle",
289.  	PM_SAMURAI, NON_PM, PM_LITTLE_DOG,
290.  	PM_LORD_SATO, PM_ROSHI, PM_ASHIKAGA_TAKAUJI,
291.  	PM_WOLF, PM_STALKER, S_DOG, S_ELEMENTAL,
292.  	ART_TSURUGI_OF_MURAMASA,
293.  	MH_HUMAN | ROLE_MALE|ROLE_FEMALE | ROLE_LAWFUL,
294.  	/* Str Int Wis Dex Con Cha */
295.  	{  10,  8,  7, 10, 17,  6 },
296.  	{  30, 10,  8, 30, 14,  8 },
297.  	/* Init   Lower  Higher */
298.  	{ 13, 0,  0, 8,  1, 0 },	/* Hit points */
299.  	{  1, 0,  0, 1,  0, 1 },11,	/* Energy */
300.  	10, 10, 0, 0,  8, A_INT, SPE_CLAIRVOYANCE,    -4
301.  },

Tourist[]

302.  #ifdef TOURIST
303.  {	{"Tourist", 0}, {
304.  	{"Rambler",     0},
305.  	{"Sightseer",   0},
306.  	{"Excursionist",0},
307.  	{"Peregrinator","Peregrinatrix"},
308.  	{"Traveler",    0},
309.  	{"Journeyer",   0},
310.  	{"Voyager",     0},
311.  	{"Explorer",    0},
312.  	{"Adventurer",  0} },
313.  	"Blind Io", "_The Lady", "Offler", /* Discworld */
314.  	"Tou", "Ankh-Morpork", "the Thieves' Guild Hall",
315.  	PM_TOURIST, NON_PM, NON_PM,
316.  	PM_TWOFLOWER, PM_GUIDE, PM_MASTER_OF_THIEVES,
317.  	PM_GIANT_SPIDER, PM_FOREST_CENTAUR, S_SPIDER, S_CENTAUR,
318.  	ART_YENDORIAN_EXPRESS_CARD,
319.  	MH_HUMAN | ROLE_MALE|ROLE_FEMALE | ROLE_NEUTRAL,
320.  	/* Str Int Wis Dex Con Cha */
321.  	{   7, 10,  6,  7,  7, 10 },
322.  	{  15, 10, 10, 15, 30, 20 },
323.  	/* Init   Lower  Higher */
324.  	{  8, 0,  0, 8,  0, 0 },	/* Hit points */
325.  	{  1, 0,  0, 1,  0, 1 },14,	/* Energy */
326.  	0, 5, 1, 2, 10, A_INT, SPE_CHARM_MONSTER,   -4
327.  },
328.  #endif

Valkyrie[]

329.  {	{"Valkyrie", 0}, {
330.  	{"Stripling",   0},
331.  	{"Skirmisher",  0},
332.  	{"Fighter",     0},
333.  	{"Man-at-arms", "Woman-at-arms"},
334.  	{"Warrior",     0},
335.  	{"Swashbuckler",0},
336.  	{"Hero",        "Heroine"},
337.  	{"Champion",    0},
338.  	{"Lord",        "Lady"} },
339.  	"Tyr", "Odin", "Loki", /* Norse */
340.  	"Val", "the Shrine of Destiny", "the cave of Surtur",
341.  	PM_VALKYRIE, NON_PM, NON_PM /*PM_WINTER_WOLF_CUB*/,
342.  	PM_NORN, PM_WARRIOR, PM_LORD_SURTUR,
343.  	PM_FIRE_ANT, PM_FIRE_GIANT, S_ANT, S_GIANT,
344.  	ART_ORB_OF_FATE,
345.  	MH_HUMAN|MH_DWARF | ROLE_FEMALE | ROLE_LAWFUL|ROLE_NEUTRAL,
346.  	/* Str Int Wis Dex Con Cha */
347.  	{  10,  7,  7,  7, 10,  7 },
348.  	{  30,  6,  7, 20, 30,  7 },
349.  	/* Init   Lower  Higher */
350.  	{ 14, 0,  0, 8,  2, 0 },	/* Hit points */
351.  	{  1, 0,  0, 1,  0, 1 },10,	/* Energy */
352.  	0, 10,-2, 0,  9, A_WIS, SPE_CONE_OF_COLD,    -4
353.  },

Wizard[]

354.  {	{"Wizard", 0}, {
355.  	{"Evoker",      0},
356.  	{"Conjurer",    0},
357.  	{"Thaumaturge", 0},
358.  	{"Magician",    0},
359.  	{"Enchanter",   "Enchantress"},
360.  	{"Sorcerer",    "Sorceress"},
361.  	{"Necromancer", 0},
362.  	{"Wizard",      0},
363.  	{"Mage",        0} },
364.  	"Ptah", "Thoth", "Anhur", /* Egyptian */
365.  	"Wiz", "the Lonely Tower", "the Tower of Darkness",
366.  	PM_WIZARD, NON_PM, PM_KITTEN,
367.  	PM_NEFERET_THE_GREEN, PM_APPRENTICE, PM_DARK_ONE,
368.  	PM_VAMPIRE_BAT, PM_XORN, S_BAT, S_WRAITH,
369.  	ART_EYE_OF_THE_AETHIOPICA,
370.  	MH_HUMAN|MH_ELF|MH_GNOME|MH_ORC | ROLE_MALE|ROLE_FEMALE |
371.  	  ROLE_NEUTRAL|ROLE_CHAOTIC,
372.  	/* Str Int Wis Dex Con Cha */
373.  	{   7, 10,  7,  7,  7,  7 },
374.  	{  10, 30, 10, 20, 20, 10 },
375.  	/* Init   Lower  Higher */
376.  	{ 10, 0,  0, 8,  1, 0 },	/* Hit points */
377.  	{  4, 3,  0, 2,  0, 3 },12,	/* Energy */
378.  	0, 1, 0, 3, 10, A_INT, SPE_MAGIC_MISSILE,   -4
379.  },
380.  /* Array terminator */
381.  {{0, 0}}
382.  };
383.  
384.  
385.  /* The player's role, created at runtime from initial
386.   * choices.  This may be munged in role_init().
387.   */
388.  struct Role urole =
389.  {	{"Undefined", 0}, { {0, 0}, {0, 0}, {0, 0},
390.  	{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0} },
391.  	"L", "N", "C", "Xxx", "home", "locate",
392.  	NON_PM, NON_PM, NON_PM, NON_PM, NON_PM, NON_PM,
393.  	NON_PM, NON_PM, 0, 0, 0, 0,
394.  	/* Str Int Wis Dex Con Cha */
395.  	{   7,  7,  7,  7,  7,  7 },
396.  	{  20, 15, 15, 20, 20, 10 },
397.  	/* Init   Lower  Higher */
398.  	{ 10, 0,  0, 8,  1, 0 },	/* Hit points */
399.  	{  2, 0,  0, 2,  0, 3 },14,	/* Energy */
400.  	0, 10, 0, 0,  4, A_INT, 0, -3
401.  };
402.  
403.  
404.  

Races[]

405.  /* Table of all races */
406.  const struct Race races[] = {

Human[]

407.  {	"human", "human", "humanity", "Hum",
408.  	{"man", "woman"},
409.  	PM_HUMAN, NON_PM, PM_HUMAN_MUMMY, PM_HUMAN_ZOMBIE,
410.  	MH_HUMAN | ROLE_MALE|ROLE_FEMALE |
411.  	  ROLE_LAWFUL|ROLE_NEUTRAL|ROLE_CHAOTIC,
412.  	MH_HUMAN, 0, MH_GNOME|MH_ORC,
413.  	/*    Str     Int Wis Dex Con Cha */
414.  	{      3,      3,  3,  3,  3,  3 },
415.  	{ STR18(100), 18, 18, 18, 18, 18 },
416.  	/* Init   Lower  Higher */
417.  	{  2, 0,  0, 2,  1, 0 },	/* Hit points */
418.  	{  1, 0,  2, 0,  2, 0 }		/* Energy */
419.  },

Elf[]

420.  {	"elf", "elven", "elvenkind", "Elf",
421.  	{0, 0},
422.  	PM_ELF, NON_PM, PM_ELF_MUMMY, PM_ELF_ZOMBIE,
423.  	MH_ELF | ROLE_MALE|ROLE_FEMALE | ROLE_CHAOTIC,
424.  	MH_ELF, MH_ELF, MH_ORC,
425.  	/*  Str    Int Wis Dex Con Cha */
426.  	{    3,     3,  3,  3,  3,  3 },
427.  	{   18,    20, 20, 18, 16, 18 },
428.  	/* Init   Lower  Higher */
429.  	{  1, 0,  0, 1,  1, 0 },	/* Hit points */
430.  	{  2, 0,  3, 0,  3, 0 }		/* Energy */
431.  },

Dwarf[]

432.  {	"dwarf", "dwarven", "dwarvenkind", "Dwa",
433.  	{0, 0},
434.  	PM_DWARF, NON_PM, PM_DWARF_MUMMY, PM_DWARF_ZOMBIE,
435.  	MH_DWARF | ROLE_MALE|ROLE_FEMALE | ROLE_LAWFUL,
436.  	MH_DWARF, MH_DWARF|MH_GNOME, MH_ORC,
437.  	/*    Str     Int Wis Dex Con Cha */
438.  	{      3,      3,  3,  3,  3,  3 },
439.  	{ STR18(100), 16, 16, 20, 20, 16 },
440.  	/* Init   Lower  Higher */
441.  	{  4, 0,  0, 3,  2, 0 },	/* Hit points */
442.  	{  0, 0,  0, 0,  0, 0 }		/* Energy */
443.  },

Gnome[]

444.  {	"gnome", "gnomish", "gnomehood", "Gno",
445.  	{0, 0},
446.  	PM_GNOME, NON_PM, PM_GNOME_MUMMY, PM_GNOME_ZOMBIE,
447.  	MH_GNOME | ROLE_MALE|ROLE_FEMALE | ROLE_NEUTRAL,
448.  	MH_GNOME, MH_DWARF|MH_GNOME, MH_HUMAN,
449.  	/*  Str    Int Wis Dex Con Cha */
450.  	{    3,     3,  3,  3,  3,  3 },
451.  	{STR18(50),19, 18, 18, 18, 18 },
452.  	/* Init   Lower  Higher */
453.  	{  1, 0,  0, 1,  0, 0 },	/* Hit points */
454.  	{  2, 0,  2, 0,  2, 0 }		/* Energy */
455.  },

Orc[]

456.  {	"orc", "orcish", "orcdom", "Orc",
457.  	{0, 0},
458.  	PM_ORC, NON_PM, PM_ORC_MUMMY, PM_ORC_ZOMBIE,
459.  	MH_ORC | ROLE_MALE|ROLE_FEMALE | ROLE_CHAOTIC,
460.  	MH_ORC, 0, MH_HUMAN|MH_ELF|MH_DWARF,
461.  	/*  Str    Int Wis Dex Con Cha */
462.  	{   3,      3,  3,  3,  3,  3 },
463.  	{STR18(50),16, 16, 18, 18, 16 },
464.  	/* Init   Lower  Higher */
465.  	{  1, 0,  0, 1,  0, 0 },	/* Hit points */
466.  	{  1, 0,  1, 0,  1, 0 }		/* Energy */
467.  },
468.  /* Array terminator */
469.  { 0, 0, 0, 0 }};
470.  
471.  
472.  /* The player's race, created at runtime from initial
473.   * choices.  This may be munged in role_init().
474.   */
475.  struct Race urace =
476.  {	"something", "undefined", "something", "Xxx",
477.  	{0, 0},
478.  	NON_PM, NON_PM, NON_PM, NON_PM,
479.  	0, 0, 0, 0,
480.  	/*    Str     Int Wis Dex Con Cha */
481.  	{      3,      3,  3,  3,  3,  3 },
482.  	{ STR18(100), 18, 18, 18, 18, 18 },
483.  	/* Init   Lower  Higher */
484.  	{  2, 0,  0, 2,  1, 0 },	/* Hit points */
485.  	{  1, 0,  2, 0,  2, 0 }		/* Energy */
486.  };
487.  
488.  

Genders[]

489.  /* Table of all genders */
490.  const struct Gender genders[] = {
491.  	{"male",	"he",	"him",	"his",	"Mal",	ROLE_MALE},
492.  	{"female",	"she",	"her",	"her",	"Fem",	ROLE_FEMALE},
493.  	{"neuter",	"it",	"it",	"its",	"Ntr",	ROLE_NEUTER}
494.  };
495.  
496.  

Alignments[]

497.  /* Table of all alignments */
498.  const struct Align aligns[] = {
499.  	{"law",		"lawful",	"Law",	ROLE_LAWFUL,	A_LAWFUL},
500.  	{"balance",	"neutral",	"Neu",	ROLE_NEUTRAL,	A_NEUTRAL},
501.  	{"chaos",	"chaotic",	"Cha",	ROLE_CHAOTIC,	A_CHAOTIC},
502.  	{"evil",	"unaligned",	"Una",	0,		A_NONE}
503.  };
504.  
505.  STATIC_DCL char * FDECL(promptsep, (char *, int));
506.  STATIC_DCL int FDECL(role_gendercount, (int));
507.  STATIC_DCL int FDECL(race_alignmentcount, (int));
508.  
509.  /* used by str2XXX() */
510.  static char NEARDATA randomstr[] = "random";
511.  
512.  

validrole[]

513.  boolean
514.  validrole(rolenum)
515.  	int rolenum;
516.  {
517.  	return (rolenum >= 0 && rolenum < SIZE(roles)-1);
518.  }
519.  
520.  

randrole[]

521.  int
522.  randrole()
523.  {
524.  	return (rn2(SIZE(roles)-1));
525.  }
526.  
527.  

str2role[]

528.  int
529.  str2role(str)
530.  	char *str;
531.  {
532.  	int i, len;
533.  
534.  	/* Is str valid? */
535.  	if (!str || !str[0])
536.  	    return ROLE_NONE;
537.  
538.  	/* Match as much of str as is provided */
539.  	len = strlen(str);
540.  	for (i = 0; roles[i].name.m; i++) {
541.  	    /* Does it match the male name? */
542.  	    if (!strncmpi(str, roles[i].name.m, len))
543.  		return i;
544.  	    /* Or the female name? */
545.  	    if (roles[i].name.f && !strncmpi(str, roles[i].name.f, len))
546.  		return i;
547.  	    /* Or the filecode? */
548.  	    if (!strcmpi(str, roles[i].filecode))
549.  		return i;
550.  	}
551.  
552.  	if ((len == 1 && (*str == '*' || *str == '@')) ||
553.  		!strncmpi(str, randomstr, len))
554.  	    return ROLE_RANDOM;
555.  
556.  	/* Couldn't find anything appropriate */
557.  	return ROLE_NONE;
558.  }
559.  
560.  

validrace[]

561.  boolean
562.  validrace(rolenum, racenum)
563.  	int rolenum, racenum;
564.  {
565.  	/* Assumes validrole */
566.  	return (racenum >= 0 && racenum < SIZE(races)-1 &&
567.  		(roles[rolenum].allow & races[racenum].allow & ROLE_RACEMASK));
568.  }
569.  
570.  

randrace[]

571.  int
572.  randrace(rolenum)
573.  	int rolenum;
574.  {
575.  	int i, n = 0;
576.  
577.  	/* Count the number of valid races */
578.  	for (i = 0; races[i].noun; i++)
579.  	    if (roles[rolenum].allow & races[i].allow & ROLE_RACEMASK)
580.  	    	n++;
581.  
582.  	/* Pick a random race */
583.  	/* Use a factor of 100 in case of bad random number generators */
584.  	if (n) n = rn2(n*100)/100;
585.  	for (i = 0; races[i].noun; i++)
586.  	    if (roles[rolenum].allow & races[i].allow & ROLE_RACEMASK) {
587.  	    	if (n) n--;
588.  	    	else return (i);
589.  	    }
590.  
591.  	/* This role has no permitted races? */
592.  	return (rn2(SIZE(races)-1));
593.  }
594.  
595.  

str2race[]

596.  int
597.  str2race(str)
598.  	char *str;
599.  {
600.  	int i, len;
601.  
602.  	/* Is str valid? */
603.  	if (!str || !str[0])
604.  	    return ROLE_NONE;
605.  
606.  	/* Match as much of str as is provided */
607.  	len = strlen(str);
608.  	for (i = 0; races[i].noun; i++) {
609.  	    /* Does it match the noun? */
610.  	    if (!strncmpi(str, races[i].noun, len))
611.  		return i;
612.  	    /* Or the filecode? */
613.  	    if (!strcmpi(str, races[i].filecode))
614.  		return i;
615.  	}
616.  
617.  	if ((len == 1 && (*str == '*' || *str == '@')) ||
618.  		!strncmpi(str, randomstr, len))
619.  	    return ROLE_RANDOM;
620.  
621.  	/* Couldn't find anything appropriate */
622.  	return ROLE_NONE;
623.  }
624.  
625.  

validgend[]

626.  boolean
627.  validgend(rolenum, racenum, gendnum)
628.  	int rolenum, racenum, gendnum;
629.  {
630.  	/* Assumes validrole and validrace */
631.  	return (gendnum >= 0 && gendnum < ROLE_GENDERS &&
632.  		(roles[rolenum].allow & races[racenum].allow &
633.  		 genders[gendnum].allow & ROLE_GENDMASK));
634.  }
635.  
636.  

randgend[]

637.  int
638.  randgend(rolenum, racenum)
639.  	int rolenum, racenum;
640.  {
641.  	int i, n = 0;
642.  
643.  	/* Count the number of valid genders */
644.  	for (i = 0; i < ROLE_GENDERS; i++)
645.  	    if (roles[rolenum].allow & races[racenum].allow &
646.  	    		genders[i].allow & ROLE_GENDMASK)
647.  	    	n++;
648.  
649.  	/* Pick a random gender */
650.  	if (n) n = rn2(n);
651.  	for (i = 0; i < ROLE_GENDERS; i++)
652.  	    if (roles[rolenum].allow & races[racenum].allow &
653.  	    		genders[i].allow & ROLE_GENDMASK) {
654.  	    	if (n) n--;
655.  	    	else return (i);
656.  	    }
657.  
658.  	/* This role/race has no permitted genders? */
659.  	return (rn2(ROLE_GENDERS));
660.  }
661.  
662.  

str2gend[]

663.  int
664.  str2gend(str)
665.  	char *str;
666.  {
667.  	int i, len;
668.  
669.  	/* Is str valid? */
670.  	if (!str || !str[0])
671.  	    return ROLE_NONE;
672.  
673.  	/* Match as much of str as is provided */
674.  	len = strlen(str);
675.  	for (i = 0; i < ROLE_GENDERS; i++) {
676.  	    /* Does it match the adjective? */
677.  	    if (!strncmpi(str, genders[i].adj, len))
678.  		return i;
679.  	    /* Or the filecode? */
680.  	    if (!strcmpi(str, genders[i].filecode))
681.  		return i;
682.  	}
683.  	if ((len == 1 && (*str == '*' || *str == '@')) ||
684.  		!strncmpi(str, randomstr, len))
685.  	    return ROLE_RANDOM;
686.  
687.  	/* Couldn't find anything appropriate */
688.  	return ROLE_NONE;
689.  }
690.  
691.  

validalign[]

692.  boolean
693.  validalign(rolenum, racenum, alignnum)
694.  	int rolenum, racenum, alignnum;
695.  {
696.  	/* Assumes validrole and validrace */
697.  	return (alignnum >= 0 && alignnum < ROLE_ALIGNS &&
698.  		(roles[rolenum].allow & races[racenum].allow &
699.  		 aligns[alignnum].allow & ROLE_ALIGNMASK));
700.  }
701.  
702.  

randalign[]

703.  int
704.  randalign(rolenum, racenum)
705.  	int rolenum, racenum;
706.  {
707.  	int i, n = 0;
708.  
709.  	/* Count the number of valid alignments */
710.  	for (i = 0; i < ROLE_ALIGNS; i++)
711.  	    if (roles[rolenum].allow & races[racenum].allow &
712.  	    		aligns[i].allow & ROLE_ALIGNMASK)
713.  	    	n++;
714.  
715.  	/* Pick a random alignment */
716.  	if (n) n = rn2(n);
717.  	for (i = 0; i < ROLE_ALIGNS; i++)
718.  	    if (roles[rolenum].allow & races[racenum].allow &
719.  	    		aligns[i].allow & ROLE_ALIGNMASK) {
720.  	    	if (n) n--;
721.  	    	else return (i);
722.  	    }
723.  
724.  	/* This role/race has no permitted alignments? */
725.  	return (rn2(ROLE_ALIGNS));
726.  }
727.  
728.  

str2align[]

729.  int
730.  str2align(str)
731.  	char *str;
732.  {
733.  	int i, len;
734.  
735.  	/* Is str valid? */
736.  	if (!str || !str[0])
737.  	    return ROLE_NONE;
738.  
739.  	/* Match as much of str as is provided */
740.  	len = strlen(str);
741.  	for (i = 0; i < ROLE_ALIGNS; i++) {
742.  	    /* Does it match the adjective? */
743.  	    if (!strncmpi(str, aligns[i].adj, len))
744.  		return i;
745.  	    /* Or the filecode? */
746.  	    if (!strcmpi(str, aligns[i].filecode))
747.  		return i;
748.  	}
749.  	if ((len == 1 && (*str == '*' || *str == '@')) ||
750.  		!strncmpi(str, randomstr, len))
751.  	    return ROLE_RANDOM;
752.  
753.  	/* Couldn't find anything appropriate */
754.  	return ROLE_NONE;
755.  }
756.  
757.  /* is rolenum compatible with any racenum/gendnum/alignnum constraints? */

ok_role[]

758.  boolean
759.  ok_role(rolenum, racenum, gendnum, alignnum)
760.  int rolenum, racenum, gendnum, alignnum;
761.  {
762.      int i;
763.      short allow;
764.  
765.      if (rolenum >= 0 && rolenum < SIZE(roles)-1) {
766.  	allow = roles[rolenum].allow;
767.  	if (racenum >= 0 && racenum < SIZE(races)-1 &&
768.  		!(allow & races[racenum].allow & ROLE_RACEMASK))
769.  	    return FALSE;
770.  	if (gendnum >= 0 && gendnum < ROLE_GENDERS &&
771.  		!(allow & genders[gendnum].allow & ROLE_GENDMASK))
772.  	    return FALSE;
773.  	if (alignnum >= 0 && alignnum < ROLE_ALIGNS &&
774.  		!(allow & aligns[alignnum].allow & ROLE_ALIGNMASK))
775.  	    return FALSE;
776.  	return TRUE;
777.      } else {
778.  	for (i = 0; i < SIZE(roles)-1; i++) {
779.  	    allow = roles[i].allow;
780.  	    if (racenum >= 0 && racenum < SIZE(races)-1 &&
781.  		    !(allow & races[racenum].allow & ROLE_RACEMASK))
782.  		continue;
783.  	    if (gendnum >= 0 && gendnum < ROLE_GENDERS &&
784.  		    !(allow & genders[gendnum].allow & ROLE_GENDMASK))
785.  		continue;
786.  	    if (alignnum >= 0 && alignnum < ROLE_ALIGNS &&
787.  		    !(allow & aligns[alignnum].allow & ROLE_ALIGNMASK))
788.  		continue;
789.  	    return TRUE;
790.  	}
791.  	return FALSE;
792.      }
793.  }
794.  

pick_role[]

795.  /* pick a random role subject to any racenum/gendnum/alignnum constraints */
796.  /* If pickhow == PICK_RIGID a role is returned only if there is  */
797.  /* a single possibility */
798.  int
799.  pick_role(racenum, gendnum, alignnum, pickhow)
800.  int racenum, gendnum, alignnum, pickhow;
801.  {
802.      int i;
803.      int roles_ok = 0;
804.  
805.      for (i = 0; i < SIZE(roles)-1; i++) {
806.  	if (ok_role(i, racenum, gendnum, alignnum))
807.  	    roles_ok++;
808.      }
809.      if (roles_ok == 0 || (roles_ok > 1 && pickhow == PICK_RIGID))
810.  	return ROLE_NONE;
811.      roles_ok = rn2(roles_ok);
812.      for (i = 0; i < SIZE(roles)-1; i++) {
813.  	if (ok_role(i, racenum, gendnum, alignnum)) {
814.  	    if (roles_ok == 0)
815.  		return i;
816.  	    else
817.  		roles_ok--;
818.  	}
819.      }
820.      return ROLE_NONE;
821.  }
822.  

ok_race[]

823.  /* is racenum compatible with any rolenum/gendnum/alignnum constraints? */
824.  boolean
825.  ok_race(rolenum, racenum, gendnum, alignnum)
826.  int rolenum, racenum, gendnum, alignnum;
827.  {
828.      int i;
829.      short allow;
830.  
831.      if (racenum >= 0 && racenum < SIZE(races)-1) {
832.  	allow = races[racenum].allow;
833.  	if (rolenum >= 0 && rolenum < SIZE(roles)-1 &&
834.  		!(allow & roles[rolenum].allow & ROLE_RACEMASK))
835.  	    return FALSE;
836.  	if (gendnum >= 0 && gendnum < ROLE_GENDERS &&
837.  		!(allow & genders[gendnum].allow & ROLE_GENDMASK))
838.  	    return FALSE;
839.  	if (alignnum >= 0 && alignnum < ROLE_ALIGNS &&
840.  		!(allow & aligns[alignnum].allow & ROLE_ALIGNMASK))
841.  	    return FALSE;
842.  	return TRUE;
843.      } else {
844.  	for (i = 0; i < SIZE(races)-1; i++) {
845.  	    allow = races[i].allow;
846.  	    if (rolenum >= 0 && rolenum < SIZE(roles)-1 &&
847.  		    !(allow & roles[rolenum].allow & ROLE_RACEMASK))
848.  		continue;
849.  	    if (gendnum >= 0 && gendnum < ROLE_GENDERS &&
850.  		    !(allow & genders[gendnum].allow & ROLE_GENDMASK))
851.  		continue;
852.  	    if (alignnum >= 0 && alignnum < ROLE_ALIGNS &&
853.  		    !(allow & aligns[alignnum].allow & ROLE_ALIGNMASK))
854.  		continue;
855.  	    return TRUE;
856.  	}
857.  	return FALSE;
858.      }
859.  }
860.  

pick_race[]

861.  /* pick a random race subject to any rolenum/gendnum/alignnum constraints */
862.  /* If pickhow == PICK_RIGID a race is returned only if there is  */
863.  /* a single possibility */
864.  int
865.  pick_race(rolenum, gendnum, alignnum, pickhow)
866.  int rolenum, gendnum, alignnum, pickhow;
867.  {
868.      int i;
869.      int races_ok = 0;
870.  
871.      for (i = 0; i < SIZE(races)-1; i++) {
872.  	if (ok_race(rolenum, i, gendnum, alignnum))
873.  	    races_ok++;
874.      }
875.      if (races_ok == 0 || (races_ok > 1 && pickhow == PICK_RIGID))
876.  	return ROLE_NONE;
877.      races_ok = rn2(races_ok);
878.      for (i = 0; i < SIZE(races)-1; i++) {
879.  	if (ok_race(rolenum, i, gendnum, alignnum)) {
880.  	    if (races_ok == 0)
881.  		return i;
882.  	    else
883.  		races_ok--;
884.  	}
885.      }
886.      return ROLE_NONE;
887.  }
888.  

ok_gend[]

889.  /* is gendnum compatible with any rolenum/racenum/alignnum constraints? */
890.  /* gender and alignment are not comparable (and also not constrainable) */
891.  boolean
892.  ok_gend(rolenum, racenum, gendnum, alignnum)
893.  int rolenum, racenum, gendnum, alignnum;
894.  {
895.      int i;
896.      short allow;
897.  
898.      if (gendnum >= 0 && gendnum < ROLE_GENDERS) {
899.  	allow = genders[gendnum].allow;
900.  	if (rolenum >= 0 && rolenum < SIZE(roles)-1 &&
901.  		!(allow & roles[rolenum].allow & ROLE_GENDMASK))
902.  	    return FALSE;
903.  	if (racenum >= 0 && racenum < SIZE(races)-1 &&
904.  		!(allow & races[racenum].allow & ROLE_GENDMASK))
905.  	    return FALSE;
906.  	return TRUE;
907.      } else {
908.  	for (i = 0; i < ROLE_GENDERS; i++) {
909.  	    allow = genders[i].allow;
910.  	    if (rolenum >= 0 && rolenum < SIZE(roles)-1 &&
911.  		    !(allow & roles[rolenum].allow & ROLE_GENDMASK))
912.  		continue;
913.  	    if (racenum >= 0 && racenum < SIZE(races)-1 &&
914.  		    !(allow & races[racenum].allow & ROLE_GENDMASK))
915.  		continue;
916.  	    return TRUE;
917.  	}
918.  	return FALSE;
919.      }
920.  }
921.  

pick_gend[]

922.  /* pick a random gender subject to any rolenum/racenum/alignnum constraints */
923.  /* gender and alignment are not comparable (and also not constrainable) */
924.  /* If pickhow == PICK_RIGID a gender is returned only if there is  */
925.  /* a single possibility */
926.  int
927.  pick_gend(rolenum, racenum, alignnum, pickhow)
928.  int rolenum, racenum, alignnum, pickhow;
929.  {
930.      int i;
931.      int gends_ok = 0;
932.  
933.      for (i = 0; i < ROLE_GENDERS; i++) {
934.  	if (ok_gend(rolenum, racenum, i, alignnum))
935.  	    gends_ok++;
936.      }
937.      if (gends_ok == 0 || (gends_ok > 1 && pickhow == PICK_RIGID))
938.  	return ROLE_NONE;
939.      gends_ok = rn2(gends_ok);
940.      for (i = 0; i < ROLE_GENDERS; i++) {
941.  	if (ok_gend(rolenum, racenum, i, alignnum)) {
942.  	    if (gends_ok == 0)
943.  		return i;
944.  	    else
945.  		gends_ok--;
946.  	}
947.      }
948.      return ROLE_NONE;
949.  }
950.  

ok_align[]

951.  /* is alignnum compatible with any rolenum/racenum/gendnum constraints? */
952.  /* alignment and gender are not comparable (and also not constrainable) */
953.  boolean
954.  ok_align(rolenum, racenum, gendnum, alignnum)
955.  int rolenum, racenum, gendnum, alignnum;
956.  {
957.      int i;
958.      short allow;
959.  
960.      if (alignnum >= 0 && alignnum < ROLE_ALIGNS) {
961.  	allow = aligns[alignnum].allow;
962.  	if (rolenum >= 0 && rolenum < SIZE(roles)-1 &&
963.  		!(allow & roles[rolenum].allow & ROLE_ALIGNMASK))
964.  	    return FALSE;
965.  	if (racenum >= 0 && racenum < SIZE(races)-1 &&
966.  		!(allow & races[racenum].allow & ROLE_ALIGNMASK))
967.  	    return FALSE;
968.  	return TRUE;
969.      } else {
970.  	for (i = 0; i < ROLE_ALIGNS; i++) {
971.  	    allow = races[i].allow;
972.  	    if (rolenum >= 0 && rolenum < SIZE(roles)-1 &&
973.  		    !(allow & roles[rolenum].allow & ROLE_ALIGNMASK))
974.  		continue;
975.  	    if (racenum >= 0 && racenum < SIZE(races)-1 &&
976.  		    !(allow & races[racenum].allow & ROLE_ALIGNMASK))
977.  		continue;
978.  	    return TRUE;
979.  	}
980.  	return FALSE;
981.      }
982.  }
983.  

pick_align[]

984.  /* pick a random alignment subject to any rolenum/racenum/gendnum constraints */
985.  /* alignment and gender are not comparable (and also not constrainable) */
986.  /* If pickhow == PICK_RIGID an alignment is returned only if there is  */
987.  /* a single possibility */
988.  int
989.  pick_align(rolenum, racenum, gendnum, pickhow)
990.  int rolenum, racenum, gendnum, pickhow;
991.  {
992.      int i;
993.      int aligns_ok = 0;
994.  
995.      for (i = 0; i < ROLE_ALIGNS; i++) {
996.  	if (ok_align(rolenum, racenum, gendnum, i))
997.  	    aligns_ok++;
998.      }
999.      if (aligns_ok == 0 || (aligns_ok > 1 && pickhow == PICK_RIGID))
1000. 	return ROLE_NONE;
1001.     aligns_ok = rn2(aligns_ok);
1002.     for (i = 0; i < ROLE_ALIGNS; i++) {
1003. 	if (ok_align(rolenum, racenum, gendnum, i)) {
1004. 	    if (aligns_ok == 0)
1005. 		return i;
1006. 	    else
1007. 		aligns_ok--;
1008. 	}
1009.     }
1010.     return ROLE_NONE;
1011. }
1012. 

rigid_role_checks[]

1013. void
1014. rigid_role_checks()
1015. {
1016.     /* Some roles are limited to a single race, alignment, or gender and
1017.      * calling this routine prior to XXX_player_selection() will help
1018.      * prevent an extraneous prompt that actually doesn't allow
1019.      * you to choose anything further. Note the use of PICK_RIGID which
1020.      * causes the pick_XX() routine to return a value only if there is one
1021.      * single possible selection, otherwise it returns ROLE_NONE.
1022.      *
1023.      */
1024.     if (flags.initrole == ROLE_RANDOM) {
1025. 	/* If the role was explicitly specified as ROLE_RANDOM
1026. 	 * via -uXXXX-@ then choose the role in here to narrow down
1027. 	 * later choices. Pick a random role in this case.
1028. 	 */
1029. 	flags.initrole = pick_role(flags.initrace, flags.initgend,
1030. 					flags.initalign, PICK_RANDOM);
1031. 	if (flags.initrole < 0)
1032. 	    flags.initrole = randrole();
1033.     }
1034.     if (flags.initrole != ROLE_NONE) {
1035. 	if (flags.initrace == ROLE_NONE)
1036. 	     flags.initrace = pick_race(flags.initrole, flags.initgend,
1037. 						flags.initalign, PICK_RIGID);
1038. 	if (flags.initalign == ROLE_NONE)
1039. 	     flags.initalign = pick_align(flags.initrole, flags.initrace,
1040. 						flags.initgend, PICK_RIGID);
1041. 	if (flags.initgend == ROLE_NONE)
1042. 	     flags.initgend = pick_gend(flags.initrole, flags.initrace,
1043. 						flags.initalign, PICK_RIGID);
1044.     }
1045. }
1046. 
1047. #define BP_ALIGN	0
1048. #define BP_GEND		1
1049. #define BP_RACE		2
1050. #define BP_ROLE		3
1051. #define NUM_BP		4
1052. 
1053. STATIC_VAR char pa[NUM_BP], post_attribs;
1054. 

promptsep[]

1055. STATIC_OVL char *
1056. promptsep(buf, num_post_attribs)
1057. char *buf;
1058. int num_post_attribs;
1059. {
1060. 	const char *conj = "and ";
1061. 	if (num_post_attribs > 1
1062. 	    && post_attribs < num_post_attribs && post_attribs > 1)
1063. 	 	Strcat(buf, ","); 
1064. 	Strcat(buf, " ");
1065. 	--post_attribs;
1066. 	if (!post_attribs && num_post_attribs > 1) Strcat(buf, conj);
1067. 	return buf;
1068. }
1069. 

role_gendercount[]

1070. STATIC_OVL int
1071. role_gendercount(rolenum)
1072. int rolenum;
1073. {
1074. 	int gendcount = 0;
1075. 	if (validrole(rolenum)) {
1076. 		if (roles[rolenum].allow & ROLE_MALE) ++gendcount;
1077. 		if (roles[rolenum].allow & ROLE_FEMALE) ++gendcount;
1078. 		if (roles[rolenum].allow & ROLE_NEUTER) ++gendcount;
1079. 	}
1080. 	return gendcount;
1081. }
1082. 

race_alignmentcount[]

1083. STATIC_OVL int
1084. race_alignmentcount(racenum)
1085. int racenum;
1086. {
1087. 	int aligncount = 0;
1088. 	if (racenum != ROLE_NONE && racenum != ROLE_RANDOM) {
1089. 		if (races[racenum].allow & ROLE_CHAOTIC) ++aligncount;
1090. 		if (races[racenum].allow & ROLE_LAWFUL) ++aligncount;
1091. 		if (races[racenum].allow & ROLE_NEUTRAL) ++aligncount;
1092. 	}
1093. 	return aligncount;
1094. }
1095. 

root_plselection_prompt[]

1096. char *
1097. root_plselection_prompt(suppliedbuf, buflen, rolenum, racenum, gendnum, alignnum)
1098. char *suppliedbuf;
1099. int buflen, rolenum, racenum, gendnum, alignnum;
1100. {
1101. 	int k, gendercount = 0, aligncount = 0;
1102. 	char buf[BUFSZ];
1103. 	static char err_ret[] = " character's";
1104. 	boolean donefirst = FALSE;
1105. 
1106. 	if (!suppliedbuf || buflen < 1) return err_ret;
1107. 
1108. 	/* initialize these static variables each time this is called */
1109. 	post_attribs = 0;
1110. 	for (k=0; k < NUM_BP; ++k)
1111. 		pa[k] = 0;
1112. 	buf[0] = '\0';
1113. 	*suppliedbuf = '\0';
1114. 	
1115. 	/* How many alignments are allowed for the desired race? */
1116. 	if (racenum != ROLE_NONE && racenum != ROLE_RANDOM)
1117. 		aligncount = race_alignmentcount(racenum);
1118. 
1119. 	if (alignnum != ROLE_NONE && alignnum != ROLE_RANDOM) {
1120. 		/* if race specified, and multiple choice of alignments for it */
1121. 		if ((racenum >= 0) && (aligncount > 1)) {
1122. 			if (donefirst) Strcat(buf, " ");
1123. 			Strcat(buf, aligns[alignnum].adj);
1124. 			donefirst = TRUE;
1125. 		} else {
1126. 			if (donefirst) Strcat(buf, " ");
1127. 			Strcat(buf, aligns[alignnum].adj);
1128. 			donefirst = TRUE;
1129. 		}
1130. 	} else {
1131. 		/* if alignment not specified, but race is specified
1132. 			and only one choice of alignment for that race then
1133. 			don't include it in the later list */
1134. 		if ((((racenum != ROLE_NONE && racenum != ROLE_RANDOM) &&
1135. 			ok_race(rolenum, racenum, gendnum, alignnum))
1136. 		      && (aligncount > 1))
1137. 		     || (racenum == ROLE_NONE || racenum == ROLE_RANDOM)) {
1138. 			pa[BP_ALIGN] = 1;
1139. 			post_attribs++;
1140. 		}
1141. 	}
1142. 	/* <your lawful> */
1143. 
1144. 	/* How many genders are allowed for the desired role? */
1145. 	if (validrole(rolenum))
1146. 		gendercount = role_gendercount(rolenum);
1147. 
1148. 	if (gendnum != ROLE_NONE  && gendnum != ROLE_RANDOM) {
1149. 		if (validrole(rolenum)) {
1150. 		     /* if role specified, and multiple choice of genders for it,
1151. 			and name of role itself does not distinguish gender */
1152. 			if ((rolenum != ROLE_NONE) && (gendercount > 1)
1153. 						&& !roles[rolenum].name.f) {
1154. 				if (donefirst) Strcat(buf, " ");
1155. 				Strcat(buf, genders[gendnum].adj);
1156. 				donefirst = TRUE;
1157. 			}
1158. 	        } else {
1159. 			if (donefirst) Strcat(buf, " ");
1160. 	        	Strcat(buf, genders[gendnum].adj);
1161. 			donefirst = TRUE;
1162. 	        }
1163. 	} else {
1164. 		/* if gender not specified, but role is specified
1165. 			and only one choice of gender then
1166. 			don't include it in the later list */
1167. 		if ((validrole(rolenum) && (gendercount > 1)) || !validrole(rolenum)) {
1168. 			pa[BP_GEND] = 1;
1169. 			post_attribs++;
1170. 		}
1171. 	}
1172. 	/* <your lawful female> */
1173. 
1174. 	if (racenum != ROLE_NONE && racenum != ROLE_RANDOM) {
1175. 		if (validrole(rolenum) && ok_race(rolenum, racenum, gendnum, alignnum)) {
1176. 			if (donefirst) Strcat(buf, " "); 
1177. 			Strcat(buf, (rolenum == ROLE_NONE) ?
1178. 				races[racenum].noun :
1179. 				races[racenum].adj);
1180. 			donefirst = TRUE;
1181. 		} else if (!validrole(rolenum)) {
1182. 			if (donefirst) Strcat(buf, " ");
1183. 			Strcat(buf, races[racenum].noun);
1184. 			donefirst = TRUE;
1185. 		} else {
1186. 			pa[BP_RACE] = 1;
1187. 			post_attribs++;
1188. 		}
1189. 	} else {
1190. 		pa[BP_RACE] = 1;
1191. 		post_attribs++;
1192. 	}
1193. 	/* <your lawful female gnomish> || <your lawful female gnome> */
1194. 
1195. 	if (validrole(rolenum)) {
1196. 		if (donefirst) Strcat(buf, " ");
1197. 		if (gendnum != ROLE_NONE) {
1198. 		    if (gendnum == 1  && roles[rolenum].name.f)
1199. 			Strcat(buf, roles[rolenum].name.f);
1200. 		    else
1201.   			Strcat(buf, roles[rolenum].name.m);
1202. 		} else {
1203. 			if (roles[rolenum].name.f) {
1204. 				Strcat(buf, roles[rolenum].name.m);
1205. 				Strcat(buf, "/");
1206. 				Strcat(buf, roles[rolenum].name.f);
1207. 			} else 
1208. 				Strcat(buf, roles[rolenum].name.m);
1209. 		}
1210. 		donefirst = TRUE;
1211. 	} else if (rolenum == ROLE_NONE) {
1212. 		pa[BP_ROLE] = 1;
1213. 		post_attribs++;
1214. 	}
1215. 	
1216. 	if ((racenum == ROLE_NONE || racenum == ROLE_RANDOM) && !validrole(rolenum)) {
1217. 		if (donefirst) Strcat(buf, " ");
1218. 		Strcat(buf, "character");
1219. 		donefirst = TRUE;
1220. 	}
1221. 	/* <your lawful female gnomish cavewoman> || <your lawful female gnome>
1222. 	 *    || <your lawful female character>
1223. 	 */
1224. 	if (buflen > (int) (strlen(buf) + 1)) {
1225. 		Strcpy(suppliedbuf, buf);
1226. 		return suppliedbuf;
1227. 	} else
1228. 		return err_ret;
1229. }
1230. 

build_plselection_prompt[]

1231. char *
1232. build_plselection_prompt(buf, buflen, rolenum, racenum, gendnum, alignnum)
1233. char *buf;
1234. int buflen, rolenum, racenum, gendnum, alignnum;
1235. {
1236. 	const char *defprompt = "Shall I pick a character for you? [ynq] ";
1237. 	int num_post_attribs = 0;
1238. 	char tmpbuf[BUFSZ];
1239. 	
1240. 	if (buflen < QBUFSZ)
1241. 		return (char *)defprompt;
1242. 
1243. 	Strcpy(tmpbuf, "Shall I pick ");
1244. 	if (racenum != ROLE_NONE || validrole(rolenum))
1245. 		Strcat(tmpbuf, "your ");
1246. 	else {
1247. 		Strcat(tmpbuf, "a ");
1248. 	}
1249. 	/* <your> */
1250. 
1251. 	(void)  root_plselection_prompt(eos(tmpbuf), buflen - strlen(tmpbuf),
1252. 					rolenum, racenum, gendnum, alignnum);
1253. 	Sprintf(buf, "%s", s_suffix(tmpbuf));
1254. 
1255. 	/* buf should now be:
1256. 	 * < your lawful female gnomish cavewoman's> || <your lawful female gnome's>
1257. 	 *    || <your lawful female character's>
1258. 	 *
1259.          * Now append the post attributes to it
1260. 	 */
1261. 
1262. 	num_post_attribs = post_attribs;
1263. 	if (post_attribs) {
1264. 		if (pa[BP_RACE]) {
1265. 			(void) promptsep(eos(buf), num_post_attribs);
1266. 			Strcat(buf, "race");
1267. 		}
1268. 		if (pa[BP_ROLE]) {
1269. 			(void) promptsep(eos(buf), num_post_attribs);
1270. 			Strcat(buf, "role");
1271. 		}
1272. 		if (pa[BP_GEND]) {
1273. 			(void) promptsep(eos(buf), num_post_attribs);
1274. 			Strcat(buf, "gender");
1275. 		}
1276. 		if (pa[BP_ALIGN]) {
1277. 			(void) promptsep(eos(buf), num_post_attribs);
1278. 			Strcat(buf, "alignment");
1279. 		}
1280. 	}
1281. 	Strcat(buf, " for you? [ynq] ");
1282. 	return buf;
1283. }
1284. 
1285. #undef BP_ALIGN
1286. #undef BP_GEND
1287. #undef BP_RACE
1288. #undef BP_ROLE
1289. #undef NUM_BP
1290. 

plnamesuffix[]

1291. void
1292. plnamesuffix()
1293. {
1294. 	char *sptr, *eptr;
1295. 	int i;
1296. 
1297. 	/* Look for tokens delimited by '-' */
1298. 	if ((eptr = index(plname, '-')) != (char *) 0)
1299. 	    *eptr++ = '\0';
1300. 	while (eptr) {
1301. 	    /* Isolate the next token */
1302. 	    sptr = eptr;
1303. 	    if ((eptr = index(sptr, '-')) != (char *)0)
1304. 		*eptr++ = '\0';
1305. 
1306. 	    /* Try to match it to something */
1307. 	    if ((i = str2role(sptr)) != ROLE_NONE)
1308. 		flags.initrole = i;
1309. 	    else if ((i = str2race(sptr)) != ROLE_NONE)
1310. 		flags.initrace = i;
1311. 	    else if ((i = str2gend(sptr)) != ROLE_NONE)
1312. 		flags.initgend = i;
1313. 	    else if ((i = str2align(sptr)) != ROLE_NONE)
1314. 		flags.initalign = i;
1315. 	}
1316. 	if(!plname[0]) {
1317. 	    askname();
1318. 	    plnamesuffix();
1319. 	}
1320. 
1321. 	/* commas in the plname confuse the record file, convert to spaces */
1322. 	for (sptr = plname; *sptr; sptr++) {
1323. 		if (*sptr == ',') *sptr = ' ';
1324. 	}
1325. }
1326. 
1327. 
1328. /*
1329.  *	Special setup modifications here:
1330.  *
1331.  *	Unfortunately, this is going to have to be done
1332.  *	on each newgame or restore, because you lose the permonst mods
1333.  *	across a save/restore.  :-)
1334.  *
1335.  *	1 - The Rogue Leader is the Tourist Nemesis.
1336.  *	2 - Priests start with a random alignment - convert the leader and
1337.  *	    guardians here.
1338.  *	3 - Elves can have one of two different leaders, but can't work it
1339.  *	    out here because it requires hacking the level file data (see
1340.  *	    sp_lev.c).
1341.  *
1342.  * This code also replaces quest_init().
1343.  */

role_init[]

1344. void
1345. role_init()
1346. {
1347. 	int alignmnt;
1348. 
1349. 	/* Strip the role letter out of the player name.
1350. 	 * This is included for backwards compatibility.
1351. 	 */
1352. 	plnamesuffix();
1353. 
1354. 	/* Check for a valid role.  Try flags.initrole first. */
1355. 	if (!validrole(flags.initrole)) {
1356. 	    /* Try the player letter second */
1357. 	    if ((flags.initrole = str2role(pl_character)) < 0)
1358. 	    	/* None specified; pick a random role */
1359. 	    	flags.initrole = randrole();
1360. 	}
1361. 
1362. 	/* We now have a valid role index.  Copy the role name back. */
1363. 	/* This should become OBSOLETE */
1364. 	Strcpy(pl_character, roles[flags.initrole].name.m);
1365. 	pl_character[PL_CSIZ-1] = '\0';
1366. 
1367. 	/* Check for a valid race */
1368. 	if (!validrace(flags.initrole, flags.initrace))
1369. 	    flags.initrace = randrace(flags.initrole);
1370. 
1371. 	/* Check for a valid gender.  If new game, check both initgend
1372. 	 * and female.  On restore, assume flags.female is correct. */
1373. 	if (flags.pantheon == -1) {	/* new game */
1374. 	    if (!validgend(flags.initrole, flags.initrace, flags.female))
1375. 		flags.female = !flags.female;
1376. 	}
1377. 	if (!validgend(flags.initrole, flags.initrace, flags.initgend))
1378. 	    /* Note that there is no way to check for an unspecified gender. */
1379. 	    flags.initgend = flags.female;
1380. 
1381. 	/* Check for a valid alignment */
1382. 	if (!validalign(flags.initrole, flags.initrace, flags.initalign))
1383. 	    /* Pick a random alignment */
1384. 	    flags.initalign = randalign(flags.initrole, flags.initrace);
1385. 	alignmnt = aligns[flags.initalign].value;
1386. 
1387. 	/* Initialize urole and urace */
1388. 	urole = roles[flags.initrole];
1389. 	urace = races[flags.initrace];
1390. 
1391. 	/* Fix up the quest leader */
1392. 	if (urole.ldrnum != NON_PM) {
1393. 	    mons[urole.ldrnum].msound = MS_LEADER;
1394. 	    mons[urole.ldrnum].mflags2 |= (M2_PEACEFUL);
1395. 	    mons[urole.ldrnum].mflags3 |= M3_CLOSE;
1396. 	    mons[urole.ldrnum].maligntyp = alignmnt * 3;
1397. 	}
1398. 
1399. 	/* Fix up the quest guardians */
1400. 	if (urole.guardnum != NON_PM) {
1401. 	    mons[urole.guardnum].mflags2 |= (M2_PEACEFUL);
1402. 	    mons[urole.guardnum].maligntyp = alignmnt * 3;
1403. 	}
1404. 
1405. 	/* Fix up the quest nemesis */
1406. 	if (urole.neminum != NON_PM) {
1407. 	    mons[urole.neminum].msound = MS_NEMESIS;
1408. 	    mons[urole.neminum].mflags2 &= ~(M2_PEACEFUL);
1409. 	    mons[urole.neminum].mflags2 |= (M2_NASTY|M2_STALK|M2_HOSTILE);
1410. 	    mons[urole.neminum].mflags3 |= M3_WANTSARTI | M3_WAITFORU;
1411. 	}
1412. 
1413. 	/* Fix up the god names */
1414. 	if (flags.pantheon == -1) {		/* new game */
1415. 	    flags.pantheon = flags.initrole;	/* use own gods */
1416. 	    while (!roles[flags.pantheon].lgod)	/* unless they're missing */
1417. 		flags.pantheon = randrole();
1418. 	}
1419. 	if (!urole.lgod) {
1420. 	    urole.lgod = roles[flags.pantheon].lgod;
1421. 	    urole.ngod = roles[flags.pantheon].ngod;
1422. 	    urole.cgod = roles[flags.pantheon].cgod;
1423. 	}
1424. 
1425. 	/* Fix up infravision */
1426. 	if (mons[urace.malenum].mflags3 & M3_INFRAVISION) {
1427. 	    /* although an infravision intrinsic is possible, infravision
1428. 	     * is purely a property of the physical race.  This means that we
1429. 	     * must put the infravision flag in the player's current race
1430. 	     * (either that or have separate permonst entries for
1431. 	     * elven/non-elven members of each class).  The side effect is that
1432. 	     * all NPCs of that class will have (probably bogus) infravision,
1433. 	     * but since infravision has no effect for NPCs anyway we can
1434. 	     * ignore this.
1435. 	     */
1436. 	    mons[urole.malenum].mflags3 |= M3_INFRAVISION;
1437. 	    if (urole.femalenum != NON_PM)
1438. 	    	mons[urole.femalenum].mflags3 |= M3_INFRAVISION;
1439. 	}
1440. 
1441. 	/* Artifacts are fixed in hack_artifacts() */
1442. 
1443. 	/* Success! */
1444. 	return;
1445. }
1446. 

Hello[]

1447. const char *
1448. Hello(mtmp)
1449. struct monst *mtmp;
1450. {
1451. 	switch (Role_switch) {
1452. 	case PM_KNIGHT:
1453. 	    return ("Salutations"); /* Olde English */
1454. 	case PM_SAMURAI:
1455. 	    return (mtmp && mtmp->data == &mons[PM_SHOPKEEPER] ?
1456. 	    		"Irasshaimase" : "Konnichi wa"); /* Japanese */
1457. #ifdef TOURIST
1458. 	case PM_TOURIST:
1459. 	    return ("Aloha");       /* Hawaiian */
1460. #endif
1461. 	case PM_VALKYRIE:
1462. 	    return (
1463. #ifdef MAIL
1464. 	    		mtmp && mtmp->data == &mons[PM_MAIL_DAEMON] ? "Hallo" :
1465. #endif
1466. 	    		"Velkommen");   /* Norse */
1467. 	default:
1468. 	    return ("Hello");
1469. 	}
1470. }
1471. 

Main article: Welcome message

Goodbye[]

1472. const char *
1473. Goodbye()
1474. {
1475. 	switch (Role_switch) {
1476. 	case PM_KNIGHT:
1477. 	    return ("Fare thee well");  /* Olde English */
1478. 	case PM_SAMURAI:
1479. 	    return ("Sayonara");        /* Japanese */
1480. #ifdef TOURIST
1481. 	case PM_TOURIST:
1482. 	    return ("Aloha");           /* Hawaiian */
1483. #endif
1484. 	case PM_VALKYRIE:
1485. 	    return ("Farvel");          /* Norse */
1486. 	default:
1487. 	    return ("Goodbye");
1488. 	}
1489. }

Main article: Welcome message#Goodbye message

1490. 
1491. /* role.c */
Advertisement