Difference between revisions of "Source:NetHack 3.4.3/src/role.c"

From NetHackWiki
Jump to navigation Jump to search
m (Add headers to tables of roles, races, etc.)
m (Role.c moved to Source:Role.c: Robot: moved page)
(No difference)

Revision as of 15:05, 4 March 2008

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.

This content was modified from the original NetHack source code distribution (by splitting up NetHack content between wiki pages, and possibly further editing). See the page history for a list of who changed it, and on what dates.

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