1 /* NetHack 3.6 role.c $NHDT-Date: 1446861770 2015/11/07 02:02:50 $ $NHDT-Branch: master $:$NHDT-Revision: 1.34 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985-1999. */
3 /* NetHack may be freely redistributed. See license for details. */
7 /*** Table of all roles ***/
8 /* According to AD&D, HD for some classes (ex. Wizard) should be smaller
9 * (4-sided for wizards). But this is not AD&D, and using the AD&D
10 * rule here produces an unplayable character. Thus I have used a minimum
11 * of an 10-sided hit die for everything. Another AD&D change: wizards get
12 * a minimum strength of 4 since without one you can't teleport or cast
15 * As the wizard has been updated (wizard patch 5 jun '96) their HD can be
16 * brought closer into line with AD&D. This forces wizards to use magic more
17 * and distance themselves from their attackers. --LSZ
19 * With the introduction of races, some hit points and energy
20 * has been reallocated for each race. The values assigned
21 * to the roles has been reduced by the amount allocated to
24 * God names use a leading underscore to flag goddesses.
26 const struct Role roles[] = {
28 { { "Archeologist", 0 },
30 { "Field Worker", 0 },
31 { "Investigator", 0 },
35 { "Speleologist", 0 },
38 "Quetzalcoatl", "Camaxtli", "Huhetotl", /* Central American */
40 { { "
\8dl
\8cÃ
\8aw
\8eÒ", 0 },
42 { "
\98J
\93
\8eÒ", 0 },
43 { "
\92²
\8d¸
\8eÒ", 0 },
44 { "
\94
\8c@
\8eÒ", 0 },
45 { "
\8c@
\8dí
\8eÒ", 0 },
46 { "
\92T
\8c\9f\8eÒ", 0 },
47 { "
\93´
\8cA
\8aw
\8eÒ", 0 },
48 { "
\94ü
\8fp
\8eû
\8fW
\8eÒ", 0 },
50 "
\83P
\83c
\83A
\83\8b\83J
\83g
\83\8b", "
\83J
\83}
\83L
\83V
\83g
\83\8a", "
\83t
\83w
\83g
\83g
\83\8b", /* Central American */
54 "the College of Archeology",
55 "the Tomb of the Toltec Kings",
57 "
\8dl
\8cÃ
\8aw
\91å
\8aw",
58 "
\83g
\83\8b\83e
\83J
\89¤
\89Æ
\82Ì
\95æ",
65 PM_MINION_OF_HUHETOTL,
71 MH_HUMAN | MH_DWARF | MH_GNOME | ROLE_MALE | ROLE_FEMALE | ROLE_LAWFUL
73 /* Str Int Wis Dex Con Cha */
74 { 7, 10, 10, 7, 7, 7 },
75 { 20, 20, 20, 10, 20, 10 },
76 /* Init Lower Higher */
77 { 11, 0, 0, 8, 1, 0 }, /* Hit points */
90 { { "Plunderer", "Plunderess" },
97 { "Chieftain", "Chieftainess" },
98 { "Conqueror", "Conqueress" } },
99 "Mitra", "Crom", "Set", /* Hyborian */
101 { { "
\96ì
\94Ø
\90l", 0 },
102 { { "
\93\90\91¯", 0 },
103 { "
\97ª
\92D
\8eÒ", 0 },
106 { "
\90N
\97ª
\8eÒ", 0 },
108 { "
\8eE
\9dC
\8eÒ", 0 },
110 { "
\90ª
\95\9e\8eÒ", 0 } },
111 "
\83~
\83g
\83\89", "
\83N
\83\8d\83\80", "
\83Z
\83g", /* Hyborian */
115 "the Camp of the Duali Tribe",
118 "
\83f
\83\85\83A
\83\8a\91°
\82Ì
\83L
\83\83\83\93\83v",
119 "
\83f
\83\85\83A
\83\8a\91°
\82Ì
\83I
\83A
\83V
\83X",
131 ART_HEART_OF_AHRIMAN,
132 MH_HUMAN | MH_ORC | ROLE_MALE | ROLE_FEMALE | ROLE_NEUTRAL
134 /* Str Int Wis Dex Con Cha */
135 { 16, 7, 7, 15, 16, 6 },
136 { 30, 6, 7, 20, 30, 7 },
137 /* Init Lower Higher */
138 { 14, 0, 0, 10, 2, 0 }, /* Hit points */
139 { 1, 0, 0, 1, 0, 1 },
150 { { "Caveman", "Cavewoman" },
151 { { "Troglodyte", 0 },
160 "Anu", "_Ishtar", "Anshar", /* Babylonian */
162 { { "
\93´
\8cA
\90l", 0 },
163 { { "
\8c\8a\8b\8f\90l", 0 },
164 { "
\8c´
\8fZ
\96¯", 0 },
165 { "
\95ú
\98Q
\8eÒ", 0 },
166 { "
\95\82\98Q
\8eÒ", 0 },
167 { "
\97·
\8ds
\8eÒ", 0 },
168 { "
\95ú
\97V
\8eÒ", 0 },
169 { "
\97V
\96q
\96¯", 0 },
170 { "
\97¬
\98Q
\8eÒ", 0 },
171 { "
\90æ
\8bì
\8eÒ", 0 } },
172 "
\83A
\83k", "_
\83C
\83V
\83\85\83^
\83\8b", "
\83A
\83\93\83V
\83\83\83\8b", /* Babylonian */
176 "the Caves of the Ancestors",
179 "
\91¾
\8cÃ
\82Ì
\93´
\8cA",
180 "
\97³
\82Ì
\89B
\82ê
\89Æ",
192 ART_SCEPTRE_OF_MIGHT,
193 MH_HUMAN | MH_DWARF | MH_GNOME | ROLE_MALE | ROLE_FEMALE | ROLE_LAWFUL
195 /* Str Int Wis Dex Con Cha */
196 { 10, 7, 7, 7, 8, 6 },
197 { 30, 6, 7, 20, 30, 7 },
198 /* Init Lower Higher */
199 { 14, 0, 0, 8, 2, 0 }, /* Hit points */
200 { 1, 0, 0, 1, 0, 1 },
212 { { "Rhizotomist", 0 },
216 { "Medicus ossium", "Medica ossium" },
218 { "Magister", "Magistra" },
220 { "Chirurgeon", 0 } },
221 "_Athena", "Hermes", "Poseidon", /* Greek */
224 { { "
\8c©
\8fK
\82¢", 0 },
225 { "
\88ã
\8et
\8c©
\8fK
\82¢", 0 },
226 { "
\8aÅ
\8cì
\8et", "
\8aÅ
\8cì
\95w" },
227 { "
\88ã
\8et
\8f\95\8eè", 0 },
228 { "
\96ò
\95¨
\8eå
\94C", 0 },
229 { "
\8a¿
\95û
\88ã", 0 },
230 { "
\88ã
\8et
\8eå
\94C", 0 },
231 { "
\93à
\89È
\88ã", 0 },
232 { "
\8aO
\89È
\88ã", 0 } },
233 "_
\83A
\83e
\83i", "
\83w
\83\8b\83\81\83X", "
\83|
\83Z
\83C
\83h
\83\93", /* Greek */
237 "the Temple of Epidaurus",
238 "the Temple of Coeus",
240 "
\83G
\83s
\83_
\83E
\83\8d\83X
\8e\9b\89@",
241 "
\83R
\83C
\83I
\83X
\8e\9b\89@",
253 ART_STAFF_OF_AESCULAPIUS,
254 MH_HUMAN | MH_GNOME | ROLE_MALE | ROLE_FEMALE | ROLE_NEUTRAL,
255 /* Str Int Wis Dex Con Cha */
256 { 7, 7, 13, 7, 11, 16 },
257 { 15, 20, 20, 15, 25, 5 },
258 /* Init Lower Higher */
259 { 11, 0, 0, 8, 1, 0 }, /* Hit points */
260 { 1, 4, 0, 1, 0, 2 },
278 { "Chevalier", "Chevaliere" },
279 { "Seignieur", "Dame" },
281 "Lugh", "_Brigit", "Manannan Mac Lir", /* Celtic */
284 { { "
\8c©
\8fK
\82¢", 0 },
288 { "
\8fd
\90í
\8em", 0 },
290 { "
\8fd
\8bR
\8em", 0 },
291 { "
\8cM
\8bR
\8em", 0 },
292 { "
\90¹
\8bR
\8em", 0 } },
293 "
\83\8b\81[
\83t", "_
\83u
\83\8a\83W
\83b
\83g", "
\83}
\83i
\83\93\83i
\83\93\81E
\83}
\83N
\83\8a\81[
\83\8b", /* Celtic */
300 "
\83L
\83\83\83\81\83\8d\83b
\83g
\8fé",
301 "
\83K
\83\89\83X
\82Ì
\93\87",
313 ART_MAGIC_MIRROR_OF_MERLIN,
314 MH_HUMAN | ROLE_MALE | ROLE_FEMALE | ROLE_LAWFUL,
315 /* Str Int Wis Dex Con Cha */
316 { 13, 7, 14, 8, 10, 17 },
317 { 30, 15, 15, 10, 20, 10 },
318 /* Init Lower Higher */
319 { 14, 0, 0, 8, 2, 0 }, /* Hit points */
320 { 1, 4, 0, 1, 0, 2 },
332 { { "Candidate", 0 },
335 { "Student of Stones", 0 },
336 { "Student of Waters", 0 },
337 { "Student of Metals", 0 },
338 { "Student of Winds", 0 },
339 { "Student of Fire", 0 },
341 "Shan Lai Ching", "Chih Sung-tzu", "Huan Ti", /* Chinese */
343 { { "
\95\90\93¬
\89Æ", 0 },
344 { { "
\93ü
\96å
\8aó
\96]
\8eÒ", 0 },
345 { "
\8f\89\90S
\8eÒ", 0 },
346 { "
\93ü
\96å
\8eÒ
\93`", 0 },
347 { "
\93y
\82Ì
\8fK
\82¢
\8eè", 0 },
348 { "
\90\85\82Ì
\8fK
\82¢
\8eè", 0 },
349 { "
\8bà
\82Ì
\8fK
\82¢
\8eè", 0 },
350 { "
\96Ø
\82Ì
\8fK
\82¢
\8eè", 0 },
351 { "
\89Î
\82Ì
\8fK
\82¢
\8eè", 0 },
352 { "
\96Æ
\8b\96\8aF
\93`", 0 } },
353 "
\8eR
\97\8b\90¸", "
\90Ô
\8f¼
\8eq", "
\89©
\92é", /* Chinese */
357 "the Monastery of Chan-Sune",
358 "the Monastery of the Earth-Lord",
360 "
\83`
\83\83\83\93\81E
\83X
\81[
\8fC
\93¹
\89@",
361 "
\92n
\89¤
\82Ì
\8fC
\93¹
\89@",
373 ART_EYES_OF_THE_OVERWORLD,
374 MH_HUMAN | ROLE_MALE | ROLE_FEMALE | ROLE_LAWFUL | ROLE_NEUTRAL
376 /* Str Int Wis Dex Con Cha */
377 { 10, 7, 8, 8, 7, 7 },
378 { 25, 10, 20, 20, 15, 10 },
379 /* Init Lower Higher */
380 { 12, 0, 0, 8, 1, 0 }, /* Hit points */
381 { 2, 2, 0, 2, 0, 2 },
392 { { "Priest", "Priestess" },
396 { "Priest", "Priestess" },
398 { "Canon", "Canoness" },
400 { "Patriarch", "Matriarch" },
401 { "High Priest", "High Priestess" } },
402 0, 0, 0, /* deities from a randomly chosen other role will be used */
404 { { "
\91m
\97µ", "
\93ò
\91m" },
405 { { "
\8fC
\93¹
\8eÒ", "
\8fC
\93¹
\8f\97" },
408 { "
\91m
\97µ", "
\93ò
\91m" },
409 { "
\8f\95\94C
\8ei
\8dÕ", 0 },
410 { "
\90¹
\8eÒ", "
\90¹
\8f\97" },
412 { "
\91å
\8ei
\8b³", 0 },
413 { "
\91å
\91m
\8fã", 0 } },
414 0, 0, 0, /* deities from a randomly chosen other role will be used */
419 "the Temple of Nalzok",
421 "
\88Ì
\91å
\82È
\82é
\8e\9b\89@",
422 "
\83i
\83\8b\83]
\83N
\8e\9b\89@",
434 ART_MITRE_OF_HOLINESS,
435 MH_HUMAN | MH_ELF | ROLE_MALE | ROLE_FEMALE | ROLE_LAWFUL | ROLE_NEUTRAL
437 /* Str Int Wis Dex Con Cha */
438 { 7, 7, 10, 7, 7, 7 },
439 { 15, 10, 30, 15, 20, 10 },
440 /* Init Lower Higher */
441 { 12, 0, 0, 8, 1, 0 }, /* Hit points */
442 { 4, 3, 0, 2, 0, 2 },
452 /* Note: Rogue precedes Ranger so that use of `-R' on the command line
453 retains its traditional meaning. */
463 { "Magsman", "Magswoman" },
465 "Issek", "Mog", "Kos", /* Nehwon */
467 { { "
\93\90\91¯", 0 },
468 { { "
\92Ç
\82¢
\82Í
\82¬", 0 },
469 { "
\82Ð
\82Á
\82½
\82
\82è", 0 },
471 { "
\82²
\82ë
\82Â
\82«", 0 },
472 { "
\82±
\82»
\82Ç
\82ë", 0 },
476 { "
\91å
\93D
\96_", 0 } },
477 "
\83C
\83Z
\83b
\83N", "
\83\82\83O", "
\83R
\83X", /* Nehwon */
481 "the Thieves' Guild Hall",
482 "the Assassins' Guild Hall",
484 "
\93\90\91¯
\83M
\83\8b\83h",
485 "
\88Ã
\8eE
\8eÒ
\83M
\83\8b\83h",
490 PM_MASTER_OF_THIEVES,
497 ART_MASTER_KEY_OF_THIEVERY,
498 MH_HUMAN | MH_ORC | ROLE_MALE | ROLE_FEMALE | ROLE_CHAOTIC,
499 /* Str Int Wis Dex Con Cha */
500 { 7, 7, 7, 10, 7, 6 },
501 { 20, 10, 10, 30, 20, 10 },
502 /* Init Lower Higher */
503 { 10, 0, 0, 8, 1, 0 }, /* Hit points */
504 { 1, 0, 0, 1, 0, 1 },
519 {"Edhel", "Elleth"}, /* elf-maid */
520 {"Ohtar", "Ohtie"}, /* warrior */
521 {"Kano", "Kanie"}, /* commander (Q.) ['a] educated guess,
522 until further research- SAC */
523 {"Arandur"," Aranduriel"}, /* king's servant, minister (Q.) - guess */
524 {"Hir", "Hiril"}, /* lord, lady (S.) ['ir] */
525 {"Aredhel", "Arwen"}, /* noble elf, maiden (S.) */
526 {"Ernil", "Elentariel"}, /* prince (S.), elf-maiden (Q.) */
527 {"Elentar", "Elentari"}, /* Star-king, -queen (Q.) */
528 "Solonor Thelandira", "Aerdrie Faenya", "Lolth", /* Elven */
532 { "Trailblazer", 0 },
533 { "Reconnoiterer", "Reconnoiteress" },
535 { "Arbalester", 0 }, /* One skilled at crossbows */
537 { "Sharpshooter", 0 },
538 { "Marksman", "Markswoman" } },
539 "Mercury", "_Venus", "Mars", /* Roman/planets */
541 { { "
\83\8c\83\93\83W
\83\83\81[", 0 },
543 { "
\8c©
\92£
\82è", 0 },
547 { "
\8b|
\95º", 0 }, /* One skilled at crossbows */
548 { "
\92\86\8b\89\8b|
\95º", 0 },
549 { "
\8fã
\8b\89\8b|
\95º", 0 },
550 { "
\8fã
\8b\89\8b|
\95º", 0 } },
551 "Mercury", "_Venus", "Mars", /* Roman/planets */
556 "the cave of the wumpus",
558 "
\83I
\83\8a\83I
\83\93\82Ì
\83L
\83\83\83\93\83v",
559 "
\83\8f\83\93\83p
\83X
\82Ì
\93´
\8cA",
563 PM_LITTLE_DOG /* Orion & canis major */,
571 ART_LONGBOW_OF_DIANA,
572 MH_HUMAN | MH_ELF | MH_GNOME | MH_ORC | ROLE_MALE | ROLE_FEMALE
573 | ROLE_NEUTRAL | ROLE_CHAOTIC,
574 /* Str Int Wis Dex Con Cha */
575 { 13, 13, 13, 9, 13, 7 },
576 { 30, 10, 10, 20, 20, 10 },
577 /* Init Lower Higher */
578 { 13, 0, 0, 6, 1, 0 }, /* Hit points */
579 { 1, 0, 0, 1, 0, 1 },
591 { { "Hatamoto", 0 }, /* Banner Knight */
592 { "Ronin", 0 }, /* no allegiance */
593 { "Ninja", "Kunoichi" }, /* secret society */
594 { "Joshu", 0 }, /* heads a castle */
595 { "Ryoshu", 0 }, /* has a territory */
596 { "Kokushu", 0 }, /* heads a province */
597 { "Daimyo", 0 }, /* a samurai lord */
598 { "Kuge", 0 }, /* Noble of the Court */
599 { "Shogun", 0 } }, /* supreme commander, warlord */
600 "_Amaterasu Omikami", "Raijin", "Susanowo", /* Japanese */
603 { { "
\8aø
\96{", 0 }, /* Banner Knight */
604 { "
\98Q
\90l", 0 }, /* no allegiance */
605 { "
\94E
\8eÒ", "
\82
\83m
\88ê" }, /* secret society */
606 { "
\8fé
\8eå", 0 }, /* heads a castle */
607 { "
\97Ì
\8eå", 0 }, /* has a territory */
608 { "
\97Ì
\8eå", 0 }, /* heads a province */
609 { "
\91å
\96¼", "
\8d\98\8c³" }, /* a samurai lord */
610 { "
\8cö
\89Æ", 0 }, /* Noble of the Court */
611 { "
\8cö
\89Æ", "
\91å
\89\9c" } }, /* supreme commander, warlord */
612 "_
\93V
\8fÆ
\91å
\90_", "
\97\8b\90_", "
\90{
\8d²
\94V
\92j", /* Japanese */
616 "the Castle of the Taro Clan",
617 "the Shogun's Castle",
619 "
\91¾
\98Y
\88ê
\91°
\82Ì
\8fé",
632 ART_TSURUGI_OF_MURAMASA,
633 MH_HUMAN | ROLE_MALE | ROLE_FEMALE | ROLE_LAWFUL,
634 /* Str Int Wis Dex Con Cha */
635 { 10, 8, 7, 10, 17, 6 },
636 { 30, 10, 8, 30, 14, 8 },
637 /* Init Lower Higher */
638 { 13, 0, 0, 8, 1, 0 }, /* Hit points */
639 { 1, 0, 0, 1, 0, 1 },
653 { "Excursionist", 0 },
654 { "Peregrinator", "Peregrinatrix" },
659 { "Adventurer", 0 } },
660 "Blind Io", "_The Lady", "Offler", /* Discworld */
662 { { "
\8aÏ
\8cõ
\8bq", 0 },
663 { { "
\83v
\81[
\91¾
\98Y", "
\83v
\81[
\8eq" },
664 { "
\8aÏ
\8cõ
\8bq", 0 },
665 { "
\8eü
\97V
\97·
\8ds
\8eÒ", 0 },
666 { "
\95Õ
\97ð
\8eÒ", 0 },
667 { "
\97·
\8ds
\8eÒ", 0 },
669 { "
\8dq
\8aC
\8eÒ", 0 },
670 { "
\92T
\8c\9f\89Æ", 0 },
671 { "
\96`
\8c¯
\8eÒ", 0 } },
672 "
\96Ó
\96Ú
\82Ì
\83C
\83\8d", "_
\81\83\8f\97\90_
\81\84", "
\83I
\83t
\83\89\81[", /* Discworld */
677 "the Thieves' Guild Hall",
680 "
\93\90\91¯
\83M
\83\8b\83h",
687 PM_MASTER_OF_THIEVES,
692 ART_YENDORIAN_EXPRESS_CARD,
693 MH_HUMAN | ROLE_MALE | ROLE_FEMALE | ROLE_NEUTRAL,
694 /* Str Int Wis Dex Con Cha */
695 { 7, 10, 6, 7, 7, 10 },
696 { 15, 10, 10, 15, 30, 20 },
697 /* Init Lower Higher */
698 { 8, 0, 0, 8, 0, 0 }, /* Hit points */
699 { 1, 0, 0, 1, 0, 1 },
711 { { "Stripling", 0 },
714 { "Man-at-arms", "Woman-at-arms" },
716 { "Swashbuckler", 0 },
717 { "Hero", "Heroine" },
719 { "Lord", "Lady" } },
720 "Tyr", "Odin", "Loki", /* Norse */
722 { { "
\83\8f\83\8b\83L
\83\85\81[
\83\8c", 0 },
723 { { "
\8c©
\8fK
\82¢", 0 },
727 { "
\90í
\93¬
\95º", 0 },
728 { "
\8dU
\8c\82\95º", 0 },
730 { "
\90æ
\93±
\8eÒ", 0 },
731 { "
\83\8d\81[
\83h", "
\83\8c\83f
\83B" } },
732 "
\83`
\83\85\81[
\83\8b", "
\83I
\81[
\83f
\83B
\83\93", "
\83\8d\83L", /* Norse */
736 "the Shrine of Destiny",
737 "the cave of Surtur",
739 "
\89^
\96½
\82Ì
\90¹
\93°",
740 "
\83X
\83\8b\83g
\82Ì
\93´
\8cA",
744 NON_PM /*PM_WINTER_WOLF_CUB*/,
753 MH_HUMAN | MH_DWARF | ROLE_FEMALE | ROLE_LAWFUL | ROLE_NEUTRAL,
754 /* Str Int Wis Dex Con Cha */
755 { 10, 7, 7, 7, 10, 7 },
756 { 30, 6, 7, 20, 30, 7 },
757 /* Init Lower Higher */
758 { 14, 0, 0, 8, 2, 0 }, /* Hit points */
759 { 1, 0, 0, 1, 0, 1 },
773 { "Thaumaturge", 0 },
775 { "Enchanter", "Enchantress" },
776 { "Sorcerer", "Sorceress" },
777 { "Necromancer", 0 },
780 "Ptah", "Thoth", "Anhur", /* Egyptian */
782 { { "
\96\82\96@
\8eg
\82¢", 0 },
783 { { "
\8eè
\95i
\8et", 0 },
784 { "
\8aï
\8fp
\8et", 0 },
785 { "
\90è
\82¢
\8et", 0 },
786 { "
\97ì
\8a´
\8et", 0 },
787 { "
\8f¢
\8a«
\8et", 0 },
788 { "
\97d
\8fp
\8et", 0 },
789 { "
\96\82\8fp
\8et", 0 },
790 { "
\96\82\96@
\8eg
\82¢", 0 },
791 { "
\91å
\96\82\96@
\8eg
\82¢", 0 } },
792 "
\83v
\83^
\83n", "
\83g
\81[
\83g", "
\83A
\83\93\83t
\83\8b", /* Egyptian */
797 "the Tower of Darkness",
799 "
\8cÇ
\8d\82\82Ì
\93\83",
800 "
\88Ã
\8d\95\82Ì
\93\83",
805 PM_NEFERET_THE_GREEN,
812 ART_EYE_OF_THE_AETHIOPICA,
813 MH_HUMAN | MH_ELF | MH_GNOME | MH_ORC | ROLE_MALE | ROLE_FEMALE
814 | ROLE_NEUTRAL | ROLE_CHAOTIC,
815 /* Str Int Wis Dex Con Cha */
816 { 7, 10, 7, 7, 7, 7 },
817 { 10, 30, 10, 20, 20, 10 },
818 /* Init Lower Higher */
819 { 10, 0, 0, 8, 1, 0 }, /* Hit points */
820 { 4, 3, 0, 2, 0, 3 },
830 /* Array terminator */
834 /* The player's role, created at runtime from initial
835 * choices. This may be munged in role_init().
837 struct Role urole = {
839 { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
840 { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } },
842 "Xxx", "home", "locate",
843 NON_PM, NON_PM, NON_PM, NON_PM, NON_PM, NON_PM, NON_PM, NON_PM,
845 /* Str Int Wis Dex Con Cha */
846 { 7, 7, 7, 7, 7, 7 },
847 { 20, 15, 15, 20, 20, 10 },
848 /* Init Lower Higher */
849 { 10, 0, 0, 8, 1, 0 }, /* Hit points */
850 { 2, 0, 0, 2, 0, 3 },
862 /* Table of all races */
863 const struct Race races[] = {
878 { "
\92j", "
\8f\97" },
884 MH_HUMAN | ROLE_MALE | ROLE_FEMALE | ROLE_LAWFUL | ROLE_NEUTRAL
889 /* Str Int Wis Dex Con Cha */
890 { 3, 3, 3, 3, 3, 3 },
891 { STR18(100), 18, 18, 18, 18, 18 },
892 /* Init Lower Higher */
893 { 2, 0, 0, 2, 1, 0 }, /* Hit points */
894 { 1, 0, 2, 0, 2, 0 } /* Energy */
903 "
\83G
\83\8b\83t
\82Ì",
912 MH_ELF | ROLE_MALE | ROLE_FEMALE | ROLE_CHAOTIC,
916 /* Str Int Wis Dex Con Cha */
917 { 3, 3, 3, 3, 3, 3 },
918 { 18, 20, 20, 18, 16, 18 },
919 /* Init Lower Higher */
920 { 1, 0, 0, 1, 1, 0 }, /* Hit points */
921 { 2, 0, 3, 0, 3, 0 } /* Energy */
929 "
\83h
\83\8f\81[
\83t",
930 "
\83h
\83\8f\81[
\83t
\82Ì",
931 "
\83h
\83\8f\81[
\83t",
939 MH_DWARF | ROLE_MALE | ROLE_FEMALE | ROLE_LAWFUL,
943 /* Str Int Wis Dex Con Cha */
944 { 3, 3, 3, 3, 3, 3 },
945 { STR18(100), 16, 16, 20, 20, 16 },
946 /* Init Lower Higher */
947 { 4, 0, 0, 3, 2, 0 }, /* Hit points */
948 { 0, 0, 0, 0, 0, 0 } /* Energy */
957 "
\83m
\81[
\83\80\82Ì",
966 MH_GNOME | ROLE_MALE | ROLE_FEMALE | ROLE_NEUTRAL,
970 /* Str Int Wis Dex Con Cha */
971 { 3, 3, 3, 3, 3, 3 },
972 { STR18(50), 19, 18, 18, 18, 18 },
973 /* Init Lower Higher */
974 { 1, 0, 0, 1, 0, 0 }, /* Hit points */
975 { 2, 0, 2, 0, 2, 0 } /* Energy */
993 MH_ORC | ROLE_MALE | ROLE_FEMALE | ROLE_CHAOTIC,
996 MH_HUMAN | MH_ELF | MH_DWARF,
997 /* Str Int Wis Dex Con Cha */
998 { 3, 3, 3, 3, 3, 3 },
999 { STR18(50), 16, 16, 18, 18, 16 },
1000 /* Init Lower Higher */
1001 { 1, 0, 0, 1, 0, 0 }, /* Hit points */
1002 { 1, 0, 1, 0, 1, 0 } /* Energy */
1004 /* Array terminator */
1008 /* The player's race, created at runtime from initial
1009 * choices. This may be munged in role_init().
1011 struct Race urace = {
1025 /* Str Int Wis Dex Con Cha */
1026 { 3, 3, 3, 3, 3, 3 },
1027 { STR18(100), 18, 18, 18, 18, 18 },
1028 /* Init Lower Higher */
1029 { 2, 0, 0, 2, 1, 0 }, /* Hit points */
1030 { 1, 0, 2, 0, 2, 0 } /* Energy */
1033 /* Table of all genders */
1035 - steed.c kick_steed() He[]
\82É
\92l
\82ª
\83R
\83s
\81[
\82³
\82ê
\82é
\82Ì
\82Å
\92·
\82³
\82ð
\95Ï
\82¦
\82½
\82Æ
\82«
\82É
\82Í
1036 \8aY
\93\96\95\94\82à
\97v
\8fC
\90³
\81B
1038 const struct Gender genders[] = {
1040 { "male", "he", "him", "his", "Mal", ROLE_MALE },
1041 { "female", "she", "her", "her", "Fem", ROLE_FEMALE },
1042 { "neuter", "it", "it", "its", "Ntr", ROLE_NEUTER }
1044 { "
\92j
\90«", "
\94Þ", "
\94Þ", "
\94Þ
\82Ì", "Mal", ROLE_MALE },
1045 { "
\8f\97\90«", "
\94Þ
\8f\97", "
\94Þ
\8f\97", "
\94Þ
\8f\97\82Ì", "Fem", ROLE_FEMALE },
1046 { "
\92\86\90«", "
\82»
\82ê", "
\82»
\82ê", "
\82»
\82Ì", "Ntr", ROLE_NEUTER }
1050 /* Table of all alignments */
1051 const struct Align aligns[] = {
1053 { "law", "lawful", "Law", ROLE_LAWFUL, A_LAWFUL },
1054 { "balance", "neutral", "Neu", ROLE_NEUTRAL, A_NEUTRAL },
1055 { "chaos", "chaotic", "Cha", ROLE_CHAOTIC, A_CHAOTIC },
1056 { "evil", "unaligned", "Una", 0, A_NONE }
1058 { "
\92\81\8f\98", "
\92\81\8f\98\82Ì", "Law", ROLE_LAWFUL, A_LAWFUL },
1059 { "
\92\86\97§", "
\92\86\97§
\82Ì", "Neu", ROLE_NEUTRAL, A_NEUTRAL },
1060 { "
\8d¬
\93×", "
\8d¬
\93×
\82Ì", "Cha", ROLE_CHAOTIC, A_CHAOTIC },
1061 { "
\96³
\90S", "
\96³
\90S
\82Ì", "Una", 0, A_NONE }
1067 boolean roles[SIZE(roles)];
1071 STATIC_DCL int NDECL(randrole_filtered);
1072 STATIC_DCL char *FDECL(promptsep, (char *, int));
1073 STATIC_DCL int FDECL(role_gendercount, (int));
1074 STATIC_DCL int FDECL(race_alignmentcount, (int));
1076 /* used by str2XXX() */
1078 static char NEARDATA randomstr[] = "random";
1080 static char NEARDATA randomstr[] = "
\83\89\83\93\83_
\83\80";
1086 return (boolean) (rolenum >= 0 && rolenum < SIZE(roles) - 1);
1092 return rn2(SIZE(roles) - 1);
1098 int i, n = 0, set[SIZE(roles)];
1100 /* this doesn't rule out impossible combinations but attempts to
1101 honor all the filter masks */
1102 for (i = 0; i < SIZE(roles); ++i)
1103 if (ok_role(i, ROLE_NONE, ROLE_NONE, ROLE_NONE)
1104 && ok_race(i, ROLE_RANDOM, ROLE_NONE, ROLE_NONE)
1105 && ok_gend(i, ROLE_NONE, ROLE_RANDOM, ROLE_NONE)
1106 && ok_align(i, ROLE_NONE, ROLE_NONE, ROLE_RANDOM))
1108 return n ? set[rn2(n)] : randrole();
1118 if (!str || !str[0])
1121 /* Match as much of str as is provided */
1123 for (i = 0; roles[i].name.m; i++) {
1124 /* Does it match the male name? */
1125 if (!strncmpi(str, roles[i].name.m, len))
1127 /* Or the female name? */
1128 if (roles[i].name.f && !strncmpi(str, roles[i].name.f, len))
1130 /* Or the filecode? */
1131 if (!strcmpi(str, roles[i].filecode))
1135 if ((len == 1 && (*str == '*' || *str == '@'))
1136 || !strncmpi(str, randomstr, len))
1139 /* Couldn't find anything appropriate */
1144 validrace(rolenum, racenum)
1145 int rolenum, racenum;
1147 /* Assumes validrole */
1148 return (boolean) (racenum >= 0 && racenum < SIZE(races) - 1
1149 && (roles[rolenum].allow & races[racenum].allow
1159 /* Count the number of valid races */
1160 for (i = 0; races[i].noun; i++)
1161 if (roles[rolenum].allow & races[i].allow & ROLE_RACEMASK)
1164 /* Pick a random race */
1165 /* Use a factor of 100 in case of bad random number generators */
1167 n = rn2(n * 100) / 100;
1168 for (i = 0; races[i].noun; i++)
1169 if (roles[rolenum].allow & races[i].allow & ROLE_RACEMASK) {
1176 /* This role has no permitted races? */
1177 return rn2(SIZE(races) - 1);
1187 if (!str || !str[0])
1190 /* Match as much of str as is provided */
1192 for (i = 0; races[i].noun; i++) {
1193 /* Does it match the noun? */
1194 if (!strncmpi(str, races[i].noun, len))
1196 /* Or the filecode? */
1197 if (!strcmpi(str, races[i].filecode))
1201 if ((len == 1 && (*str == '*' || *str == '@'))
1202 || !strncmpi(str, randomstr, len))
1205 /* Couldn't find anything appropriate */
1210 validgend(rolenum, racenum, gendnum)
1211 int rolenum, racenum, gendnum;
1213 /* Assumes validrole and validrace */
1214 return (boolean) (gendnum >= 0 && gendnum < ROLE_GENDERS
1215 && (roles[rolenum].allow & races[racenum].allow
1216 & genders[gendnum].allow & ROLE_GENDMASK));
1220 randgend(rolenum, racenum)
1221 int rolenum, racenum;
1225 /* Count the number of valid genders */
1226 for (i = 0; i < ROLE_GENDERS; i++)
1227 if (roles[rolenum].allow & races[racenum].allow & genders[i].allow
1231 /* Pick a random gender */
1234 for (i = 0; i < ROLE_GENDERS; i++)
1235 if (roles[rolenum].allow & races[racenum].allow & genders[i].allow
1243 /* This role/race has no permitted genders? */
1244 return rn2(ROLE_GENDERS);
1254 if (!str || !str[0])
1257 /* Match as much of str as is provided */
1259 for (i = 0; i < ROLE_GENDERS; i++) {
1260 /* Does it match the adjective? */
1261 if (!strncmpi(str, genders[i].adj, len))
1263 /* Or the filecode? */
1264 if (!strcmpi(str, genders[i].filecode))
1267 if ((len == 1 && (*str == '*' || *str == '@'))
1268 || !strncmpi(str, randomstr, len))
1271 /* Couldn't find anything appropriate */
1276 validalign(rolenum, racenum, alignnum)
1277 int rolenum, racenum, alignnum;
1279 /* Assumes validrole and validrace */
1280 return (boolean) (alignnum >= 0 && alignnum < ROLE_ALIGNS
1281 && (roles[rolenum].allow & races[racenum].allow
1282 & aligns[alignnum].allow & ROLE_ALIGNMASK));
1286 randalign(rolenum, racenum)
1287 int rolenum, racenum;
1291 /* Count the number of valid alignments */
1292 for (i = 0; i < ROLE_ALIGNS; i++)
1293 if (roles[rolenum].allow & races[racenum].allow & aligns[i].allow
1297 /* Pick a random alignment */
1300 for (i = 0; i < ROLE_ALIGNS; i++)
1301 if (roles[rolenum].allow & races[racenum].allow & aligns[i].allow
1309 /* This role/race has no permitted alignments? */
1310 return rn2(ROLE_ALIGNS);
1320 if (!str || !str[0])
1323 /* Match as much of str as is provided */
1325 for (i = 0; i < ROLE_ALIGNS; i++) {
1326 /* Does it match the adjective? */
1327 if (!strncmpi(str, aligns[i].adj, len))
1329 /* Or the filecode? */
1330 if (!strcmpi(str, aligns[i].filecode))
1333 if ((len == 1 && (*str == '*' || *str == '@'))
1334 || !strncmpi(str, randomstr, len))
1337 /* Couldn't find anything appropriate */
1341 /* is rolenum compatible with any racenum/gendnum/alignnum constraints? */
1343 ok_role(rolenum, racenum, gendnum, alignnum)
1344 int rolenum, racenum, gendnum, alignnum;
1349 if (rolenum >= 0 && rolenum < SIZE(roles) - 1) {
1350 if (filter.roles[rolenum])
1352 allow = roles[rolenum].allow;
1353 if (racenum >= 0 && racenum < SIZE(races) - 1
1354 && !(allow & races[racenum].allow & ROLE_RACEMASK))
1356 if (gendnum >= 0 && gendnum < ROLE_GENDERS
1357 && !(allow & genders[gendnum].allow & ROLE_GENDMASK))
1359 if (alignnum >= 0 && alignnum < ROLE_ALIGNS
1360 && !(allow & aligns[alignnum].allow & ROLE_ALIGNMASK))
1364 /* random; check whether any selection is possible */
1365 for (i = 0; i < SIZE(roles) - 1; i++) {
1366 if (filter.roles[i])
1368 allow = roles[i].allow;
1369 if (racenum >= 0 && racenum < SIZE(races) - 1
1370 && !(allow & races[racenum].allow & ROLE_RACEMASK))
1372 if (gendnum >= 0 && gendnum < ROLE_GENDERS
1373 && !(allow & genders[gendnum].allow & ROLE_GENDMASK))
1375 if (alignnum >= 0 && alignnum < ROLE_ALIGNS
1376 && !(allow & aligns[alignnum].allow & ROLE_ALIGNMASK))
1384 /* pick a random role subject to any racenum/gendnum/alignnum constraints */
1385 /* If pickhow == PICK_RIGID a role is returned only if there is */
1386 /* a single possibility */
1388 pick_role(racenum, gendnum, alignnum, pickhow)
1389 int racenum, gendnum, alignnum, pickhow;
1392 int roles_ok = 0, set[SIZE(roles)];
1394 for (i = 0; i < SIZE(roles) - 1; i++) {
1395 if (ok_role(i, racenum, gendnum, alignnum)
1396 && ok_race(i, (racenum >= 0) ? racenum : ROLE_RANDOM,
1398 && ok_gend(i, racenum,
1399 (gendnum >= 0) ? gendnum : ROLE_RANDOM, alignnum)
1400 && ok_race(i, racenum,
1401 gendnum, (alignnum >= 0) ? alignnum : ROLE_RANDOM))
1402 set[roles_ok++] = i;
1404 if (roles_ok == 0 || (roles_ok > 1 && pickhow == PICK_RIGID))
1406 return set[rn2(roles_ok)];
1409 /* is racenum compatible with any rolenum/gendnum/alignnum constraints? */
1411 ok_race(rolenum, racenum, gendnum, alignnum)
1412 int rolenum, racenum, gendnum, alignnum;
1417 if (racenum >= 0 && racenum < SIZE(races) - 1) {
1418 if (filter.mask & races[racenum].selfmask)
1420 allow = races[racenum].allow;
1421 if (rolenum >= 0 && rolenum < SIZE(roles) - 1
1422 && !(allow & roles[rolenum].allow & ROLE_RACEMASK))
1424 if (gendnum >= 0 && gendnum < ROLE_GENDERS
1425 && !(allow & genders[gendnum].allow & ROLE_GENDMASK))
1427 if (alignnum >= 0 && alignnum < ROLE_ALIGNS
1428 && !(allow & aligns[alignnum].allow & ROLE_ALIGNMASK))
1432 /* random; check whether any selection is possible */
1433 for (i = 0; i < SIZE(races) - 1; i++) {
1434 if (filter.mask & races[i].selfmask)
1436 allow = races[i].allow;
1437 if (rolenum >= 0 && rolenum < SIZE(roles) - 1
1438 && !(allow & roles[rolenum].allow & ROLE_RACEMASK))
1440 if (gendnum >= 0 && gendnum < ROLE_GENDERS
1441 && !(allow & genders[gendnum].allow & ROLE_GENDMASK))
1443 if (alignnum >= 0 && alignnum < ROLE_ALIGNS
1444 && !(allow & aligns[alignnum].allow & ROLE_ALIGNMASK))
1452 /* pick a random race subject to any rolenum/gendnum/alignnum constraints */
1453 /* If pickhow == PICK_RIGID a race is returned only if there is */
1454 /* a single possibility */
1456 pick_race(rolenum, gendnum, alignnum, pickhow)
1457 int rolenum, gendnum, alignnum, pickhow;
1462 for (i = 0; i < SIZE(races) - 1; i++) {
1463 if (ok_race(rolenum, i, gendnum, alignnum))
1466 if (races_ok == 0 || (races_ok > 1 && pickhow == PICK_RIGID))
1468 races_ok = rn2(races_ok);
1469 for (i = 0; i < SIZE(races) - 1; i++) {
1470 if (ok_race(rolenum, i, gendnum, alignnum)) {
1480 /* is gendnum compatible with any rolenum/racenum/alignnum constraints? */
1481 /* gender and alignment are not comparable (and also not constrainable) */
1483 ok_gend(rolenum, racenum, gendnum, alignnum)
1484 int rolenum, racenum, gendnum;
1485 int alignnum UNUSED;
1490 if (gendnum >= 0 && gendnum < ROLE_GENDERS) {
1491 if (filter.mask & genders[gendnum].allow)
1493 allow = genders[gendnum].allow;
1494 if (rolenum >= 0 && rolenum < SIZE(roles) - 1
1495 && !(allow & roles[rolenum].allow & ROLE_GENDMASK))
1497 if (racenum >= 0 && racenum < SIZE(races) - 1
1498 && !(allow & races[racenum].allow & ROLE_GENDMASK))
1502 /* random; check whether any selection is possible */
1503 for (i = 0; i < ROLE_GENDERS; i++) {
1504 if (filter.mask & genders[i].allow)
1506 allow = genders[i].allow;
1507 if (rolenum >= 0 && rolenum < SIZE(roles) - 1
1508 && !(allow & roles[rolenum].allow & ROLE_GENDMASK))
1510 if (racenum >= 0 && racenum < SIZE(races) - 1
1511 && !(allow & races[racenum].allow & ROLE_GENDMASK))
1519 /* pick a random gender subject to any rolenum/racenum/alignnum constraints */
1520 /* gender and alignment are not comparable (and also not constrainable) */
1521 /* If pickhow == PICK_RIGID a gender is returned only if there is */
1522 /* a single possibility */
1524 pick_gend(rolenum, racenum, alignnum, pickhow)
1525 int rolenum, racenum, alignnum, pickhow;
1530 for (i = 0; i < ROLE_GENDERS; i++) {
1531 if (ok_gend(rolenum, racenum, i, alignnum))
1534 if (gends_ok == 0 || (gends_ok > 1 && pickhow == PICK_RIGID))
1536 gends_ok = rn2(gends_ok);
1537 for (i = 0; i < ROLE_GENDERS; i++) {
1538 if (ok_gend(rolenum, racenum, i, alignnum)) {
1548 /* is alignnum compatible with any rolenum/racenum/gendnum constraints? */
1549 /* alignment and gender are not comparable (and also not constrainable) */
1551 ok_align(rolenum, racenum, gendnum, alignnum)
1552 int rolenum, racenum;
1559 if (alignnum >= 0 && alignnum < ROLE_ALIGNS) {
1560 if (filter.mask & aligns[alignnum].allow)
1562 allow = aligns[alignnum].allow;
1563 if (rolenum >= 0 && rolenum < SIZE(roles) - 1
1564 && !(allow & roles[rolenum].allow & ROLE_ALIGNMASK))
1566 if (racenum >= 0 && racenum < SIZE(races) - 1
1567 && !(allow & races[racenum].allow & ROLE_ALIGNMASK))
1571 /* random; check whether any selection is possible */
1572 for (i = 0; i < ROLE_ALIGNS; i++) {
1573 if (filter.mask & aligns[i].allow)
1575 allow = aligns[i].allow;
1576 if (rolenum >= 0 && rolenum < SIZE(roles) - 1
1577 && !(allow & roles[rolenum].allow & ROLE_ALIGNMASK))
1579 if (racenum >= 0 && racenum < SIZE(races) - 1
1580 && !(allow & races[racenum].allow & ROLE_ALIGNMASK))
1588 /* pick a random alignment subject to any rolenum/racenum/gendnum constraints
1590 /* alignment and gender are not comparable (and also not constrainable) */
1591 /* If pickhow == PICK_RIGID an alignment is returned only if there is */
1592 /* a single possibility */
1594 pick_align(rolenum, racenum, gendnum, pickhow)
1595 int rolenum, racenum, gendnum, pickhow;
1600 for (i = 0; i < ROLE_ALIGNS; i++) {
1601 if (ok_align(rolenum, racenum, gendnum, i))
1604 if (aligns_ok == 0 || (aligns_ok > 1 && pickhow == PICK_RIGID))
1606 aligns_ok = rn2(aligns_ok);
1607 for (i = 0; i < ROLE_ALIGNS; i++) {
1608 if (ok_align(rolenum, racenum, gendnum, i)) {
1621 /* Some roles are limited to a single race, alignment, or gender and
1622 * calling this routine prior to XXX_player_selection() will help
1623 * prevent an extraneous prompt that actually doesn't allow
1624 * you to choose anything further. Note the use of PICK_RIGID which
1625 * causes the pick_XX() routine to return a value only if there is one
1626 * single possible selection, otherwise it returns ROLE_NONE.
1629 if (flags.initrole == ROLE_RANDOM) {
1630 /* If the role was explicitly specified as ROLE_RANDOM
1631 * via -uXXXX-@ then choose the role in here to narrow down
1632 * later choices. Pick a random role in this case.
1634 flags.initrole = pick_role(flags.initrace, flags.initgend,
1635 flags.initalign, PICK_RANDOM);
1636 if (flags.initrole < 0)
1637 flags.initrole = randrole_filtered();
1639 if (flags.initrole != ROLE_NONE) {
1640 if (flags.initrace == ROLE_NONE)
1641 flags.initrace = pick_race(flags.initrole, flags.initgend,
1642 flags.initalign, PICK_RIGID);
1643 if (flags.initalign == ROLE_NONE)
1644 flags.initalign = pick_align(flags.initrole, flags.initrace,
1645 flags.initgend, PICK_RIGID);
1646 if (flags.initgend == ROLE_NONE)
1647 flags.initgend = pick_gend(flags.initrole, flags.initrace,
1648 flags.initalign, PICK_RIGID);
1657 boolean reslt = TRUE;
1659 if ((i = str2role(bufp)) != ROLE_NONE && i != ROLE_RANDOM)
1660 filter.roles[i] = TRUE;
1661 else if ((i = str2race(bufp)) != ROLE_NONE && i != ROLE_RANDOM)
1662 filter.mask |= races[i].selfmask;
1663 else if ((i = str2gend(bufp)) != ROLE_NONE && i != ROLE_RANDOM)
1664 filter.mask |= genders[i].allow;
1665 else if ((i = str2align(bufp)) != ROLE_NONE && i != ROLE_RANDOM)
1666 filter.mask |= aligns[i].allow;
1679 for (i = 0; i < SIZE(roles); ++i)
1680 if (filter.roles[i])
1690 for (i = 0; i < SIZE(roles); ++i)
1691 filter.roles[i] = FALSE;
1701 STATIC_VAR char pa[NUM_BP], post_attribs;
1704 promptsep(buf, num_post_attribs)
1706 int num_post_attribs;
1709 const char *conjuct = "and ";
1711 if (num_post_attribs > 1 && post_attribs < num_post_attribs
1712 && post_attribs > 1)
1716 if (!post_attribs && num_post_attribs > 1)
1717 Strcat(buf, conjuct);
1719 /*JP:
\93ú
\96{
\8cê
\82Å
\82Í "A, B, and C"
\82Æ
\82¢
\82¤
\8f\88\97\9d\82Í
\95s
\97v */
1720 if(num_post_attribs > post_attribs){
1721 Strcat(buf, "
\81C");
1729 role_gendercount(rolenum)
1734 if (validrole(rolenum)) {
1735 if (roles[rolenum].allow & ROLE_MALE)
1737 if (roles[rolenum].allow & ROLE_FEMALE)
1739 if (roles[rolenum].allow & ROLE_NEUTER)
1746 race_alignmentcount(racenum)
1751 if (racenum != ROLE_NONE && racenum != ROLE_RANDOM) {
1752 if (races[racenum].allow & ROLE_CHAOTIC)
1754 if (races[racenum].allow & ROLE_LAWFUL)
1756 if (races[racenum].allow & ROLE_NEUTRAL)
1763 root_plselection_prompt(suppliedbuf, buflen, rolenum, racenum, gendnum,
1766 int buflen, rolenum, racenum, gendnum, alignnum;
1768 int k, gendercount = 0, aligncount = 0;
1771 static char err_ret[] = " character's";
1773 static char err_ret[] = "
\83L
\83\83\83\89\83N
\83^
\81[
\82Ì";
1774 boolean donefirst = FALSE;
1776 if (!suppliedbuf || buflen < 1)
1779 /* initialize these static variables each time this is called */
1781 for (k = 0; k < NUM_BP; ++k)
1784 *suppliedbuf = '\0';
1786 /* How many alignments are allowed for the desired race? */
1787 if (racenum != ROLE_NONE && racenum != ROLE_RANDOM)
1788 aligncount = race_alignmentcount(racenum);
1790 if (alignnum != ROLE_NONE && alignnum != ROLE_RANDOM
1791 && ok_align(rolenum, racenum, gendnum, alignnum)) {
1792 /* if race specified, and multiple choice of alignments for it */
1793 if ((racenum >= 0) && (aligncount > 1)) {
1798 Strcat(buf, aligns[alignnum].adj);
1805 Strcat(buf, aligns[alignnum].adj);
1809 /* in case we got here by failing the ok_align() test */
1810 if (alignnum != ROLE_RANDOM)
1811 alignnum = ROLE_NONE;
1812 /* if alignment not specified, but race is specified
1813 and only one choice of alignment for that race then
1814 don't include it in the later list */
1815 if ((((racenum != ROLE_NONE && racenum != ROLE_RANDOM)
1816 && ok_race(rolenum, racenum, gendnum, alignnum))
1817 && (aligncount > 1))
1818 || (racenum == ROLE_NONE || racenum == ROLE_RANDOM)) {
1825 /* How many genders are allowed for the desired role? */
1826 if (validrole(rolenum))
1827 gendercount = role_gendercount(rolenum);
1829 if (gendnum != ROLE_NONE && gendnum != ROLE_RANDOM) {
1830 if (validrole(rolenum)) {
1831 /* if role specified, and multiple choice of genders for it,
1832 and name of role itself does not distinguish gender */
1833 if ((rolenum != ROLE_NONE) && (gendercount > 1)
1834 && !roles[rolenum].name.f) {
1839 Strcat(buf, genders[gendnum].adj);
1847 Strcat(buf, genders[gendnum].adj);
1851 /* if gender not specified, but role is specified
1852 and only one choice of gender then
1853 don't include it in the later list */
1854 if ((validrole(rolenum) && (gendercount > 1))
1855 || !validrole(rolenum)) {
1860 /* <your lawful female> */
1862 if (racenum != ROLE_NONE && racenum != ROLE_RANDOM) {
1863 if (validrole(rolenum)
1864 && ok_race(rolenum, racenum, gendnum, alignnum)) {
1869 Strcat(buf, (rolenum == ROLE_NONE) ? races[racenum].noun
1870 : races[racenum].adj);
1872 } else if (!validrole(rolenum)) {
1877 Strcat(buf, races[racenum].noun);
1887 /* <your lawful female gnomish> || <your lawful female gnome> */
1889 if (validrole(rolenum)) {
1894 if (gendnum != ROLE_NONE) {
1895 if (gendnum == 1 && roles[rolenum].name.f)
1896 Strcat(buf, roles[rolenum].name.f);
1898 Strcat(buf, roles[rolenum].name.m);
1900 if (roles[rolenum].name.f) {
1901 Strcat(buf, roles[rolenum].name.m);
1903 Strcat(buf, roles[rolenum].name.f);
1905 Strcat(buf, roles[rolenum].name.m);
1908 } else if (rolenum == ROLE_NONE) {
1913 if ((racenum == ROLE_NONE || racenum == ROLE_RANDOM)
1914 && !validrole(rolenum)) {
1920 Strcat(buf, "character");
1922 Strcat(buf, "
\83L
\83\83\83\89\83N
\83^
\81[");
1925 /* <your lawful female gnomish cavewoman> || <your lawful female gnome>
1926 * || <your lawful female character>
1928 if (buflen > (int) (strlen(buf) + 1)) {
1929 Strcpy(suppliedbuf, buf);
1936 build_plselection_prompt(buf, buflen, rolenum, racenum, gendnum, alignnum)
1938 int buflen, rolenum, racenum, gendnum, alignnum;
1941 const char *defprompt = "Shall I pick a character for you? [ynaq] ";
1943 const char *defprompt = "
\93K
\93\96\82É
\83L
\83\83\83\89\83N
\83^
\81[
\82ð
\91I
\82ñ
\82Å
\82æ
\82¢
\82Å
\82·
\82©
\81H[ynaq] ";
1944 int num_post_attribs = 0;
1945 char tmpbuf[BUFSZ], *p;
1947 if (buflen < QBUFSZ)
1948 return (char *) defprompt;
1951 Strcpy(tmpbuf, "Shall I pick ");
1952 if (racenum != ROLE_NONE || validrole(rolenum))
1953 Strcat(tmpbuf, "your ");
1955 Strcat(tmpbuf, "a ");
1962 (void) root_plselection_prompt(eos(tmpbuf), buflen - strlen(tmpbuf),
1963 rolenum, racenum, gendnum, alignnum);
1965 Sprintf(buf, "%s", s_suffix(tmpbuf));
1967 Sprintf(buf, "%s
\82Ì", tmpbuf);
1969 #if 0 /*JP:
\93ú
\96{
\8cê
\82Å
\82Í
\95s
\97v*/
1970 /* don't bother splitting caveman/cavewoman or priest/priestess
1971 in order to apply possessive suffix to both halves, but do
1972 change "priest/priestess'" to "priest/priestess's" */
1973 if ((p = strstri(buf, "priest/priestess'")) != 0
1974 && p[sizeof "priest/priestess'" - sizeof ""] == '\0')
1975 strkitten(buf, 's');
1978 /* buf should now be:
1979 * <your lawful female gnomish cavewoman's>
1980 * || <your lawful female gnome's>
1981 * || <your lawful female character's>
1983 * Now append the post attributes to it
1985 num_post_attribs = post_attribs;
1988 (void) promptsep(eos(buf), num_post_attribs);
1990 Strcat(buf, "race");
1992 Strcat(buf, "
\8eí
\91°");
1995 (void) promptsep(eos(buf), num_post_attribs);
1997 Strcat(buf, "role");
1999 Strcat(buf, "
\90E
\8bÆ");
2002 (void) promptsep(eos(buf), num_post_attribs);
2004 Strcat(buf, "gender");
2006 Strcat(buf, "
\90«
\95Ê");
2009 (void) promptsep(eos(buf), num_post_attribs);
2011 Strcat(buf, "alignment");
2013 Strcat(buf, "
\91®
\90«");
2017 Strcat(buf, " for you? [ynaq] ");
2019 Strcat(buf, "
\82ð
\93K
\93\96\82É
\91I
\82ñ
\82Å
\82æ
\82ë
\82µ
\82¢
\82Å
\82·
\82©
\81H[ynq] ");
2035 #ifdef GENERIC_USERNAMES
2037 /* some generic user names will be ignored in favor of prompting */
2038 const char *uptr = GENERIC_USERNAMES;
2040 i = (int) strlen(plname);
2041 if ((sptr = strstri(uptr, plname)) != 0
2042 && (sptr == uptr || sptr[-1] == ' ')
2043 && (sptr[i] == ' ' || sptr[i] == '\0'))
2044 *plname = '\0'; /* call askname() */
2050 askname(); /* fill plname[] if necessary */
2052 /* Look for tokens delimited by '-' */
2053 if ((eptr = index(plname, '-')) != (char *) 0)
2056 /* Isolate the next token */
2058 if ((eptr = index(sptr, '-')) != (char *) 0)
2061 /* Try to match it to something */
2062 if ((i = str2role(sptr)) != ROLE_NONE)
2064 else if ((i = str2race(sptr)) != ROLE_NONE)
2066 else if ((i = str2gend(sptr)) != ROLE_NONE)
2068 else if ((i = str2align(sptr)) != ROLE_NONE)
2069 flags.initalign = i;
2073 /* commas in the plname confuse the record file, convert to spaces */
2074 for (sptr = plname; *sptr; sptr++) {
2080 /* show current settings for name, role, race, gender, and alignment
2081 in the specified window */
2083 role_selection_prolog(which, where)
2088 static const char NEARDATA choosing[] = " choosing now",
2090 static const char NEARDATA choosing[] = "
\8c»
\8dÝ
\91I
\91ð
\92\86",
2092 not_yet[] = " not yet specified",
2094 not_yet[] = "
\96¢
\91I
\91ð",
2096 rand_choice[] = " random";
2098 rand_choice[] = "
\83\89\83\93\83_
\83\80";
2100 int r, c, g, a, allowmask;
2105 a = flags.initalign;
2107 allowmask = roles[r].allow;
2108 if ((allowmask & ROLE_RACEMASK) == MH_HUMAN)
2109 c = 0; /* races[human] */
2110 else if (c >= 0 && !(allowmask & ROLE_RACEMASK & races[c].allow))
2112 if ((allowmask & ROLE_GENDMASK) == ROLE_MALE)
2113 g = 0; /* role forces male (hypothetical) */
2114 else if ((allowmask & ROLE_GENDMASK) == ROLE_FEMALE)
2115 g = 1; /* role forces female (valkyrie) */
2116 if ((allowmask & ROLE_ALIGNMASK) == AM_LAWFUL)
2117 a = 0; /* aligns[lawful] */
2118 else if ((allowmask & ROLE_ALIGNMASK) == AM_NEUTRAL)
2119 a = 1; /* aligns[neutral] */
2120 else if ((allowmask & ROLE_ALIGNMASK) == AM_CHAOTIC)
2121 a = 2; /* alings[chaotic] */
2124 allowmask = races[c].allow;
2125 if ((allowmask & ROLE_ALIGNMASK) == AM_LAWFUL)
2126 a = 0; /* aligns[lawful] */
2127 else if ((allowmask & ROLE_ALIGNMASK) == AM_NEUTRAL)
2128 a = 1; /* aligns[neutral] */
2129 else if ((allowmask & ROLE_ALIGNMASK) == AM_CHAOTIC)
2130 a = 2; /* alings[chaotic] */
2131 /* [c never forces gender] */
2133 /* [g and a don't constrain anything sufficiently
2134 to narrow something done to a single choice] */
2136 Sprintf(buf, "%12s ", "name:");
2137 Strcat(buf, (which == RS_NAME) ? choosing : !*plname ? not_yet : plname);
2138 putstr(where, 0, buf);
2139 Sprintf(buf, "%12s ", "role:");
2140 Strcat(buf, (which == RS_ROLE) ? choosing : (r == ROLE_NONE)
2142 : (r == ROLE_RANDOM)
2145 if (r >= 0 && roles[r].name.f) {
2146 /* distinct female name [caveman/cavewoman, priest/priestess] */
2148 /* female specified; replace male role name with female one */
2149 Sprintf(index(buf, ':'), ": %s", roles[r].name.f);
2151 /* gender unspecified; append slash and female role name */
2152 Sprintf(eos(buf), "/%s", roles[r].name.f);
2154 putstr(where, 0, buf);
2156 Sprintf(buf, "%12s ", "race:");
2158 Sprintf(buf, "%12s ", "
\8eí
\91°:");
2159 Strcat(buf, (which == RS_RACE) ? choosing : (c == ROLE_NONE)
2161 : (c == ROLE_RANDOM)
2164 putstr(where, 0, buf);
2166 Sprintf(buf, "%12s ", "gender:");
2168 Sprintf(buf, "%12s ", "
\90«
\95Ê:");
2169 Strcat(buf, (which == RS_GENDER) ? choosing : (g == ROLE_NONE)
2171 : (g == ROLE_RANDOM)
2174 putstr(where, 0, buf);
2176 Sprintf(buf, "%12s ", "alignment:");
2178 Sprintf(buf, "%12s ", "
\91®
\90«:");
2179 Strcat(buf, (which == RS_ALGNMNT) ? choosing : (a == ROLE_NONE)
2181 : (a == ROLE_RANDOM)
2183 #if 0 /*JP:
\93ú
\96{
\8cê
\82Å
\82Í
\96¼
\8e\8c\82ª
\8e©
\91R*/
2188 putstr(where, 0, buf);
2191 /* add a "pick alignment first"-type entry to the specified menu */
2193 role_menu_extra(which, where)
2197 static NEARDATA const char RS_menu_let[] = {
2202 '[', /* alignment */
2206 const char *what = 0, *constrainer = 0, *forcedvalue = 0;
2207 int f = 0, r, c, g, a, i, allowmask;
2218 for (i = 0; i < SIZE(roles); ++i)
2219 if (i != f && !filter.roles[i])
2221 if (i == SIZE(roles)) {
2222 constrainer = "filter";
2223 forcedvalue = "role";
2229 c = ROLE_NONE; /* override player's setting */
2231 allowmask = roles[r].allow & ROLE_RACEMASK;
2232 if (allowmask == MH_HUMAN)
2233 c = 0; /* races[human] */
2235 constrainer = "role";
2236 forcedvalue = races[c].noun;
2238 && (allowmask & ~filter.mask) == races[f].selfmask) {
2239 /* if there is only one race choice available due to user
2240 options disallowing others, race menu entry is disabled */
2241 constrainer = "filter";
2242 forcedvalue = "race";
2251 allowmask = roles[r].allow & ROLE_GENDMASK;
2252 if (allowmask == ROLE_MALE)
2253 g = 0; /* genders[male] */
2254 else if (allowmask == ROLE_FEMALE)
2255 g = 1; /* genders[female] */
2257 constrainer = "role";
2258 forcedvalue = genders[g].adj;
2260 && (allowmask & ~filter.mask) == genders[f].allow) {
2261 /* if there is only one gender choice available due to user
2262 options disallowing other, gender menu entry is disabled */
2263 constrainer = "filter";
2264 forcedvalue = "gender";
2270 f = flags.initalign;
2273 allowmask = roles[r].allow & ROLE_ALIGNMASK;
2274 if (allowmask == AM_LAWFUL)
2275 a = 0; /* aligns[lawful] */
2276 else if (allowmask == AM_NEUTRAL)
2277 a = 1; /* aligns[neutral] */
2278 else if (allowmask == AM_CHAOTIC)
2279 a = 2; /* aligns[chaotic] */
2281 constrainer = "role";
2283 if (c >= 0 && !constrainer) {
2284 allowmask = races[c].allow & ROLE_ALIGNMASK;
2285 if (allowmask == AM_LAWFUL)
2286 a = 0; /* aligns[lawful] */
2287 else if (allowmask == AM_NEUTRAL)
2288 a = 1; /* aligns[neutral] */
2289 else if (allowmask == AM_CHAOTIC)
2290 a = 2; /* aligns[chaotic] */
2292 constrainer = "race";
2294 if (f >= 0 && !constrainer
2295 && (ROLE_ALIGNMASK & ~filter.mask) == aligns[f].allow) {
2296 /* if there is only one alignment choice available due to user
2297 options disallowing others, algn menu entry is disabled */
2298 constrainer = "filter";
2299 forcedvalue = "alignment";
2302 forcedvalue = aligns[a].adj;
2306 any = zeroany; /* zero out all bits */
2309 /* use four spaces of padding to fake a grayed out menu choice */
2310 Sprintf(buf, "%4s%s forces %s", "", constrainer, forcedvalue);
2311 add_menu(where, NO_GLYPH, &any, ' ', 0, ATR_NONE, buf,
2314 any.a_int = RS_menu_arg(which);
2315 Sprintf(buf, "Pick%s %s first", (f >= 0) ? " another" : "", what);
2316 add_menu(where, NO_GLYPH, &any, RS_menu_let[which], 0, ATR_NONE, buf,
2318 } else if (which == RS_filter) {
2319 any.a_int = RS_menu_arg(RS_filter);
2320 add_menu(where, NO_GLYPH, &any, '~', 0, ATR_NONE,
2321 "Reset role/race/&c filtering", MENU_UNSELECTED);
2322 } else if (which == ROLE_RANDOM) {
2323 any.a_int = ROLE_RANDOM;
2324 add_menu(where, NO_GLYPH, &any, '*', 0, ATR_NONE, "Random",
2326 } else if (which == ROLE_NONE) {
2327 any.a_int = ROLE_NONE;
2328 add_menu(where, NO_GLYPH, &any, 'q', 0, ATR_NONE, "Quit",
2331 impossible("role_menu_extra: bad arg (%d)", which);
2336 * Special setup modifications here:
2338 * Unfortunately, this is going to have to be done
2339 * on each newgame or restore, because you lose the permonst mods
2340 * across a save/restore. :-)
2342 * 1 - The Rogue Leader is the Tourist Nemesis.
2343 * 2 - Priests start with a random alignment - convert the leader and
2345 * 3 - Priests also get their of deities from a randomly chosen role.
2346 * 4 - [obsolete] Elves can have one of two different leaders,
2347 * but can't work it out here because it requires hacking the
2348 * level file data (see sp_lev.c).
2350 * This code also replaces quest_init().
2356 struct permonst *pm;
2358 /* Strip the role letter out of the player name.
2359 * This is included for backwards compatibility.
2363 /* Check for a valid role. Try flags.initrole first. */
2364 if (!validrole(flags.initrole)) {
2365 /* Try the player letter second */
2366 if ((flags.initrole = str2role(pl_character)) < 0)
2367 /* None specified; pick a random role */
2368 flags.initrole = randrole_filtered();
2371 /* We now have a valid role index. Copy the role name back. */
2372 /* This should become OBSOLETE */
2373 Strcpy(pl_character, roles[flags.initrole].name.m);
2374 pl_character[PL_CSIZ - 1] = '\0';
2376 /* Check for a valid race */
2377 if (!validrace(flags.initrole, flags.initrace))
2378 flags.initrace = randrace(flags.initrole);
2380 /* Check for a valid gender. If new game, check both initgend
2381 * and female. On restore, assume flags.female is correct. */
2382 if (flags.pantheon == -1) { /* new game */
2383 if (!validgend(flags.initrole, flags.initrace, flags.female))
2384 flags.female = !flags.female;
2386 if (!validgend(flags.initrole, flags.initrace, flags.initgend))
2387 /* Note that there is no way to check for an unspecified gender. */
2388 flags.initgend = flags.female;
2390 /* Check for a valid alignment */
2391 if (!validalign(flags.initrole, flags.initrace, flags.initalign))
2392 /* Pick a random alignment */
2393 flags.initalign = randalign(flags.initrole, flags.initrace);
2394 alignmnt = aligns[flags.initalign].value;
2396 /* Initialize urole and urace */
2397 urole = roles[flags.initrole];
2398 urace = races[flags.initrace];
2400 /* Fix up the quest leader */
2401 if (urole.ldrnum != NON_PM) {
2402 pm = &mons[urole.ldrnum];
2403 pm->msound = MS_LEADER;
2404 pm->mflags2 |= (M2_PEACEFUL);
2405 pm->mflags3 |= M3_CLOSE;
2406 pm->maligntyp = alignmnt * 3;
2407 /* if gender is random, we choose it now instead of waiting
2408 until the leader monster is created */
2409 quest_status.ldrgend =
2410 is_neuter(pm) ? 2 : is_female(pm) ? 1 : is_male(pm)
2415 /* Fix up the quest guardians */
2416 if (urole.guardnum != NON_PM) {
2417 pm = &mons[urole.guardnum];
2418 pm->mflags2 |= (M2_PEACEFUL);
2419 pm->maligntyp = alignmnt * 3;
2422 /* Fix up the quest nemesis */
2423 if (urole.neminum != NON_PM) {
2424 pm = &mons[urole.neminum];
2425 pm->msound = MS_NEMESIS;
2426 pm->mflags2 &= ~(M2_PEACEFUL);
2427 pm->mflags2 |= (M2_NASTY | M2_STALK | M2_HOSTILE);
2428 pm->mflags3 &= ~(M3_CLOSE);
2429 pm->mflags3 |= M3_WANTSARTI | M3_WAITFORU;
2430 /* if gender is random, we choose it now instead of waiting
2431 until the nemesis monster is created */
2432 quest_status.nemgend = is_neuter(pm) ? 2 : is_female(pm) ? 1
2433 : is_male(pm) ? 0 : (rn2(100) < 50);
2436 /* Fix up the god names */
2437 if (flags.pantheon == -1) { /* new game */
2438 flags.pantheon = flags.initrole; /* use own gods */
2439 while (!roles[flags.pantheon].lgod) /* unless they're missing */
2440 flags.pantheon = randrole();
2443 urole.lgod = roles[flags.pantheon].lgod;
2444 urole.ngod = roles[flags.pantheon].ngod;
2445 urole.cgod = roles[flags.pantheon].cgod;
2447 /* 0 or 1; no gods are neuter, nor is gender randomized */
2448 quest_status.godgend = !strcmpi(align_gtitle(alignmnt), "goddess");
2450 /* Fix up infravision */
2451 if (mons[urace.malenum].mflags3 & M3_INFRAVISION) {
2452 /* although an infravision intrinsic is possible, infravision
2453 * is purely a property of the physical race. This means that we
2454 * must put the infravision flag in the player's current race
2455 * (either that or have separate permonst entries for
2456 * elven/non-elven members of each class). The side effect is that
2457 * all NPCs of that class will have (probably bogus) infravision,
2458 * but since infravision has no effect for NPCs anyway we can
2461 mons[urole.malenum].mflags3 |= M3_INFRAVISION;
2462 if (urole.femalenum != NON_PM)
2463 mons[urole.femalenum].mflags3 |= M3_INFRAVISION;
2466 /* Artifacts are fixed in hack_artifacts() */
2477 switch (Role_switch) {
2479 return "Salutations"; /* Olde English */
2481 return (mtmp && mtmp->data == &mons[PM_SHOPKEEPER])
2483 : "Konnichi wa"; /* Japanese */
2485 return "Aloha"; /* Hawaiian */
2489 (mtmp && mtmp->data == &mons[PM_MAIL_DAEMON]) ? "Hallo" :
2491 "Velkommen"; /* Norse */
2497 \82 \82¢
\82³
\82Â
\82Í
\93ú
\96{
\8cê
\82Æ
\82µ
\82Ä
\8e©
\91R
\82É
\82È
\82é
\82æ
\82¤
\91å
\82«
\82
\8ed
\97l
\82ð
\95Ï
\8dX
2499 static char helo_buf[BUFSZ];
2501 switch (Role_switch) {
2503 Sprintf(helo_buf, "
\82æ
\82
\82¼
\8eQ
\82Á
\82½%s
\82æ", plname);
2506 Sprintf(helo_buf, "
\82æ
\82
\82¼
\8eQ
\82ç
\82ê
\82½%s
\82æ", plname);
2509 Sprintf(helo_buf, "
\83A
\83\8d\81[
\83n%s", plname);
2512 Sprintf(helo_buf, "
\8d°
\82Ì
\8eç
\8cì
\8eÒ%s
\82æ", plname);
2515 Sprintf(helo_buf, "
\82æ
\82¤
\82±
\82»%s", plname);
2527 switch (Role_switch) {
2529 return "Fare thee well"; /* Olde English */
2531 return "Sayonara"; /* Japanese */
2533 return "Aloha"; /* Hawaiian */
2535 return "Farvel"; /* Norse */
2540 static char helo_buf[BUFSZ];
2542 switch (Role_switch) {
2544 Sprintf(helo_buf, "
\82³
\82ç
\82Î
\8chåi
\82È
\82é");
2547 Sprintf(helo_buf, "
\82³
\82ç
\82Î
\95\90\8em
\93¹
\82ð
\8eu
\82·");
2550 Sprintf(helo_buf, "
\83A
\83\8d\81[
\83n");
2553 Sprintf(helo_buf, "
\82³
\82ç
\82Î
\8d°
\82Ì
\8eç
\8cì
\8eÒ");
2556 Sprintf(helo_buf, "
\82³
\82æ
\82¤
\82È
\82ç");