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