Source:SLASH'EM 0.0.7E7F2/role.c

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

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

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