Wikihack
Advertisement

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

Warning! This is the source code from an old release. For the latest release, see Source code

The NetHack General Public License applies to screenshots, source code and other content from NetHack.
1.    /*	SCCS Id: @(#)role.c	3.3	1999/11/26	*/
2.    /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985-1999. */
3.    /* NetHack may be freely redistributed.  See license for details. */
4.    
5.    #include "hack.h"
6.    
7.    
8.    /*** Table of all roles ***/
9.    /* According to AD&D, HD for some classes (ex. Wizard) should be smaller
10.    * (4-sided for wizards).  But this is not AD&D, and using the AD&D
11.    * rule here produces an unplayable character.  Thus I have used a minimum
12.    * of an 10-sided hit die for everything.  Another AD&D change: wizards get
13.    * a minimum strength of 4 since without one you can't teleport or cast
14.    * spells. --KAA
15.    *
16.    * As the wizard has been updated (wizard patch 5 jun '96) their HD can be
17.    * brought closer into line with AD&D. This forces wizards to use magic more
18.    * and distance themselves from their attackers. --LSZ
19.    *
20.    * With the introduction of races, some hit points and energy
21.    * has been reallocated for each race.  The values assigned
22.    * to the roles has been reduced by the amount allocated to
23.    * humans.  --KMH
24.    *
25.    * God names use a leading underscore to flag goddesses.
26.    */
27.   const struct Role roles[] = {
28.   {	{"Archeologist", 0}, {
29.   	{"Digger",      0},
30.   	{"Field Worker",0},
31.   	{"Investigator",0},
32.   	{"Exhumer",     0},
33.   	{"Excavator",   0},
34.   	{"Spelunker",   0},
35.   	{"Speleologist",0},
36.   	{"Collector",   0},
37.   	{"Curator",     0} },
38.   	"Quetzalcoatl", "Camaxtli", "Huhetotl", /* Central American */
39.   	"Arc", "the College of Archeology", "the Tomb of the Toltec Kings",
40.   	PM_ARCHEOLOGIST, NON_PM, NON_PM,
41.   	PM_LORD_CARNARVON, PM_STUDENT, PM_MINION_OF_HUHETOTL,
42.   	NON_PM, PM_HUMAN_MUMMY, S_SNAKE, S_MUMMY,
43.   	ART_ORB_OF_DETECTION,
44.   	MH_HUMAN|MH_DWARF|MH_GNOME | ROLE_MALE|ROLE_FEMALE |
45.   	  ROLE_LAWFUL|ROLE_NEUTRAL,
46.   	/* Str Int Wis Dex Con Cha */
47.   	{   7, 10, 10,  7,  7,  7 },
48.   	{  20, 20, 20, 10, 20, 10 },
49.   	/* Init   Lower  Higher */
50.   	{ 11, 0,  0, 8,  1, 0 },	/* Hit points */
51.   	{  1, 0,  0, 1,  0, 1 },14,	/* Energy */
52.   	10, 5, 0, 2, 10, A_INT, SPE_MAGIC_MAPPING,   -4
53.   },
54.   {	{"Barbarian", 0}, {
55.   	{"Plunderer",   "Plunderess"},
56.   	{"Pillager",    0},
57.   	{"Bandit",      0},
58.   	{"Brigand",     0},
59.   	{"Raider",      0},
60.   	{"Reaver",      0},
61.   	{"Slayer",      0},
62.   	{"Chieftain",   "Chieftainess"},
63.   	{"Conqueror",   "Conqueress"} },
64.   	"Mitra", "Crom", "Set", /* Hyborian */
65.   	"Bar", "the Camp of the Duali Tribe", "the Duali Oasis",
66.   	PM_BARBARIAN, NON_PM, NON_PM,
67.   	PM_PELIAS, PM_CHIEFTAIN, PM_THOTH_AMON,
68.   	PM_OGRE, PM_TROLL, S_OGRE, S_TROLL,
69.   	ART_HEART_OF_AHRIMAN,
70.   	MH_HUMAN|MH_ORC | ROLE_MALE|ROLE_FEMALE |
71.   	  ROLE_NEUTRAL|ROLE_CHAOTIC,
72.   	/* Str Int Wis Dex Con Cha */
73.   	{  16,  7,  7, 15, 16,  6 },
74.   	{  30,  6,  7, 20, 30,  7 },
75.   	/* Init   Lower  Higher */
76.   	{ 14, 0,  0,10,  2, 0 },	/* Hit points */
77.   	{  1, 0,  0, 1,  0, 1 },10,	/* Energy */
78.   	10, 14, 0, 0,  8, A_INT, SPE_HASTE_SELF,      -4
79.   },
80.   {	{"Caveman", "Cavewoman"}, {
81.   	{"Troglodyte",  0},
82.   	{"Aborigine",   0},
83.   	{"Wanderer",    0},
84.   	{"Vagrant",     0},
85.   	{"Wayfarer",    0},
86.   	{"Roamer",      0},
87.   	{"Nomad",       0},
88.   	{"Rover",       0},
89.   	{"Pioneer",     0} },
90.   	"Anu", "_Ishtar", "Anshar", /* Babylonian */
91.   	"Cav", "the Caves of the Ancestors", "the Dragon's Lair",
92.   	PM_CAVEMAN, PM_CAVEWOMAN, PM_LITTLE_DOG,
93.   	PM_SHAMAN_KARNOV, PM_NEANDERTHAL, PM_CHROMATIC_DRAGON,
94.   	PM_BUGBEAR, PM_HILL_GIANT, S_HUMANOID, S_GIANT,
95.   	ART_SCEPTRE_OF_MIGHT,
96.   	MH_HUMAN|MH_DWARF|MH_GNOME | ROLE_MALE|ROLE_FEMALE |
97.   	  ROLE_LAWFUL|ROLE_NEUTRAL,
98.   	/* Str Int Wis Dex Con Cha */
99.   	{  10,  7,  7,  7,  8,  6 },
100.  	{  30,  6,  7, 20, 30,  7 },
101.  	/* Init   Lower  Higher */
102.  	{ 14, 0,  0, 8,  2, 0 },	/* Hit points */
103.  	{  1, 0,  0, 1,  0, 1 },10,	/* Energy */
104.  	0, 12, 0, 1,  8, A_INT, SPE_DIG,             -4
105.  },
106.  {	{"Healer", 0}, {
107.  	{"Rhizotomist",    0},
108.  	{"Empiric",        0},
109.  	{"Embalmer",       0},
110.  	{"Dresser",        0},
111.  	{"Medici ossium",  0},
112.  	{"Herbalist",      0},
113.  	{"Magister",       0},
114.  	{"Physician",      0},
115.  	{"Chirurgeon",     0} },
116.  	"_Athena", "Hermes", "Poseidon", /* Greek */
117.  	"Hea", "the Temple of Epidaurus", "the Temple of Coeus",
118.  	PM_HEALER, NON_PM, NON_PM,
119.  	PM_HIPPOCRATES, PM_ATTENDANT, PM_CYCLOPS,
120.  	PM_GIANT_RAT, PM_SNAKE, S_RODENT, S_YETI,
121.  	ART_STAFF_OF_AESCULAPIUS,
122.  	MH_HUMAN|MH_GNOME | ROLE_MALE|ROLE_FEMALE | ROLE_NEUTRAL,
123.  	/* Str Int Wis Dex Con Cha */
124.  	{   7,  7, 13,  7, 11, 16 },
125.  	{  15, 20, 20, 15, 25, 10 },
126.  	/* Init   Lower  Higher */
127.  	{ 11, 0,  0, 8,  1, 0 },	/* Hit points */
128.  	{  1, 4,  0, 1,  0, 2 },20,	/* Energy */
129.  	10, 3,-3, 2, 10, A_WIS, SPE_CURE_SICKNESS,   -4
130.  },
131.  {	{"Knight", 0}, {
132.  	{"Gallant",     0},
133.  	{"Esquire",     0},
134.  	{"Bachelor",    0},
135.  	{"Sergeant",    0},
136.  	{"Knight",      0},
137.  	{"Banneret",    0},
138.  	{"Chevalier",   0},
139.  	{"Seignieur",   0},
140.  	{"Paladin",     0} },
141.  	"Lugh", "_Brigit", "Manannan Mac Lir", /* Celtic */
142.  	"Kni", "Camelot Castle", "the Isle of Glass",
143.  	PM_KNIGHT, NON_PM, PM_PONY,
144.  	PM_KING_ARTHUR, PM_PAGE, PM_IXOTH,
145.  	PM_QUASIT, PM_OCHRE_JELLY, S_IMP, S_JELLY,
146.  	ART_MAGIC_MIRROR_OF_MERLIN,
147.  	MH_HUMAN | ROLE_MALE|ROLE_FEMALE | ROLE_LAWFUL,
148.  	/* Str Int Wis Dex Con Cha */
149.  	{  13,  7, 14,  8, 10, 17 },
150.  	{  20, 15, 15, 10, 20, 10 },
151.  	/* Init   Lower  Higher */
152.  	{ 14, 0,  0, 8,  2, 0 },	/* Hit points */
153.  	{  1, 4,  0, 1,  0, 2 },10,	/* Energy */
154.  	10, 8,-2, 0,  9, A_WIS, SPE_TURN_UNDEAD,     -4
155.  },
156.  {	{"Monk", 0}, {
157.  	{"Candidate",                 0},
158.  	{"Novice",                    0},
159.  	{"Initiate",                  0},
160.  	{"Student of the Stone path", 0},
161.  	{"Student of the Waters",     0},
162.  	{"Student of Metals",         0},
163.  	{"Student of the Winds",      0},
164.  	{"Student of Fire",           0},
165.  	{"Master",                    0} },
166.  	"Shan Lai Ching", "Chih Sung-tzu", "Huan Ti", /* Chinese */
167.  	"Mon", "the Monastery of Chan-Sune",
168.  	  "the Monastery of the Earth-Lord",
169.  	PM_MONK, NON_PM, NON_PM,
170.  	PM_GRAND_MASTER, PM_ABBOT, PM_MASTER_KAEN,
171.  	PM_EARTH_ELEMENTAL, PM_XORN, S_ELEMENTAL, S_XORN,
172.  	ART_EYES_OF_THE_OVERWORLD,
173.  	MH_HUMAN | ROLE_MALE|ROLE_FEMALE |
174.  	  ROLE_LAWFUL|ROLE_NEUTRAL|ROLE_CHAOTIC,
175.  	/* Str Int Wis Dex Con Cha */
176.  	{  10,  7,  8,  8,  7,  7 },
177.  	{  25, 10, 20, 20, 15, 10 },
178.  	/* Init   Lower  Higher */
179.  	{ 12, 0,  0, 8,  1, 0 },	/* Hit points */
180.  	{  2, 2,  0, 2,  0, 2 },10,	/* Energy */
181.  	10, 8,-2, 2, 20, A_WIS, SPE_RESTORE_ABILITY, -4
182.  },
183.  {	{"Priest", "Priestess"}, {
184.  	{"Aspirant",    0},
185.  	{"Acolyte",     0},
186.  	{"Adept",       0},
187.  	{"Priest",      "Priestess"},
188.  	{"Curate",      0},
189.  	{"Canon",       "Canoness"},
190.  	{"Lama",        0},
191.  	{"Patriarch",   "Matriarch"},
192.  	{"High Priest", "High Priestess"} },
193.  	0, 0, 0,	/* chosen randomly from among the other roles */
194.  	"Pri", "the Great Temple", "the Temple of Nalzok",
195.  	PM_PRIEST, PM_PRIESTESS, NON_PM,
196.  	PM_ARCH_PRIEST, PM_ACOLYTE, PM_NALZOK,
197.  	PM_HUMAN_ZOMBIE, PM_WRAITH, S_ZOMBIE, S_WRAITH,
198.  	ART_MITRE_OF_HOLINESS,
199.  	MH_HUMAN|MH_ELF | ROLE_MALE|ROLE_FEMALE |
200.  	  ROLE_LAWFUL|ROLE_NEUTRAL|ROLE_CHAOTIC,
201.  	/* Str Int Wis Dex Con Cha */
202.  	{   7,  7, 10,  7,  7,  7 },
203.  	{  15, 10, 30, 15, 20, 10 },
204.  	/* Init   Lower  Higher */
205.  	{ 12, 0,  0, 8,  1, 0 },	/* Hit points */
206.  	{  4, 3,  0, 2,  0, 2 },10,	/* Energy */
207.  	0, 3,-2, 2, 10, A_WIS, SPE_REMOVE_CURSE,    -4
208.  },
209.    /* Note:  Rogue precedes Ranger so that use of `-R' on the command line
210.       retains its traditional meaning. */
211.  {	{"Rogue", 0}, {
212.  	{"Footpad",     0},
213.  	{"Cutpurse",    0},
214.  	{"Rogue",       0},
215.  	{"Pilferer",    0},
216.  	{"Robber",      0},
217.  	{"Burglar",     0},
218.  	{"Filcher",     0},
219.  	{"Magsman",     "Magswoman"},
220.  	{"Thief",       0} },
221.  	"Issek", "Mog", "Kos", /* Nehwon */
222.  	"Rog", "the Thieves' Guild Hall", "the Assassins' Guild Hall",
223.  	PM_ROGUE, NON_PM, NON_PM,
224.  	PM_MASTER_OF_THIEVES, PM_THUG, PM_MASTER_ASSASSIN,
225.  	PM_LEPRECHAUN, PM_GUARDIAN_NAGA, S_NYMPH, S_NAGA,
226.  	ART_MASTER_KEY_OF_THIEVERY,
227.  	MH_HUMAN|MH_ORC | ROLE_MALE|ROLE_FEMALE |
228.  	  ROLE_CHAOTIC,
229.  	/* Str Int Wis Dex Con Cha */
230.  	{   7,  7,  7, 10,  7,  6 },
231.  	{  20, 10, 10, 30, 20, 10 },
232.  	/* Init   Lower  Higher */
233.  	{ 10, 0,  0, 8,  1, 0 },	/* Hit points */
234.  	{  1, 0,  0, 1,  0, 1 },11,	/* Energy */
235.  	10, 8, 0, 1,  9, A_INT, SPE_DETECT_TREASURE, -4
236.  },
237.  {	{"Ranger", 0}, {
238.  #if 0	/* OBSOLETE */
239.  	{"Edhel",       "Elleth"},
240.  	{"Edhel",       "Elleth"},      /* elf-maid */
241.  	{"Ohtar",       "Ohtie"},       /* warrior */
242.  	{"Kano",			/* commander (Q.) ['a] */
243.  			"Kanie"},	/* educated guess, until further research- SAC */
244.  	{"Arandur",			/* king's servant, minister (Q.) - guess */
245.  			"Aranduriel"},	/* educated guess */
246.  	{"Hir",         "Hiril"},       /* lord, lady (S.) ['ir] */
247.  	{"Aredhel",     "Arwen"},       /* noble elf, maiden (S.) */
248.  	{"Ernil",       "Elentariel"},  /* prince (S.), elf-maiden (Q.) */
249.  	{"Elentar",     "Elentari"},	/* Star-king, -queen (Q.) */
250.  	"Solonor Thelandira", "Aerdrie Faenya", "Lolth", /* Elven */
251.  #endif
252.  	{"Tenderfoot",    0},
253.  	{"Lookout",       0},
254.  	{"Trailblazer",   0},
255.  	{"Reconnoiterer", "Reconnoiteress"},
256.  	{"Scout",         0},
257.  	{"Arbalester",    0},	/* One skilled at crossbows */
258.  	{"Archer",        0},
259.  	{"Sharpshooter",  0},
260.  	{"Marksman",      "Markswoman"} },
261.  	"Mercury", "_Venus", "Mars", /* Roman/planets */
262.  	"Ran", "Orion's camp", "the cave of the wumpus",
263.  	PM_RANGER, NON_PM, PM_LITTLE_DOG /* Orion & canis major */,
264.  	PM_ORION, PM_HUNTER, PM_SCORPIUS,
265.  	PM_FOREST_CENTAUR, PM_SCORPION, S_CENTAUR, S_SPIDER,
266.  	ART_LONGBOW_OF_ARTEMIS,
267.  	MH_HUMAN|MH_ELF|MH_GNOME|MH_ORC | ROLE_MALE|ROLE_FEMALE |
268.  	  ROLE_NEUTRAL|ROLE_CHAOTIC,
269.  	/* Str Int Wis Dex Con Cha */
270.  	{  13, 13, 13,  9, 13,  7 },
271.  	{  30, 10, 10, 20, 20, 10 },
272.  	/* Init   Lower  Higher */
273.  	{ 13, 0,  0, 6,  1, 0 },	/* Hit points */
274.  	{  1, 0,  0, 1,  0, 1 },12,	/* Energy */
275.  	10, 9, 2, 1, 10, A_INT, SPE_INVISIBILITY,   -4
276.  },
277.  {	{"Samurai", 0}, {
278.  	{"Hatamoto",    0},  /* Banner Knight */
279.  	{"Ronin",       0},  /* no allegiance */
280.  	{"Ninja",       0},  /* secret society */
281.  	{"Joshu",       0},  /* heads a castle */
282.  	{"Ryoshu",      0},  /* has a territory */
283.  	{"Kokushu",     0},  /* heads a province */
284.  	{"Daimyo",      0},  /* a samurai lord */
285.  	{"Kuge",        0},  /* Noble of the Court */
286.  	{"Shogun",      0} },/* supreme commander, warlord */
287.  	"_Amaterasu Omikami", "Raijin", "Susanowo", /* Japanese */
288.  	"Sam", "the Castle of the Taro Clan", "the Shogun's Castle",
289.  	PM_SAMURAI, NON_PM, PM_LITTLE_DOG,
290.  	PM_LORD_SATO, PM_ROSHI, PM_ASHIKAGA_TAKAUJI,
291.  	PM_WOLF, PM_STALKER, S_DOG, S_ELEMENTAL,
292.  	ART_TSURUGI_OF_MURAMASA,
293.  	MH_HUMAN | ROLE_MALE|ROLE_FEMALE | ROLE_LAWFUL,
294.  	/* Str Int Wis Dex Con Cha */
295.  	{  10,  8,  7, 10, 17,  6 },
296.  	{  30, 10, 10, 30, 14, 10 },
297.  	/* Init   Lower  Higher */
298.  	{ 13, 0,  0, 8,  1, 0 },	/* Hit points */
299.  	{  1, 0,  0, 1,  0, 1 },11,	/* Energy */
300.  	10, 10, 0, 0,  8, A_INT, SPE_CLAIRVOYANCE,    -4
301.  },
302.  #ifdef TOURIST
303.  {	{"Tourist", 0}, {
304.  	{"Rambler",     0},
305.  	{"Sightseer",   0},
306.  	{"Excursionist",0},
307.  	{"Peregrinator","Peregrinatrix"},
308.  	{"Traveler",    0},
309.  	{"Journeyer",   0},
310.  	{"Voyager",     0},
311.  	{"Explorer",    0},
312.  	{"Adventurer",  0} },
313.  	"Blind Io", "_The Lady", "Offler", /* Discworld */
314.  	"Tou", "Ankh-Morpork", "the Thieves' Guild Hall",
315.  	PM_TOURIST, NON_PM, NON_PM,
316.  	PM_TWOFLOWER, PM_GUIDE, PM_MASTER_OF_THIEVES,
317.  	PM_GIANT_SPIDER, PM_FOREST_CENTAUR, S_SPIDER, S_CENTAUR,
318.  	ART_YENDORIAN_EXPRESS_CARD,
319.  	MH_HUMAN | ROLE_MALE|ROLE_FEMALE | ROLE_NEUTRAL,
320.  	/* Str Int Wis Dex Con Cha */
321.  	{   7, 10,  6,  7,  7, 10 },
322.  	{  15, 10, 10, 15, 30, 20 },
323.  	/* Init   Lower  Higher */
324.  	{  8, 0,  0, 8,  0, 0 },	/* Hit points */
325.  	{  1, 0,  0, 1,  0, 1 },14,	/* Energy */
326.  	0, 5, 1, 2, 10, A_INT, SPE_CHARM_MONSTER,   -4
327.  },
328.  #endif
329.  {	{"Valkyrie", 0}, {
330.  	{"Stripling",   0},
331.  	{"Skirmisher",  0},
332.  	{"Fighter",     0},
333.  	{"Man-at-arms", "Woman-at-arms"},
334.  	{"Warrior",     0},
335.  	{"Swashbuckler",0},
336.  	{"Hero",        "Heroine"},
337.  	{"Champion",    0},
338.  	{"Lord",        "Lady"} },
339.  	"Tyr", "Odin", "Loki", /* Norse */
340.  	"Val", "the Shrine of Destiny", "the cave of Surtur",
341.  	PM_VALKYRIE, NON_PM, NON_PM /*PM_WINTER_WOLF_CUB*/,
342.  	PM_NORN, PM_WARRIOR, PM_LORD_SURTUR,
343.  	PM_FIRE_ANT, PM_FIRE_GIANT, S_ANT, S_GIANT,
344.  	ART_ORB_OF_FATE,
345.  	MH_HUMAN|MH_DWARF | ROLE_FEMALE | ROLE_LAWFUL|ROLE_NEUTRAL,
346.  	/* Str Int Wis Dex Con Cha */
347.  	{  10,  7,  7,  7, 10,  7 },
348.  	{  30,  6,  7, 20, 30,  7 },
349.  	/* Init   Lower  Higher */
350.  	{ 14, 0,  0, 8,  2, 0 },	/* Hit points */
351.  	{  1, 0,  0, 1,  0, 1 },10,	/* Energy */
352.  	0, 10,-2, 0,  9, A_WIS, SPE_CONE_OF_COLD,    -4
353.  },
354.  {	{"Wizard", 0}, {
355.  	{"Evoker",      0},
356.  	{"Conjurer",    0},
357.  	{"Thaumaturge", 0},
358.  	{"Magician",    0},
359.  	{"Enchanter",   "Enchantress"},
360.  	{"Sorcerer",    "Sorceress"},
361.  	{"Necromancer", 0},
362.  	{"Wizard",      0},
363.  	{"Mage",        0} },
364.  	"Ptah", "Thoth", "Anhur", /* Egyptian */
365.  	"Wiz", "the Tower of the Balance", "the Tower of Darkness",
366.  	PM_WIZARD, NON_PM, PM_KITTEN,
367.  	PM_WIZARD_OF_BALANCE, PM_APPRENTICE, PM_DARK_ONE,
368.  	PM_VAMPIRE_BAT, PM_XORN, S_BAT, S_WRAITH,
369.  	ART_EYE_OF_THE_AETHIOPICA,
370.  	MH_HUMAN|MH_ELF|MH_GNOME|MH_ORC | ROLE_MALE|ROLE_FEMALE |
371.  	  ROLE_NEUTRAL|ROLE_CHAOTIC,
372.  	/* Str Int Wis Dex Con Cha */
373.  	{   7, 10,  7,  7,  7,  7 },
374.  	{  10, 30, 10, 20, 20, 10 },
375.  	/* Init   Lower  Higher */
376.  	{ 10, 0,  0, 8,  1, 0 },	/* Hit points */
377.  	{  4, 3,  0, 2,  0, 3 },12,	/* Energy */
378.  	0, 1, 0, 3, 10, A_INT, SPE_MAGIC_MISSILE,   -4
379.  },
380.  /* Array terminator */
381.  {{0, 0}}
382.  };
383.  
384.  
385.  /* The player's role, created at runtime from initial
386.   * choices.  This may be munged in role_init().
387.   */
388.  struct Role urole =
389.  {	{"Undefined", 0}, { {0, 0}, {0, 0}, {0, 0},
390.  	{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0} },
391.  	"L", "N", "C", "Xxx", "home", "locate",
392.  	NON_PM, NON_PM, NON_PM, NON_PM, NON_PM, NON_PM,
393.  	NON_PM, NON_PM, 0, 0, 0, 0,
394.  	/* Str Int Wis Dex Con Cha */
395.  	{   7,  7,  7,  7,  7,  7 },
396.  	{  20, 15, 15, 20, 20, 10 },
397.  	/* Init   Lower  Higher */
398.  	{ 10, 0,  0, 8,  1, 0 },	/* Hit points */
399.  	{  2, 0,  0, 2,  0, 3 },14,	/* Energy */
400.  	0, 10, 0, 0,  4, A_INT, 0, -3
401.  };
402.  
403.  
404.  
405.  /* Table of all races */
406.  const struct Race races[] = {
407.  {	"human", "human", "humanity", "Hum",
408.  	{"man", "woman"},
409.  	PM_HUMAN, NON_PM, PM_HUMAN_MUMMY, PM_HUMAN_ZOMBIE,
410.  	MH_HUMAN | ROLE_MALE|ROLE_FEMALE |
411.  	  ROLE_LAWFUL|ROLE_NEUTRAL|ROLE_CHAOTIC,
412.  	MH_HUMAN, 0, MH_GNOME|MH_ORC,
413.  	/*    Str     Int Wis Dex Con Cha */
414.  	{      3,      3,  3,  3,  3,  3 },
415.  	{ STR18(100), 18, 18, 18, 18, 18 },
416.  	/* Init   Lower  Higher */
417.  	{  2, 0,  0, 2,  1, 0 },	/* Hit points */
418.  	{  1, 0,  2, 0,  2, 0 }		/* Energy */
419.  },
420.  {	"elf", "elven", "elvenkind", "Elf",
421.  	{0, 0},
422.  	PM_ELF, NON_PM, PM_ELF_MUMMY, PM_ELF_ZOMBIE,
423.  	MH_ELF | ROLE_MALE|ROLE_FEMALE | ROLE_CHAOTIC,
424.  	MH_ELF, MH_ELF, MH_ORC,
425.  	/*  Str    Int Wis Dex Con Cha */
426.  	{    3,     3,  3,  3,  3,  3 },
427.  	{   18,    20, 20, 18, 16, 18 },
428.  	/* Init   Lower  Higher */
429.  	{  1, 0,  0, 1,  1, 0 },	/* Hit points */
430.  	{  2, 0,  3, 0,  3, 0 }		/* Energy */
431.  },
432.  {	"dwarf", "dwarven", "dwarvenkind", "Dwa",
433.  	{0, 0},
434.  	PM_DWARF, NON_PM, PM_DWARF_MUMMY, PM_DWARF_ZOMBIE,
435.  	MH_DWARF | ROLE_MALE|ROLE_FEMALE | ROLE_LAWFUL,
436.  	MH_DWARF, MH_DWARF|MH_GNOME, MH_ORC,
437.  	/*    Str     Int Wis Dex Con Cha */
438.  	{      3,      3,  3,  3,  3,  3 },
439.  	{ STR18(100), 16, 16, 20, 20, 16 },
440.  	/* Init   Lower  Higher */
441.  	{  4, 0,  0, 3,  2, 0 },	/* Hit points */
442.  	{  0, 0,  0, 0,  0, 0 }		/* Energy */
443.  },
444.  {	"gnome", "gnomish", "gnomehood", "Gno",
445.  	{0, 0},
446.  	PM_GNOME, NON_PM, PM_GNOME_MUMMY, PM_GNOME_ZOMBIE,
447.  	MH_GNOME | ROLE_MALE|ROLE_FEMALE | ROLE_NEUTRAL,
448.  	MH_GNOME, MH_DWARF|MH_GNOME, MH_HUMAN,
449.  	/*  Str    Int Wis Dex Con Cha */
450.  	{    3,     3,  3,  3,  3,  3 },
451.  	{STR18(50),19, 18, 18, 18, 18 },
452.  	/* Init   Lower  Higher */
453.  	{  1, 0,  0, 1,  0, 0 },	/* Hit points */
454.  	{  2, 0,  2, 0,  2, 0 }		/* Energy */
455.  },
456.  {	"orc", "orcish", "orcdom", "Orc",
457.  	{0, 0},
458.  	PM_ORC, NON_PM, PM_ORC_MUMMY, PM_ORC_ZOMBIE,
459.  	MH_ORC | ROLE_MALE|ROLE_FEMALE | ROLE_CHAOTIC,
460.  	MH_ORC, 0, MH_HUMAN|MH_ELF|MH_DWARF,
461.  	/*  Str    Int Wis Dex Con Cha */
462.  	{   3,      3,  3,  3,  3,  3 },
463.  	{STR18(50),16, 16, 18, 18, 16 },
464.  	/* Init   Lower  Higher */
465.  	{  1, 0,  0, 1,  0, 0 },	/* Hit points */
466.  	{  1, 0,  1, 0,  1, 0 }		/* Energy */
467.  },
468.  /* Array terminator */
469.  { 0, 0, 0, 0 }};
470.  
471.  
472.  /* The player's race, created at runtime from initial
473.   * choices.  This may be munged in role_init().
474.   */
475.  struct Race urace =
476.  {	"something", "undefined", "something", "Xxx",
477.  	{0, 0},
478.  	NON_PM, NON_PM, NON_PM, NON_PM,
479.  	0, 0, 0, 0,
480.  	/*    Str     Int Wis Dex Con Cha */
481.  	{      3,      3,  3,  3,  3,  3 },
482.  	{ STR18(100), 18, 18, 18, 18, 18 },
483.  	/* Init   Lower  Higher */
484.  	{  2, 0,  0, 2,  1, 0 },	/* Hit points */
485.  	{  1, 0,  2, 0,  2, 0 }		/* Energy */
486.  };
487.  
488.  
489.  /* Table of all genders */
490.  const struct Gender genders[] = {
491.  	{"male",	"he",	"him",	"his",	"Mal",	ROLE_MALE},
492.  	{"female",	"she",	"her",	"her",	"Fem",	ROLE_FEMALE},
493.  	{"neuter",	"it",	"it",	"its",	"Ntr",	ROLE_NEUTER}
494.  };
495.  
496.  
497.  /* Table of all alignments */
498.  const struct Align aligns[] = {
499.  	{"law",		"lawful",	"Law",	ROLE_LAWFUL,	A_LAWFUL},
500.  	{"balance",	"neutral",	"Neu",	ROLE_NEUTRAL,	A_NEUTRAL},
501.  	{"chaos",	"chaotic",	"Cha",	ROLE_CHAOTIC,	A_CHAOTIC},
502.  	{"evil",	"unaligned",	"Una",	0,		A_NONE}
503.  };
504.  
505.  
506.  boolean
507.  validrole(rolenum)
508.  	int rolenum;
509.  {
510.  	return (rolenum >= 0 && rolenum < SIZE(roles)-1);
511.  }
512.  
513.  
514.  int
515.  randrole()
516.  {
517.  	return (rn2(SIZE(roles)-1));
518.  }
519.  
520.  
521.  int
522.  str2role(str)
523.  	char *str;
524.  {
525.  	int i, len;
526.  
527.  	/* Is str valid? */
528.  	if (!str || !str[0])
529.  	    return (-1);
530.  
531.  	/* "@" returns a random role */
532.  	if (str[0] == '@')
533.  		return (randrole());
534.  
535.  	/* Match as much of str as is provided */
536.  	len = strlen(str);
537.  	for (i = 0; roles[i].name.m; i++) {
538.  	    /* Does it match the male name? */
539.  	    if (!strncmpi(str, roles[i].name.m, len))
540.  	    	return (i);
541.  	    /* Or the female name? */
542.  	    if (roles[i].name.f && !strncmpi(str, roles[i].name.f, len))
543.  	    	return (i);
544.  	    /* Or the filecode? */
545.  	    if (!strcmpi(str, roles[i].filecode))
546.  	    	return (i);
547.  	}
548.  
549.  	/* Couldn't find anything appropriate */
550.  	return (-1);
551.  }
552.  
553.  
554.  boolean
555.  validrace(rolenum, racenum)
556.  	int rolenum, racenum;
557.  {
558.  	/* Assumes validrole */
559.  	return (racenum >= 0 && racenum < SIZE(races)-1 &&
560.  		(roles[rolenum].allow & races[racenum].allow & ROLE_RACEMASK));
561.  }
562.  
563.  
564.  int
565.  randrace(rolenum)
566.  	int rolenum;
567.  {
568.  	int i, n = 0;
569.  
570.  	/* Count the number of valid races */
571.  	for (i = 0; races[i].noun; i++)
572.  	    if (roles[rolenum].allow & races[i].allow & ROLE_RACEMASK)
573.  	    	n++;
574.  
575.  	/* Pick a random race */
576.  	/* Use a factor of 100 in case of bad random number generators */
577.  	if (n) n = rn2(n*100)/100;
578.  	for (i = 0; races[i].noun; i++)
579.  	    if (roles[rolenum].allow & races[i].allow & ROLE_RACEMASK) {
580.  	    	if (n) n--;
581.  	    	else return (i);
582.  	    }
583.  
584.  	/* This role has no permitted races? */
585.  	return (rn2(SIZE(races)-1));
586.  }
587.  
588.  
589.  int
590.  str2race(str)
591.  	char *str;
592.  {
593.  	int i, len;
594.  
595.  	/* Is str valid? */
596.  	if (!str || !str[0])
597.  	    return (-1);
598.  
599.  	/* Match as much of str as is provided */
600.  	len = strlen(str);
601.  	for (i = 0; races[i].noun; i++) {
602.  	    /* Does it match the noun? */
603.  	    if (!strncmpi(str, races[i].noun, len))
604.  	    	return (i);
605.  	    /* Or the filecode? */
606.  	    if (!strcmpi(str, races[i].filecode))
607.  	    	return (i);
608.  	}
609.  
610.  	/* Couldn't find anything appropriate */
611.  	return (-1);
612.  }
613.  
614.  
615.  boolean
616.  validgend(rolenum, racenum, gendnum)
617.  	int rolenum, racenum, gendnum;
618.  {
619.  	/* Assumes validrole and validrace */
620.  	return (gendnum >= 0 && gendnum < ROLE_GENDERS &&
621.  		(roles[rolenum].allow & races[racenum].allow &
622.  		 genders[gendnum].allow & ROLE_GENDMASK));
623.  }
624.  
625.  
626.  int
627.  randgend(rolenum, racenum)
628.  	int rolenum, racenum;
629.  {
630.  	int i, n = 0;
631.  
632.  	/* Count the number of valid genders */
633.  	for (i = 0; i < ROLE_GENDERS; i++)
634.  	    if (roles[rolenum].allow & races[racenum].allow &
635.  	    		genders[i].allow & ROLE_GENDMASK)
636.  	    	n++;
637.  
638.  	/* Pick a random gender */
639.  	if (n) n = rn2(n);
640.  	for (i = 0; i < ROLE_GENDERS; i++)
641.  	    if (roles[rolenum].allow & races[racenum].allow &
642.  	    		genders[i].allow & ROLE_GENDMASK) {
643.  	    	if (n) n--;
644.  	    	else return (i);
645.  	    }
646.  
647.  	/* This role/race has no permitted genders? */
648.  	return (rn2(ROLE_GENDERS));
649.  }
650.  
651.  
652.  int
653.  str2gend(str)
654.  	char *str;
655.  {
656.  	int i, len;
657.  
658.  	/* Is str valid? */
659.  	if (!str || !str[0])
660.  	    return (-1);
661.  
662.  	/* Match as much of str as is provided */
663.  	len = strlen(str);
664.  	for (i = 0; i < ROLE_GENDERS; i++) {
665.  	    /* Does it match the adjective? */
666.  	    if (!strncmpi(str, genders[i].adj, len))
667.  	    	return (i);
668.  	    /* Or the filecode? */
669.  	    if (!strcmpi(str, genders[i].filecode))
670.  	    	return (i);
671.  	}
672.  
673.  	/* Couldn't find anything appropriate */
674.  	return (-1);
675.  }
676.  
677.  
678.  boolean
679.  validalign(rolenum, racenum, alignnum)
680.  	int rolenum, racenum, alignnum;
681.  {
682.  	/* Assumes validrole and validrace */
683.  	return (alignnum >= 0 && alignnum < ROLE_ALIGNS &&
684.  		(roles[rolenum].allow & races[racenum].allow &
685.  		 aligns[alignnum].allow & ROLE_ALIGNMASK));
686.  }
687.  
688.  
689.  int
690.  randalign(rolenum, racenum)
691.  	int rolenum, racenum;
692.  {
693.  	int i, n = 0;
694.  
695.  	/* Count the number of valid alignments */
696.  	for (i = 0; i < ROLE_ALIGNS; i++)
697.  	    if (roles[rolenum].allow & races[racenum].allow &
698.  	    		aligns[i].allow & ROLE_ALIGNMASK)
699.  	    	n++;
700.  
701.  	/* Pick a random alignment */
702.  	if (n) n = rn2(n);
703.  	for (i = 0; i < ROLE_ALIGNS; i++)
704.  	    if (roles[rolenum].allow & races[racenum].allow &
705.  	    		aligns[i].allow & ROLE_ALIGNMASK) {
706.  	    	if (n) n--;
707.  	    	else return (i);
708.  	    }
709.  
710.  	/* This role/race has no permitted alignments? */
711.  	return (rn2(ROLE_ALIGNS));
712.  }
713.  
714.  
715.  int
716.  str2align(str)
717.  	char *str;
718.  {
719.  	int i, len;
720.  
721.  	/* Is str valid? */
722.  	if (!str || !str[0])
723.  	    return (-1);
724.  
725.  	/* Match as much of str as is provided */
726.  	len = strlen(str);
727.  	for (i = 0; i < ROLE_ALIGNS; i++) {
728.  	    /* Does it match the adjective? */
729.  	    if (!strncmpi(str, aligns[i].adj, len))
730.  	    	return (i);
731.  	    /* Or the filecode? */
732.  	    if (!strcmpi(str, aligns[i].filecode))
733.  	    	return (i);
734.  	}
735.  
736.  	/* Couldn't find anything appropriate */
737.  	return (-1);
738.  }
739.  
740.  
741.  void
742.  plnamesuffix()
743.  {
744.  	char *sptr, *eptr;
745.  	int i;
746.  
747.  	/* Look for tokens delimited by '-' */
748.  	if ((eptr = index(plname, '-')) != (char *) 0)
749.  	    *eptr++ = '\0';
750.  	while (eptr) {
751.  	    /* Isolate the next token */
752.  	    sptr = eptr;
753.  	    if ((eptr = index(sptr, '-')) != (char *)0)
754.  	    	*eptr++ = '\0';
755.  
756.  	    /* Try to match it to something */
757.  	    if ((i = str2role(sptr)) >= 0)
758.  	    	flags.initrole = i;
759.  	    else if ((i = str2race(sptr)) >= 0)
760.  	    	flags.initrace = i;
761.  	    else if ((i = str2gend(sptr)) >= 0)
762.  	    	flags.initgend = i;
763.  	    else if ((i = str2align(sptr)) >= 0)
764.  	    	flags.initalign = i;
765.  	}
766.  	if(!plname[0]) {
767.  	    askname();
768.  	    plnamesuffix();
769.  	}
770.  	return;
771.  }
772.  
773.  
774.  /*
775.   *	Special setup modifications here:
776.   *
777.   *	Unfortunately, this is going to have to be done
778.   *	on each newgame or restore, because you lose the permonst mods
779.   *	across a save/restore.  :-)
780.   *
781.   *	1 - The Rogue Leader is the Tourist Nemesis.
782.   *	2 - Priests start with a random alignment - convert the leader and
783.   *	    guardians here.
784.   *	3 - Elves can have one of two different leaders, but can't work it
785.   *	    out here because it requires hacking the level file data (see
786.   *	    sp_lev.c).
787.   *
788.   * This code also replaces quest_init().
789.   */
790.  void
791.  role_init()
792.  {
793.  	int alignmnt;
794.  
795.  	/* Strip the role letter out of the player name.
796.  	 * This is included for backwards compatibility.
797.  	 */
798.  	plnamesuffix();
799.  
800.  	/* Check for a valid role.  Try flags.initrole first. */
801.  	if (!validrole(flags.initrole)) {
802.  	    /* Try the player letter second */
803.  	    if ((flags.initrole = str2role(pl_character)) < 0)
804.  	    	/* None specified; pick a random role */
805.  	    	flags.initrole = randrole();
806.  	}
807.  
808.  	/* We now have a valid role index.  Copy the role name back. */
809.  	/* This should become OBSOLETE */
810.  	Strcpy(pl_character, roles[flags.initrole].name.m);
811.  	pl_character[PL_CSIZ-1] = '\0';
812.  
813.  	/* Check for a valid race */
814.  	if (!validrace(flags.initrole, flags.initrace))
815.  	    flags.initrace = randrace(flags.initrole);
816.  
817.  	/* Check for a valid gender.  Try flags.igend first. */
818.  	if (!validgend(flags.initrole, flags.initrace, flags.initgend))
819.  	    /* Use flags.female second.  Note that there is no way
820.  	     * to check for an unspecified gender.
821.  	     */
822.  	    flags.initgend = flags.female;
823.  	/* Don't change flags.female; this may be a restore */
824.  
825.  	/* Check for a valid alignment */
826.  	if (!validalign(flags.initrole, flags.initrace, flags.initalign))
827.  	    /* Pick a random alignment */
828.  	    flags.initalign = randalign(flags.initrole, flags.initrace);
829.  	alignmnt = aligns[flags.initalign].value;
830.  
831.  	/* Initialize urole and urace */
832.  	urole = roles[flags.initrole];
833.  	urace = races[flags.initrace];
834.  
835.  	/* Fix up the quest leader */
836.  	if (urole.ldrnum != NON_PM) {
837.  	    mons[urole.ldrnum].msound = MS_LEADER;
838.  	    mons[urole.ldrnum].mflags2 |= (M2_PEACEFUL);
839.  	    mons[urole.ldrnum].mflags3 = M3_CLOSE;
840.  	    mons[urole.ldrnum].maligntyp = alignmnt * 3;
841.  	}
842.  
843.  	/* Fix up the quest guardians */
844.  	if (urole.guardnum != NON_PM) {
845.  	    mons[urole.guardnum].mflags2 |= (M2_PEACEFUL);
846.  	    mons[urole.guardnum].maligntyp = alignmnt * 3;
847.  	}
848.  
849.  	/* Fix up the quest nemesis */
850.  	if (urole.neminum != NON_PM) {
851.  	    mons[urole.neminum].msound = MS_NEMESIS;
852.  	    mons[urole.neminum].mflags2 &= ~(M2_PEACEFUL);
853.  	    mons[urole.neminum].mflags2 |= (M2_NASTY|M2_STALK|M2_HOSTILE);
854.  	    mons[urole.neminum].mflags3 = M3_WANTSARTI | M3_WAITFORU;
855.  	}
856.  
857.  	/* Fix up the god names */
858.  	if (flags.pantheon == -1) {		/* new game */
859.  	    flags.pantheon = flags.initrole;	/* use own gods */
860.  	    while (!roles[flags.pantheon].lgod)	/* unless they're missing */
861.  		flags.pantheon = randrole();
862.  	}
863.  	if (!urole.lgod) {
864.  	    urole.lgod = roles[flags.pantheon].lgod;
865.  	    urole.ngod = roles[flags.pantheon].ngod;
866.  	    urole.cgod = roles[flags.pantheon].cgod;
867.  	}
868.  
869.  	/* Fix up infravision */
870.  	if (mons[urace.malenum].mflags3 & M3_INFRAVISION) {
871.  	    /* although an infravision intrinsic is possible, infravision
872.  	     * is purely a property of the physical race.  This means that we
873.  	     * must put the infravision flag in the player's current race
874.  	     * (either that or have separate permonst entries for
875.  	     * elven/non-elven members of each class).  The side effect is that
876.  	     * all NPCs of that class will have (probably bogus) infravision,
877.  	     * but since infravision has no effect for NPCs anyway we can
878.  	     * ignore this.
879.  	     */
880.  	    mons[urole.malenum].mflags3 |= M3_INFRAVISION;
881.  	    if (urole.femalenum != NON_PM)
882.  	    	mons[urole.femalenum].mflags3 |= M3_INFRAVISION;
883.  	}
884.  
885.  	/* Artifacts are fixed in hack_artifacts() */
886.  
887.  	/* Success! */
888.  	return;
889.  }
890.  
891.  const char *
892.  Hello()
893.  {
894.  	switch (Role_switch) {
895.  	case PM_KNIGHT:
896.  	    return ("Salutations"); /* Olde English */
897.  	case PM_SAMURAI:
898.  	    return ("Konnichi wa"); /* Japanese */
899.  #ifdef TOURIST
900.  	case PM_TOURIST:
901.  	    return ("Aloha");       /* Hawaiian */
902.  #endif
903.  	case PM_VALKYRIE:
904.  	    return ("Velkommen");   /* Norse */
905.  	default:
906.  	    return ("Hello");
907.  	}
908.  }
909.  
910.  const char *
911.  Goodbye()
912.  {
913.  	switch (Role_switch) {
914.  	case PM_KNIGHT:
915.  	    return ("Fare thee well");  /* Olde English */
916.  	case PM_SAMURAI:
917.  	    return ("Sayonara");        /* Japanese */
918.  #ifdef TOURIST
919.  	case PM_TOURIST:
920.  	    return ("Aloha");           /* Hawaiian */
921.  #endif
922.  	case PM_VALKYRIE:
923.  	    return ("Farvel");          /* Norse */
924.  	default:
925.  	    return ("Goodbye");
926.  	}
927.  }
928.  
929.  /* role.c */
Advertisement