Source:NetHack 3.6.0/src/role.c

From NetHackWiki
(Redirected from Source:NetHack 3.6.0/role.c)
Jump to: navigation, search

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

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.

Top of file

  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. */
  4.  
  5.  #include "hack.h"
  6.  

Roles

  1.  /*** Table of all roles ***/
  2.  /* According to AD&D, HD for some classes (ex. Wizard) should be smaller
  3.   * (4-sided for wizards).  But this is not AD&D, and using the AD&D
  4.   * rule here produces an unplayable character.  Thus I have used a minimum
  5.   * of an 10-sided hit die for everything.  Another AD&D change: wizards get
  6.   * a minimum strength of 4 since without one you can't teleport or cast
  7.   * spells. --KAA
  8.   *
  9.   * As the wizard has been updated (wizard patch 5 jun '96) their HD can be
  10.   * brought closer into line with AD&D. This forces wizards to use magic more
  11.   * and distance themselves from their attackers. --LSZ
  12.   *
  13.   * With the introduction of races, some hit points and energy
  14.   * has been reallocated for each race.  The values assigned
  15.   * to the roles has been reduced by the amount allocated to
  16.   * humans.  --KMH
  17.   *
  18.   * God names use a leading underscore to flag goddesses.
  19.   */
  20.  const struct Role roles[] = {

Archeologist

  1.      { { "Archeologist", 0 },
  2.        { { "Digger", 0 },
  3.          { "Field Worker", 0 },
  4.          { "Investigator", 0 },
  5.          { "Exhumer", 0 },
  6.          { "Excavator", 0 },
  7.          { "Spelunker", 0 },
  8.          { "Speleologist", 0 },
  9.          { "Collector", 0 },
  10.          { "Curator", 0 } },
  11.        "Quetzalcoatl", "Camaxtli", "Huhetotl", /* Central American */
  12.        "Arc",
  13.        "the College of Archeology",
  14.        "the Tomb of the Toltec Kings",
  15.        PM_ARCHEOLOGIST,
  16.        NON_PM,
  17.        NON_PM,
  18.        PM_LORD_CARNARVON,
  19.        PM_STUDENT,
  20.        PM_MINION_OF_HUHETOTL,
  21.        NON_PM,
  22.        PM_HUMAN_MUMMY,
  23.        S_SNAKE,
  24.        S_MUMMY,
  25.        ART_ORB_OF_DETECTION,
  26.        MH_HUMAN | MH_DWARF | MH_GNOME | ROLE_MALE | ROLE_FEMALE | ROLE_LAWFUL
  27.            | ROLE_NEUTRAL,
  28.        /* Str Int Wis Dex Con Cha */
  29.        { 7, 10, 10, 7, 7, 7 },
  30.        { 20, 20, 20, 10, 20, 10 },
  31.        /* Init   Lower  Higher */
  32.        { 11, 0, 0, 8, 1, 0 }, /* Hit points */
  33.        { 1, 0, 0, 1, 0, 1 },
  34.        14, /* Energy */
  35.        10,
  36.        5,
  37.        0,
  38.        2,
  39.        10,
  40.        A_INT,
  41.        SPE_MAGIC_MAPPING,
  42.        -4 },

Barbarian

  1.      { { "Barbarian", 0 },
  2.        { { "Plunderer", "Plunderess" },
  3.          { "Pillager", 0 },
  4.          { "Bandit", 0 },
  5.          { "Brigand", 0 },
  6.          { "Raider", 0 },
  7.          { "Reaver", 0 },
  8.          { "Slayer", 0 },
  9.          { "Chieftain", "Chieftainess" },
  10.          { "Conqueror", "Conqueress" } },
  11.        "Mitra", "Crom", "Set", /* Hyborian */
  12.        "Bar",
  13.        "the Camp of the Duali Tribe",
  14.        "the Duali Oasis",
  15.        PM_BARBARIAN,
  16.        NON_PM,
  17.        NON_PM,
  18.        PM_PELIAS,
  19.        PM_CHIEFTAIN,
  20.        PM_THOTH_AMON,
  21.        PM_OGRE,
  22.        PM_TROLL,
  23.        S_OGRE,
  24.        S_TROLL,
  25.        ART_HEART_OF_AHRIMAN,
  26.        MH_HUMAN | MH_ORC | ROLE_MALE | ROLE_FEMALE | ROLE_NEUTRAL
  27.            | ROLE_CHAOTIC,
  28.        /* Str Int Wis Dex Con Cha */
  29.        { 16, 7, 7, 15, 16, 6 },
  30.        { 30, 6, 7, 20, 30, 7 },
  31.        /* Init   Lower  Higher */
  32.        { 14, 0, 0, 10, 2, 0 }, /* Hit points */
  33.        { 1, 0, 0, 1, 0, 1 },
  34.        10, /* Energy */
  35.        10,
  36.        14,
  37.        0,
  38.        0,
  39.        8,
  40.        A_INT,
  41.        SPE_HASTE_SELF,
  42.        -4 },

Caveman

  1.      { { "Caveman", "Cavewoman" },
  2.        { { "Troglodyte", 0 },
  3.          { "Aborigine", 0 },
  4.          { "Wanderer", 0 },
  5.          { "Vagrant", 0 },
  6.          { "Wayfarer", 0 },
  7.          { "Roamer", 0 },
  8.          { "Nomad", 0 },
  9.          { "Rover", 0 },
  10.          { "Pioneer", 0 } },
  11.        "Anu", "_Ishtar", "Anshar", /* Babylonian */
  12.        "Cav",
  13.        "the Caves of the Ancestors",
  14.        "the Dragon's Lair",
  15.        PM_CAVEMAN,
  16.        PM_CAVEWOMAN,
  17.        PM_LITTLE_DOG,
  18.        PM_SHAMAN_KARNOV,
  19.        PM_NEANDERTHAL,
  20.        PM_CHROMATIC_DRAGON,
  21.        PM_BUGBEAR,
  22.        PM_HILL_GIANT,
  23.        S_HUMANOID,
  24.        S_GIANT,
  25.        ART_SCEPTRE_OF_MIGHT,
  26.        MH_HUMAN | MH_DWARF | MH_GNOME | ROLE_MALE | ROLE_FEMALE | ROLE_LAWFUL
  27.            | ROLE_NEUTRAL,
  28.        /* Str Int Wis Dex Con Cha */
  29.        { 10, 7, 7, 7, 8, 6 },
  30.        { 30, 6, 7, 20, 30, 7 },
  31.        /* Init   Lower  Higher */
  32.        { 14, 0, 0, 8, 2, 0 }, /* Hit points */
  33.        { 1, 0, 0, 1, 0, 1 },
  34.        10, /* Energy */
  35.        0,
  36.        12,
  37.        0,
  38.        1,
  39.        8,
  40.        A_INT,
  41.        SPE_DIG,
  42.        -4 },

Healer

  1.      { { "Healer", 0 },
  2.        { { "Rhizotomist", 0 },
  3.          { "Empiric", 0 },
  4.          { "Embalmer", 0 },
  5.          { "Dresser", 0 },
  6.          { "Medicus ossium", "Medica ossium" },
  7.          { "Herbalist", 0 },
  8.          { "Magister", "Magistra" },
  9.          { "Physician", 0 },
  10.          { "Chirurgeon", 0 } },
  11.        "_Athena", "Hermes", "Poseidon", /* Greek */
  12.        "Hea",
  13.        "the Temple of Epidaurus",
  14.        "the Temple of Coeus",
  15.        PM_HEALER,
  16.        NON_PM,
  17.        NON_PM,
  18.        PM_HIPPOCRATES,
  19.        PM_ATTENDANT,
  20.        PM_CYCLOPS,
  21.        PM_GIANT_RAT,
  22.        PM_SNAKE,
  23.        S_RODENT,
  24.        S_YETI,
  25.        ART_STAFF_OF_AESCULAPIUS,
  26.        MH_HUMAN | MH_GNOME | ROLE_MALE | ROLE_FEMALE | ROLE_NEUTRAL,
  27.        /* Str Int Wis Dex Con Cha */
  28.        { 7, 7, 13, 7, 11, 16 },
  29.        { 15, 20, 20, 15, 25, 5 },
  30.        /* Init   Lower  Higher */
  31.        { 11, 0, 0, 8, 1, 0 }, /* Hit points */
  32.        { 1, 4, 0, 1, 0, 2 },
  33.        20, /* Energy */
  34.        10,
  35.        3,
  36.        -3,
  37.        2,
  38.        10,
  39.        A_WIS,
  40.        SPE_CURE_SICKNESS,
  41.        -4 },

Knight

  1.      { { "Knight", 0 },
  2.        { { "Gallant", 0 },
  3.          { "Esquire", 0 },
  4.          { "Bachelor", 0 },
  5.          { "Sergeant", 0 },
  6.          { "Knight", 0 },
  7.          { "Banneret", 0 },
  8.          { "Chevalier", "Chevaliere" },
  9.          { "Seignieur", "Dame" },
  10.          { "Paladin", 0 } },
  11.        "Lugh", "_Brigit", "Manannan Mac Lir", /* Celtic */
  12.        "Kni",
  13.        "Camelot Castle",
  14.        "the Isle of Glass",
  15.        PM_KNIGHT,
  16.        NON_PM,
  17.        PM_PONY,
  18.        PM_KING_ARTHUR,
  19.        PM_PAGE,
  20.        PM_IXOTH,
  21.        PM_QUASIT,
  22.        PM_OCHRE_JELLY,
  23.        S_IMP,
  24.        S_JELLY,
  25.        ART_MAGIC_MIRROR_OF_MERLIN,
  26.        MH_HUMAN | ROLE_MALE | ROLE_FEMALE | ROLE_LAWFUL,
  27.        /* Str Int Wis Dex Con Cha */
  28.        { 13, 7, 14, 8, 10, 17 },
  29.        { 30, 15, 15, 10, 20, 10 },
  30.        /* Init   Lower  Higher */
  31.        { 14, 0, 0, 8, 2, 0 }, /* Hit points */
  32.        { 1, 4, 0, 1, 0, 2 },
  33.        10, /* Energy */
  34.        10,
  35.        8,
  36.        -2,
  37.        0,
  38.        9,
  39.        A_WIS,
  40.        SPE_TURN_UNDEAD,
  41.        -4 },

Monk

  1.      { { "Monk", 0 },
  2.        { { "Candidate", 0 },
  3.          { "Novice", 0 },
  4.          { "Initiate", 0 },
  5.          { "Student of Stones", 0 },
  6.          { "Student of Waters", 0 },
  7.          { "Student of Metals", 0 },
  8.          { "Student of Winds", 0 },
  9.          { "Student of Fire", 0 },
  10.          { "Master", 0 } },
  11.        "Shan Lai Ching", "Chih Sung-tzu", "Huan Ti", /* Chinese */
  12.        "Mon",
  13.        "the Monastery of Chan-Sune",
  14.        "the Monastery of the Earth-Lord",
  15.        PM_MONK,
  16.        NON_PM,
  17.        NON_PM,
  18.        PM_GRAND_MASTER,
  19.        PM_ABBOT,
  20.        PM_MASTER_KAEN,
  21.        PM_EARTH_ELEMENTAL,
  22.        PM_XORN,
  23.        S_ELEMENTAL,
  24.        S_XORN,
  25.        ART_EYES_OF_THE_OVERWORLD,
  26.        MH_HUMAN | ROLE_MALE | ROLE_FEMALE | ROLE_LAWFUL | ROLE_NEUTRAL
  27.            | ROLE_CHAOTIC,
  28.        /* Str Int Wis Dex Con Cha */
  29.        { 10, 7, 8, 8, 7, 7 },
  30.        { 25, 10, 20, 20, 15, 10 },
  31.        /* Init   Lower  Higher */
  32.        { 12, 0, 0, 8, 1, 0 }, /* Hit points */
  33.        { 2, 2, 0, 2, 0, 2 },
  34.        10, /* Energy */
  35.        10,
  36.        8,
  37.        -2,
  38.        2,
  39.        20,
  40.        A_WIS,
  41.        SPE_RESTORE_ABILITY,
  42.        -4 },

Priest

  1.      { { "Priest", "Priestess" },
  2.        { { "Aspirant", 0 },
  3.          { "Acolyte", 0 },
  4.          { "Adept", 0 },
  5.          { "Priest", "Priestess" },
  6.          { "Curate", 0 },
  7.          { "Canon", "Canoness" },
  8.          { "Lama", 0 },
  9.          { "Patriarch", "Matriarch" },
  10.          { "High Priest", "High Priestess" } },
  11.        0, 0, 0, /* deities from a randomly chosen other role will be used */
  12.        "Pri",
  13.        "the Great Temple",
  14.        "the Temple of Nalzok",
  15.        PM_PRIEST,
  16.        PM_PRIESTESS,
  17.        NON_PM,
  18.        PM_ARCH_PRIEST,
  19.        PM_ACOLYTE,
  20.        PM_NALZOK,
  21.        PM_HUMAN_ZOMBIE,
  22.        PM_WRAITH,
  23.        S_ZOMBIE,
  24.        S_WRAITH,
  25.        ART_MITRE_OF_HOLINESS,
  26.        MH_HUMAN | MH_ELF | ROLE_MALE | ROLE_FEMALE | ROLE_LAWFUL | ROLE_NEUTRAL
  27.            | ROLE_CHAOTIC,
  28.        /* Str Int Wis Dex Con Cha */
  29.        { 7, 7, 10, 7, 7, 7 },
  30.        { 15, 10, 30, 15, 20, 10 },
  31.        /* Init   Lower  Higher */
  32.        { 12, 0, 0, 8, 1, 0 }, /* Hit points */
  33.        { 4, 3, 0, 2, 0, 2 },
  34.        10, /* Energy */
  35.        0,
  36.        3,
  37.        -2,
  38.        2,
  39.        10,
  40.        A_WIS,
  41.        SPE_REMOVE_CURSE,
  42.        -4 },

Rogue

  1.      /* Note:  Rogue precedes Ranger so that use of `-R' on the command line
  2.         retains its traditional meaning. */
  3.      { { "Rogue", 0 },
  4.        { { "Footpad", 0 },
  5.          { "Cutpurse", 0 },
  6.          { "Rogue", 0 },
  7.          { "Pilferer", 0 },
  8.          { "Robber", 0 },
  9.          { "Burglar", 0 },
  10.          { "Filcher", 0 },
  11.          { "Magsman", "Magswoman" },
  12.          { "Thief", 0 } },
  13.        "Issek", "Mog", "Kos", /* Nehwon */
  14.        "Rog",
  15.        "the Thieves' Guild Hall",
  16.        "the Assassins' Guild Hall",
  17.        PM_ROGUE,
  18.        NON_PM,
  19.        NON_PM,
  20.        PM_MASTER_OF_THIEVES,
  21.        PM_THUG,
  22.        PM_MASTER_ASSASSIN,
  23.        PM_LEPRECHAUN,
  24.        PM_GUARDIAN_NAGA,
  25.        S_NYMPH,
  26.        S_NAGA,
  27.        ART_MASTER_KEY_OF_THIEVERY,
  28.        MH_HUMAN | MH_ORC | ROLE_MALE | ROLE_FEMALE | ROLE_CHAOTIC,
  29.        /* Str Int Wis Dex Con Cha */
  30.        { 7, 7, 7, 10, 7, 6 },
  31.        { 20, 10, 10, 30, 20, 10 },
  32.        /* Init   Lower  Higher */
  33.        { 10, 0, 0, 8, 1, 0 }, /* Hit points */
  34.        { 1, 0, 0, 1, 0, 1 },
  35.        11, /* Energy */
  36.        10,
  37.        8,
  38.        0,
  39.        1,
  40.        9,
  41.        A_INT,
  42.        SPE_DETECT_TREASURE,
  43.        -4 },

Ranger

  1.      { { "Ranger", 0 },
  2.        {
  3.  #if 0 /* OBSOLETE */
  4.          {"Edhel",   "Elleth"},
  5.          {"Edhel",   "Elleth"},         /* elf-maid */
  6.          {"Ohtar",   "Ohtie"},          /* warrior */
  7.          {"Kano",    "Kanie"},          /* commander (Q.) ['a] educated guess,
  8.                                            until further research- SAC */
  9.          {"Arandur"," Aranduriel"}, /* king's servant, minister (Q.) - guess */
  10.          {"Hir",         "Hiril"},      /* lord, lady (S.) ['ir] */
  11.          {"Aredhel",     "Arwen"},      /* noble elf, maiden (S.) */
  12.          {"Ernil",       "Elentariel"}, /* prince (S.), elf-maiden (Q.) */
  13.          {"Elentar",     "Elentari"},   /* Star-king, -queen (Q.) */
  14.          "Solonor Thelandira", "Aerdrie Faenya", "Lolth", /* Elven */
  15.  #endif
  16.          { "Tenderfoot", 0 },
  17.          { "Lookout", 0 },
  18.          { "Trailblazer", 0 },
  19.          { "Reconnoiterer", "Reconnoiteress" },
  20.          { "Scout", 0 },
  21.          { "Arbalester", 0 }, /* One skilled at crossbows */
  22.          { "Archer", 0 },
  23.          { "Sharpshooter", 0 },
  24.          { "Marksman", "Markswoman" } },
  25.        "Mercury", "_Venus", "Mars", /* Roman/planets */
  26.        "Ran",
  27.        "Orion's camp",
  28.        "the cave of the wumpus",
  29.        PM_RANGER,
  30.        NON_PM,
  31.        PM_LITTLE_DOG /* Orion & canis major */,
  32.        PM_ORION,
  33.        PM_HUNTER,
  34.        PM_SCORPIUS,
  35.        PM_FOREST_CENTAUR,
  36.        PM_SCORPION,
  37.        S_CENTAUR,
  38.        S_SPIDER,
  39.        ART_LONGBOW_OF_DIANA,
  40.        MH_HUMAN | MH_ELF | MH_GNOME | MH_ORC | ROLE_MALE | ROLE_FEMALE
  41.            | ROLE_NEUTRAL | ROLE_CHAOTIC,
  42.        /* Str Int Wis Dex Con Cha */
  43.        { 13, 13, 13, 9, 13, 7 },
  44.        { 30, 10, 10, 20, 20, 10 },
  45.        /* Init   Lower  Higher */
  46.        { 13, 0, 0, 6, 1, 0 }, /* Hit points */
  47.        { 1, 0, 0, 1, 0, 1 },
  48.        12, /* Energy */
  49.        10,
  50.        9,
  51.        2,
  52.        1,
  53.        10,
  54.        A_INT,
  55.        SPE_INVISIBILITY,
  56.        -4 },

Samurai

  1.      { { "Samurai", 0 },
  2.        { { "Hatamoto", 0 },       /* Banner Knight */
  3.          { "Ronin", 0 },          /* no allegiance */
  4.          { "Ninja", "Kunoichi" }, /* secret society */
  5.          { "Joshu", 0 },          /* heads a castle */
  6.          { "Ryoshu", 0 },         /* has a territory */
  7.          { "Kokushu", 0 },        /* heads a province */
  8.          { "Daimyo", 0 },         /* a samurai lord */
  9.          { "Kuge", 0 },           /* Noble of the Court */
  10.          { "Shogun", 0 } },       /* supreme commander, warlord */
  11.        "_Amaterasu Omikami", "Raijin", "Susanowo", /* Japanese */
  12.        "Sam",
  13.        "the Castle of the Taro Clan",
  14.        "the Shogun's Castle",
  15.        PM_SAMURAI,
  16.        NON_PM,
  17.        PM_LITTLE_DOG,
  18.        PM_LORD_SATO,
  19.        PM_ROSHI,
  20.        PM_ASHIKAGA_TAKAUJI,
  21.        PM_WOLF,
  22.        PM_STALKER,
  23.        S_DOG,
  24.        S_ELEMENTAL,
  25.        ART_TSURUGI_OF_MURAMASA,
  26.        MH_HUMAN | ROLE_MALE | ROLE_FEMALE | ROLE_LAWFUL,
  27.        /* Str Int Wis Dex Con Cha */
  28.        { 10, 8, 7, 10, 17, 6 },
  29.        { 30, 10, 8, 30, 14, 8 },
  30.        /* Init   Lower  Higher */
  31.        { 13, 0, 0, 8, 1, 0 }, /* Hit points */
  32.        { 1, 0, 0, 1, 0, 1 },
  33.        11, /* Energy */
  34.        10,
  35.        10,
  36.        0,
  37.        0,
  38.        8,
  39.        A_INT,
  40.        SPE_CLAIRVOYANCE,
  41.        -4 },

Tourist

  1.      { { "Tourist", 0 },
  2.        { { "Rambler", 0 },
  3.          { "Sightseer", 0 },
  4.          { "Excursionist", 0 },
  5.          { "Peregrinator", "Peregrinatrix" },
  6.          { "Traveler", 0 },
  7.          { "Journeyer", 0 },
  8.          { "Voyager", 0 },
  9.          { "Explorer", 0 },
  10.          { "Adventurer", 0 } },
  11.        "Blind Io", "_The Lady", "Offler", /* Discworld */
  12.        "Tou",
  13.        "Ankh-Morpork",
  14.        "the Thieves' Guild Hall",
  15.        PM_TOURIST,
  16.        NON_PM,
  17.        NON_PM,
  18.        PM_TWOFLOWER,
  19.        PM_GUIDE,
  20.        PM_MASTER_OF_THIEVES,
  21.        PM_GIANT_SPIDER,
  22.        PM_FOREST_CENTAUR,
  23.        S_SPIDER,
  24.        S_CENTAUR,
  25.        ART_YENDORIAN_EXPRESS_CARD,
  26.        MH_HUMAN | ROLE_MALE | ROLE_FEMALE | ROLE_NEUTRAL,
  27.        /* Str Int Wis Dex Con Cha */
  28.        { 7, 10, 6, 7, 7, 10 },
  29.        { 15, 10, 10, 15, 30, 20 },
  30.        /* Init   Lower  Higher */
  31.        { 8, 0, 0, 8, 0, 0 }, /* Hit points */
  32.        { 1, 0, 0, 1, 0, 1 },
  33.        14, /* Energy */
  34.        0,
  35.        5,
  36.        1,
  37.        2,
  38.        10,
  39.        A_INT,
  40.        SPE_CHARM_MONSTER,
  41.        -4 },

Valkyrie

  1.      { { "Valkyrie", 0 },
  2.        { { "Stripling", 0 },
  3.          { "Skirmisher", 0 },
  4.          { "Fighter", 0 },
  5.          { "Man-at-arms", "Woman-at-arms" },
  6.          { "Warrior", 0 },
  7.          { "Swashbuckler", 0 },
  8.          { "Hero", "Heroine" },
  9.          { "Champion", 0 },
  10.          { "Lord", "Lady" } },
  11.        "Tyr", "Odin", "Loki", /* Norse */
  12.        "Val",
  13.        "the Shrine of Destiny",
  14.        "the cave of Surtur",
  15.        PM_VALKYRIE,
  16.        NON_PM,
  17.        NON_PM /*PM_WINTER_WOLF_CUB*/,
  18.        PM_NORN,
  19.        PM_WARRIOR,
  20.        PM_LORD_SURTUR,
  21.        PM_FIRE_ANT,
  22.        PM_FIRE_GIANT,
  23.        S_ANT,
  24.        S_GIANT,
  25.        ART_ORB_OF_FATE,
  26.        MH_HUMAN | MH_DWARF | ROLE_FEMALE | ROLE_LAWFUL | ROLE_NEUTRAL,
  27.        /* Str Int Wis Dex Con Cha */
  28.        { 10, 7, 7, 7, 10, 7 },
  29.        { 30, 6, 7, 20, 30, 7 },
  30.        /* Init   Lower  Higher */
  31.        { 14, 0, 0, 8, 2, 0 }, /* Hit points */
  32.        { 1, 0, 0, 1, 0, 1 },
  33.        10, /* Energy */
  34.        0,
  35.        10,
  36.        -2,
  37.        0,
  38.        9,
  39.        A_WIS,
  40.        SPE_CONE_OF_COLD,
  41.        -4 },

Wizard

  1.      { { "Wizard", 0 },
  2.        { { "Evoker", 0 },
  3.          { "Conjurer", 0 },
  4.          { "Thaumaturge", 0 },
  5.          { "Magician", 0 },
  6.          { "Enchanter", "Enchantress" },
  7.          { "Sorcerer", "Sorceress" },
  8.          { "Necromancer", 0 },
  9.          { "Wizard", 0 },
  10.          { "Mage", 0 } },
  11.        "Ptah", "Thoth", "Anhur", /* Egyptian */
  12.        "Wiz",
  13.        "the Lonely Tower",
  14.        "the Tower of Darkness",
  15.        PM_WIZARD,
  16.        NON_PM,
  17.        PM_KITTEN,
  18.        PM_NEFERET_THE_GREEN,
  19.        PM_APPRENTICE,
  20.        PM_DARK_ONE,
  21.        PM_VAMPIRE_BAT,
  22.        PM_XORN,
  23.        S_BAT,
  24.        S_WRAITH,
  25.        ART_EYE_OF_THE_AETHIOPICA,
  26.        MH_HUMAN | MH_ELF | MH_GNOME | MH_ORC | ROLE_MALE | ROLE_FEMALE
  27.            | ROLE_NEUTRAL | ROLE_CHAOTIC,
  28.        /* Str Int Wis Dex Con Cha */
  29.        { 7, 10, 7, 7, 7, 7 },
  30.        { 10, 30, 10, 20, 20, 10 },
  31.        /* Init   Lower  Higher */
  32.        { 10, 0, 0, 8, 1, 0 }, /* Hit points */
  33.        { 4, 3, 0, 2, 0, 3 },
  34.        12, /* Energy */
  35.        0,
  36.        1,
  37.        0,
  38.        3,
  39.        10,
  40.        A_INT,
  41.        SPE_MAGIC_MISSILE,
  42.        -4 },
  43.      /* Array terminator */
  44.      { { 0, 0 } }
  45.  };
  46.  


  1.  /* The player's role, created at runtime from initial
  2.   * choices.  This may be munged in role_init().
  3.   */
  4.  struct Role urole = {
  5.      { "Undefined", 0 },
  6.      { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
  7.        { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } },
  8.      "L", "N", "C",
  9.      "Xxx", "home", "locate",
  10.      NON_PM, NON_PM, NON_PM, NON_PM, NON_PM, NON_PM, NON_PM, NON_PM,
  11.      0, 0, 0, 0,
  12.      /* Str Int Wis Dex Con Cha */
  13.      { 7, 7, 7, 7, 7, 7 },
  14.      { 20, 15, 15, 20, 20, 10 },
  15.      /* Init   Lower  Higher */
  16.      { 10, 0, 0, 8, 1, 0 }, /* Hit points */
  17.      { 2, 0, 0, 2, 0, 3 },
  18.      14, /* Energy */
  19.       0,
  20.      10,
  21.       0,
  22.       0,
  23.       4,
  24.      A_INT,
  25.       0,
  26.      -3
  27.  };
  28.  

Races

  1.  /* Table of all races */
  2.  const struct Race races[] = {

Human

  1.      {
  2.          "human",
  3.          "human",
  4.          "humanity",
  5.          "Hum",
  6.          { "man", "woman" },
  7.          PM_HUMAN,
  8.          NON_PM,
  9.          PM_HUMAN_MUMMY,
  10.          PM_HUMAN_ZOMBIE,
  11.          MH_HUMAN | ROLE_MALE | ROLE_FEMALE | ROLE_LAWFUL | ROLE_NEUTRAL
  12.              | ROLE_CHAOTIC,
  13.          MH_HUMAN,
  14.          0,
  15.          MH_GNOME | MH_ORC,
  16.          /*    Str     Int Wis Dex Con Cha */
  17.          { 3, 3, 3, 3, 3, 3 },
  18.          { STR18(100), 18, 18, 18, 18, 18 },
  19.          /* Init   Lower  Higher */
  20.          { 2, 0, 0, 2, 1, 0 }, /* Hit points */
  21.          { 1, 0, 2, 0, 2, 0 }  /* Energy */
  22.      },

Elf

  1.      {
  2.          "elf",
  3.          "elven",
  4.          "elvenkind",
  5.          "Elf",
  6.          { 0, 0 },
  7.          PM_ELF,
  8.          NON_PM,
  9.          PM_ELF_MUMMY,
  10.          PM_ELF_ZOMBIE,
  11.          MH_ELF | ROLE_MALE | ROLE_FEMALE | ROLE_CHAOTIC,
  12.          MH_ELF,
  13.          MH_ELF,
  14.          MH_ORC,
  15.          /*  Str    Int Wis Dex Con Cha */
  16.          { 3, 3, 3, 3, 3, 3 },
  17.          { 18, 20, 20, 18, 16, 18 },
  18.          /* Init   Lower  Higher */
  19.          { 1, 0, 0, 1, 1, 0 }, /* Hit points */
  20.          { 2, 0, 3, 0, 3, 0 }  /* Energy */
  21.      },

Dwarf

  1.      {
  2.          "dwarf",
  3.          "dwarven",
  4.          "dwarvenkind",
  5.          "Dwa",
  6.          { 0, 0 },
  7.          PM_DWARF,
  8.          NON_PM,
  9.          PM_DWARF_MUMMY,
  10.          PM_DWARF_ZOMBIE,
  11.          MH_DWARF | ROLE_MALE | ROLE_FEMALE | ROLE_LAWFUL,
  12.          MH_DWARF,
  13.          MH_DWARF | MH_GNOME,
  14.          MH_ORC,
  15.          /*    Str     Int Wis Dex Con Cha */
  16.          { 3, 3, 3, 3, 3, 3 },
  17.          { STR18(100), 16, 16, 20, 20, 16 },
  18.          /* Init   Lower  Higher */
  19.          { 4, 0, 0, 3, 2, 0 }, /* Hit points */
  20.          { 0, 0, 0, 0, 0, 0 }  /* Energy */
  21.      },

Gnome

  1.      {
  2.          "gnome",
  3.          "gnomish",
  4.          "gnomehood",
  5.          "Gno",
  6.          { 0, 0 },
  7.          PM_GNOME,
  8.          NON_PM,
  9.          PM_GNOME_MUMMY,
  10.          PM_GNOME_ZOMBIE,
  11.          MH_GNOME | ROLE_MALE | ROLE_FEMALE | ROLE_NEUTRAL,
  12.          MH_GNOME,
  13.          MH_DWARF | MH_GNOME,
  14.          MH_HUMAN,
  15.          /*  Str    Int Wis Dex Con Cha */
  16.          { 3, 3, 3, 3, 3, 3 },
  17.          { STR18(50), 19, 18, 18, 18, 18 },
  18.          /* Init   Lower  Higher */
  19.          { 1, 0, 0, 1, 0, 0 }, /* Hit points */
  20.          { 2, 0, 2, 0, 2, 0 }  /* Energy */
  21.      },

Orc

  1.      {
  2.          "orc",
  3.          "orcish",
  4.          "orcdom",
  5.          "Orc",
  6.          { 0, 0 },
  7.          PM_ORC,
  8.          NON_PM,
  9.          PM_ORC_MUMMY,
  10.          PM_ORC_ZOMBIE,
  11.          MH_ORC | ROLE_MALE | ROLE_FEMALE | ROLE_CHAOTIC,
  12.          MH_ORC,
  13.          0,
  14.          MH_HUMAN | MH_ELF | MH_DWARF,
  15.          /*  Str    Int Wis Dex Con Cha */
  16.          { 3, 3, 3, 3, 3, 3 },
  17.          { STR18(50), 16, 16, 18, 18, 16 },
  18.          /* Init   Lower  Higher */
  19.          { 1, 0, 0, 1, 0, 0 }, /* Hit points */
  20.          { 1, 0, 1, 0, 1, 0 }  /* Energy */
  21.      },
  22.      /* Array terminator */
  23.      { 0, 0, 0, 0 }
  24.  };


  1.  
  2.  /* The player's race, created at runtime from initial
  3.   * choices.  This may be munged in role_init().
  4.   */
  5.  struct Race urace = {
  6.      "something",
  7.      "undefined",
  8.      "something",
  9.      "Xxx",
  10.      { 0, 0 },
  11.      NON_PM,
  12.      NON_PM,
  13.      NON_PM,
  14.      NON_PM,
  15.      0,
  16.      0,
  17.      0,
  18.      0,
  19.      /*    Str     Int Wis Dex Con Cha */
  20.      { 3, 3, 3, 3, 3, 3 },
  21.      { STR18(100), 18, 18, 18, 18, 18 },
  22.      /* Init   Lower  Higher */
  23.      { 2, 0, 0, 2, 1, 0 }, /* Hit points */
  24.      { 1, 0, 2, 0, 2, 0 }  /* Energy */
  25.  };
  26.  

Genders

  1.  /* Table of all genders */
  2.  const struct Gender genders[] = {
  3.      { "male", "he", "him", "his", "Mal", ROLE_MALE },
  4.      { "female", "she", "her", "her", "Fem", ROLE_FEMALE },
  5.      { "neuter", "it", "it", "its", "Ntr", ROLE_NEUTER }
  6.  };
  7.  

Alignments

  1.  /* Table of all alignments */
  2.  const struct Align aligns[] = {
  3.      { "law", "lawful", "Law", ROLE_LAWFUL, A_LAWFUL },
  4.      { "balance", "neutral", "Neu", ROLE_NEUTRAL, A_NEUTRAL },
  5.      { "chaos", "chaotic", "Cha", ROLE_CHAOTIC, A_CHAOTIC },
  6.      { "evil", "unaligned", "Una", 0, A_NONE }
  7.  };
  8.  


  1.  /* Filters */
  2.  static struct {
  3.      boolean roles[SIZE(roles)];
  4.      short mask;
  5.  } filter;
  6.  
  7.  STATIC_DCL int NDECL(randrole_filtered);
  8.  STATIC_DCL char *FDECL(promptsep, (char *, int));
  9.  STATIC_DCL int FDECL(role_gendercount, (int));
  10.  STATIC_DCL int FDECL(race_alignmentcount, (int));
  11.  
  12.  /* used by str2XXX() */
  13.  static char NEARDATA randomstr[] = "random";
  14.  

validrole

  1.  boolean
  2.  validrole(rolenum)
  3.  int rolenum;
  4.  {
  5.      return (boolean) (rolenum >= 0 && rolenum < SIZE(roles) - 1);
  6.  }
  7.  

randrole

  1.  int
  2.  randrole()
  3.  {
  4.      return rn2(SIZE(roles) - 1);
  5.  }
  6.  

randrole_filtered

  1.  STATIC_OVL int
  2.  randrole_filtered()
  3.  {
  4.      int i, n = 0, set[SIZE(roles)];
  5.  
  6.      /* this doesn't rule out impossible combinations but attempts to
  7.         honor all the filter masks */
  8.      for (i = 0; i < SIZE(roles); ++i)
  9.          if (ok_role(i, ROLE_NONE, ROLE_NONE, ROLE_NONE)
  10.              && ok_race(i, ROLE_RANDOM, ROLE_NONE, ROLE_NONE)
  11.              && ok_gend(i, ROLE_NONE, ROLE_RANDOM, ROLE_NONE)
  12.              && ok_align(i, ROLE_NONE, ROLE_NONE, ROLE_RANDOM))
  13.              set[n++] = i;
  14.      return n ? set[rn2(n)] : randrole();
  15.  }
  16.  

str2role

  1.  int
  2.  str2role(str)
  3.  const char *str;
  4.  {
  5.      int i, len;
  6.  
  7.      /* Is str valid? */
  8.      if (!str || !str[0])
  9.          return ROLE_NONE;
  10.  
  11.      /* Match as much of str as is provided */
  12.      len = strlen(str);
  13.      for (i = 0; roles[i].name.m; i++) {
  14.          /* Does it match the male name? */
  15.          if (!strncmpi(str, roles[i].name.m, len))
  16.              return i;
  17.          /* Or the female name? */
  18.          if (roles[i].name.f && !strncmpi(str, roles[i].name.f, len))
  19.              return i;
  20.          /* Or the filecode? */
  21.          if (!strcmpi(str, roles[i].filecode))
  22.              return i;
  23.      }
  24.  
  25.      if ((len == 1 && (*str == '*' || *str == '@'))
  26.          || !strncmpi(str, randomstr, len))
  27.          return ROLE_RANDOM;
  28.  
  29.      /* Couldn't find anything appropriate */
  30.      return ROLE_NONE;
  31.  }
  32.  

validrace

  1.  boolean
  2.  validrace(rolenum, racenum)
  3.  int rolenum, racenum;
  4.  {
  5.      /* Assumes validrole */
  6.      return (boolean) (racenum >= 0 && racenum < SIZE(races) - 1
  7.                        && (roles[rolenum].allow & races[racenum].allow
  8.                            & ROLE_RACEMASK));
  9.  }
  10.  

randrace

  1.  int
  2.  randrace(rolenum)
  3.  int rolenum;
  4.  {
  5.      int i, n = 0;
  6.  
  7.      /* Count the number of valid races */
  8.      for (i = 0; races[i].noun; i++)
  9.          if (roles[rolenum].allow & races[i].allow & ROLE_RACEMASK)
  10.              n++;
  11.  
  12.      /* Pick a random race */
  13.      /* Use a factor of 100 in case of bad random number generators */
  14.      if (n)
  15.          n = rn2(n * 100) / 100;
  16.      for (i = 0; races[i].noun; i++)
  17.          if (roles[rolenum].allow & races[i].allow & ROLE_RACEMASK) {
  18.              if (n)
  19.                  n--;
  20.              else
  21.                  return i;
  22.          }
  23.  
  24.      /* This role has no permitted races? */
  25.      return rn2(SIZE(races) - 1);
  26.  }
  27.  

str2race

  1.  int
  2.  str2race(str)
  3.  const char *str;
  4.  {
  5.      int i, len;
  6.  
  7.      /* Is str valid? */
  8.      if (!str || !str[0])
  9.          return ROLE_NONE;
  10.  
  11.      /* Match as much of str as is provided */
  12.      len = strlen(str);
  13.      for (i = 0; races[i].noun; i++) {
  14.          /* Does it match the noun? */
  15.          if (!strncmpi(str, races[i].noun, len))
  16.              return i;
  17.          /* Or the filecode? */
  18.          if (!strcmpi(str, races[i].filecode))
  19.              return i;
  20.      }
  21.  
  22.      if ((len == 1 && (*str == '*' || *str == '@'))
  23.          || !strncmpi(str, randomstr, len))
  24.          return ROLE_RANDOM;
  25.  
  26.      /* Couldn't find anything appropriate */
  27.      return ROLE_NONE;
  28.  }
  29.  

validgend

  1.  boolean
  2.  validgend(rolenum, racenum, gendnum)
  3.  int rolenum, racenum, gendnum;
  4.  {
  5.      /* Assumes validrole and validrace */
  6.      return (boolean) (gendnum >= 0 && gendnum < ROLE_GENDERS
  7.                        && (roles[rolenum].allow & races[racenum].allow
  8.                            & genders[gendnum].allow & ROLE_GENDMASK));
  9.  }
  10.  

randgend

  1.  int
  2.  randgend(rolenum, racenum)
  3.  int rolenum, racenum;
  4.  {
  5.      int i, n = 0;
  6.  
  7.      /* Count the number of valid genders */
  8.      for (i = 0; i < ROLE_GENDERS; i++)
  9.          if (roles[rolenum].allow & races[racenum].allow & genders[i].allow
  10.              & ROLE_GENDMASK)
  11.              n++;
  12.  
  13.      /* Pick a random gender */
  14.      if (n)
  15.          n = rn2(n);
  16.      for (i = 0; i < ROLE_GENDERS; i++)
  17.          if (roles[rolenum].allow & races[racenum].allow & genders[i].allow
  18.              & ROLE_GENDMASK) {
  19.              if (n)
  20.                  n--;
  21.              else
  22.                  return i;
  23.          }
  24.  
  25.      /* This role/race has no permitted genders? */
  26.      return rn2(ROLE_GENDERS);
  27.  }
  28.  

str2gend

  1.  int
  2.  str2gend(str)
  3.  const char *str;
  4.  {
  5.      int i, len;
  6.  
  7.      /* Is str valid? */
  8.      if (!str || !str[0])
  9.          return ROLE_NONE;
  10.  
  11.      /* Match as much of str as is provided */
  12.      len = strlen(str);
  13.      for (i = 0; i < ROLE_GENDERS; i++) {
  14.          /* Does it match the adjective? */
  15.          if (!strncmpi(str, genders[i].adj, len))
  16.              return i;
  17.          /* Or the filecode? */
  18.          if (!strcmpi(str, genders[i].filecode))
  19.              return i;
  20.      }
  21.      if ((len == 1 && (*str == '*' || *str == '@'))
  22.          || !strncmpi(str, randomstr, len))
  23.          return ROLE_RANDOM;
  24.  
  25.      /* Couldn't find anything appropriate */
  26.      return ROLE_NONE;
  27.  }
  28.  

validalign

  1.  boolean
  2.  validalign(rolenum, racenum, alignnum)
  3.  int rolenum, racenum, alignnum;
  4.  {
  5.      /* Assumes validrole and validrace */
  6.      return (boolean) (alignnum >= 0 && alignnum < ROLE_ALIGNS
  7.                        && (roles[rolenum].allow & races[racenum].allow
  8.                            & aligns[alignnum].allow & ROLE_ALIGNMASK));
  9.  }
  10.  

randalign

  1.  int
  2.  randalign(rolenum, racenum)
  3.  int rolenum, racenum;
  4.  {
  5.      int i, n = 0;
  6.  
  7.      /* Count the number of valid alignments */
  8.      for (i = 0; i < ROLE_ALIGNS; i++)
  9.          if (roles[rolenum].allow & races[racenum].allow & aligns[i].allow
  10.              & ROLE_ALIGNMASK)
  11.              n++;
  12.  
  13.      /* Pick a random alignment */
  14.      if (n)
  15.          n = rn2(n);
  16.      for (i = 0; i < ROLE_ALIGNS; i++)
  17.          if (roles[rolenum].allow & races[racenum].allow & aligns[i].allow
  18.              & ROLE_ALIGNMASK) {
  19.              if (n)
  20.                  n--;
  21.              else
  22.                  return i;
  23.          }
  24.  
  25.      /* This role/race has no permitted alignments? */
  26.      return rn2(ROLE_ALIGNS);
  27.  }
  28.  

str2align

  1.  int
  2.  str2align(str)
  3.  const char *str;
  4.  {
  5.      int i, len;
  6.  
  7.      /* Is str valid? */
  8.      if (!str || !str[0])
  9.          return ROLE_NONE;
  10.  
  11.      /* Match as much of str as is provided */
  12.      len = strlen(str);
  13.      for (i = 0; i < ROLE_ALIGNS; i++) {
  14.          /* Does it match the adjective? */
  15.          if (!strncmpi(str, aligns[i].adj, len))
  16.              return i;
  17.          /* Or the filecode? */
  18.          if (!strcmpi(str, aligns[i].filecode))
  19.              return i;
  20.      }
  21.      if ((len == 1 && (*str == '*' || *str == '@'))
  22.          || !strncmpi(str, randomstr, len))
  23.          return ROLE_RANDOM;
  24.  
  25.      /* Couldn't find anything appropriate */
  26.      return ROLE_NONE;
  27.  }
  28.  

ok_role

  1.  /* is rolenum compatible with any racenum/gendnum/alignnum constraints? */
  2.  boolean
  3.  ok_role(rolenum, racenum, gendnum, alignnum)
  4.  int rolenum, racenum, gendnum, alignnum;
  5.  {
  6.      int i;
  7.      short allow;
  8.  
  9.      if (rolenum >= 0 && rolenum < SIZE(roles) - 1) {
  10.          if (filter.roles[rolenum])
  11.              return FALSE;
  12.          allow = roles[rolenum].allow;
  13.          if (racenum >= 0 && racenum < SIZE(races) - 1
  14.              && !(allow & races[racenum].allow & ROLE_RACEMASK))
  15.              return FALSE;
  16.          if (gendnum >= 0 && gendnum < ROLE_GENDERS
  17.              && !(allow & genders[gendnum].allow & ROLE_GENDMASK))
  18.              return FALSE;
  19.          if (alignnum >= 0 && alignnum < ROLE_ALIGNS
  20.              && !(allow & aligns[alignnum].allow & ROLE_ALIGNMASK))
  21.              return FALSE;
  22.          return TRUE;
  23.      } else {
  24.          /* random; check whether any selection is possible */
  25.          for (i = 0; i < SIZE(roles) - 1; i++) {
  26.              if (filter.roles[i])
  27.                  continue;
  28.              allow = roles[i].allow;
  29.              if (racenum >= 0 && racenum < SIZE(races) - 1
  30.                  && !(allow & races[racenum].allow & ROLE_RACEMASK))
  31.                  continue;
  32.              if (gendnum >= 0 && gendnum < ROLE_GENDERS
  33.                  && !(allow & genders[gendnum].allow & ROLE_GENDMASK))
  34.                  continue;
  35.              if (alignnum >= 0 && alignnum < ROLE_ALIGNS
  36.                  && !(allow & aligns[alignnum].allow & ROLE_ALIGNMASK))
  37.                  continue;
  38.              return TRUE;
  39.          }
  40.          return FALSE;
  41.      }
  42.  }
  43.  

pick_role

  1.  /* pick a random role subject to any racenum/gendnum/alignnum constraints */
  2.  /* If pickhow == PICK_RIGID a role is returned only if there is  */
  3.  /* a single possibility */
  4.  int
  5.  pick_role(racenum, gendnum, alignnum, pickhow)
  6.  int racenum, gendnum, alignnum, pickhow;
  7.  {
  8.      int i;
  9.      int roles_ok = 0, set[SIZE(roles)];
  10.  
  11.      for (i = 0; i < SIZE(roles) - 1; i++) {
  12.          if (ok_role(i, racenum, gendnum, alignnum)
  13.              && ok_race(i, (racenum >= 0) ? racenum : ROLE_RANDOM,
  14.                         gendnum, alignnum)
  15.              && ok_gend(i, racenum,
  16.                         (gendnum >= 0) ? gendnum : ROLE_RANDOM, alignnum)
  17.              && ok_race(i, racenum,
  18.                         gendnum, (alignnum >= 0) ? alignnum : ROLE_RANDOM))
  19.              set[roles_ok++] = i;
  20.      }
  21.      if (roles_ok == 0 || (roles_ok > 1 && pickhow == PICK_RIGID))
  22.          return ROLE_NONE;
  23.      return set[rn2(roles_ok)];
  24.  }
  25.  

ok_race

  1.  /* is racenum compatible with any rolenum/gendnum/alignnum constraints? */
  2.  boolean
  3.  ok_race(rolenum, racenum, gendnum, alignnum)
  4.  int rolenum, racenum, gendnum, alignnum;
  5.  {
  6.      int i;
  7.      short allow;
  8.  
  9.      if (racenum >= 0 && racenum < SIZE(races) - 1) {
  10.          if (filter.mask & races[racenum].selfmask)
  11.              return FALSE;
  12.          allow = races[racenum].allow;
  13.          if (rolenum >= 0 && rolenum < SIZE(roles) - 1
  14.              && !(allow & roles[rolenum].allow & ROLE_RACEMASK))
  15.              return FALSE;
  16.          if (gendnum >= 0 && gendnum < ROLE_GENDERS
  17.              && !(allow & genders[gendnum].allow & ROLE_GENDMASK))
  18.              return FALSE;
  19.          if (alignnum >= 0 && alignnum < ROLE_ALIGNS
  20.              && !(allow & aligns[alignnum].allow & ROLE_ALIGNMASK))
  21.              return FALSE;
  22.          return TRUE;
  23.      } else {
  24.          /* random; check whether any selection is possible */
  25.          for (i = 0; i < SIZE(races) - 1; i++) {
  26.              if (filter.mask & races[i].selfmask)
  27.                  continue;
  28.              allow = races[i].allow;
  29.              if (rolenum >= 0 && rolenum < SIZE(roles) - 1
  30.                  && !(allow & roles[rolenum].allow & ROLE_RACEMASK))
  31.                  continue;
  32.              if (gendnum >= 0 && gendnum < ROLE_GENDERS
  33.                  && !(allow & genders[gendnum].allow & ROLE_GENDMASK))
  34.                  continue;
  35.              if (alignnum >= 0 && alignnum < ROLE_ALIGNS
  36.                  && !(allow & aligns[alignnum].allow & ROLE_ALIGNMASK))
  37.                  continue;
  38.              return TRUE;
  39.          }
  40.          return FALSE;
  41.      }
  42.  }
  43.  

pick_race

  1.  /* pick a random race subject to any rolenum/gendnum/alignnum constraints */
  2.  /* If pickhow == PICK_RIGID a race is returned only if there is  */
  3.  /* a single possibility */
  4.  int
  5.  pick_race(rolenum, gendnum, alignnum, pickhow)
  6.  int rolenum, gendnum, alignnum, pickhow;
  7.  {
  8.      int i;
  9.      int races_ok = 0;
  10.  
  11.      for (i = 0; i < SIZE(races) - 1; i++) {
  12.          if (ok_race(rolenum, i, gendnum, alignnum))
  13.              races_ok++;
  14.      }
  15.      if (races_ok == 0 || (races_ok > 1 && pickhow == PICK_RIGID))
  16.          return ROLE_NONE;
  17.      races_ok = rn2(races_ok);
  18.      for (i = 0; i < SIZE(races) - 1; i++) {
  19.          if (ok_race(rolenum, i, gendnum, alignnum)) {
  20.              if (races_ok == 0)
  21.                  return i;
  22.              else
  23.                  races_ok--;
  24.          }
  25.      }
  26.      return ROLE_NONE;
  27.  }
  28.  

ok_gend

  1.  /* is gendnum compatible with any rolenum/racenum/alignnum constraints? */
  2.  /* gender and alignment are not comparable (and also not constrainable) */
  3.  boolean
  4.  ok_gend(rolenum, racenum, gendnum, alignnum)
  5.  int rolenum, racenum, gendnum;
  6.  int alignnum UNUSED;
  7.  {
  8.      int i;
  9.      short allow;
  10.  
  11.      if (gendnum >= 0 && gendnum < ROLE_GENDERS) {
  12.          if (filter.mask & genders[gendnum].allow)
  13.              return FALSE;
  14.          allow = genders[gendnum].allow;
  15.          if (rolenum >= 0 && rolenum < SIZE(roles) - 1
  16.              && !(allow & roles[rolenum].allow & ROLE_GENDMASK))
  17.              return FALSE;
  18.          if (racenum >= 0 && racenum < SIZE(races) - 1
  19.              && !(allow & races[racenum].allow & ROLE_GENDMASK))
  20.              return FALSE;
  21.          return TRUE;
  22.      } else {
  23.          /* random; check whether any selection is possible */
  24.          for (i = 0; i < ROLE_GENDERS; i++) {
  25.              if (filter.mask & genders[i].allow)
  26.                  continue;
  27.              allow = genders[i].allow;
  28.              if (rolenum >= 0 && rolenum < SIZE(roles) - 1
  29.                  && !(allow & roles[rolenum].allow & ROLE_GENDMASK))
  30.                  continue;
  31.              if (racenum >= 0 && racenum < SIZE(races) - 1
  32.                  && !(allow & races[racenum].allow & ROLE_GENDMASK))
  33.                  continue;
  34.              return TRUE;
  35.          }
  36.          return FALSE;
  37.      }
  38.  }
  39.  

pick_gend

  1.  /* pick a random gender subject to any rolenum/racenum/alignnum constraints */
  2.  /* gender and alignment are not comparable (and also not constrainable) */
  3.  /* If pickhow == PICK_RIGID a gender is returned only if there is  */
  4.  /* a single possibility */
  5.  int
  6.  pick_gend(rolenum, racenum, alignnum, pickhow)
  7.  int rolenum, racenum, alignnum, pickhow;
  8.  {
  9.      int i;
  10.      int gends_ok = 0;
  11.  
  12.      for (i = 0; i < ROLE_GENDERS; i++) {
  13.          if (ok_gend(rolenum, racenum, i, alignnum))
  14.              gends_ok++;
  15.      }
  16.      if (gends_ok == 0 || (gends_ok > 1 && pickhow == PICK_RIGID))
  17.          return ROLE_NONE;
  18.      gends_ok = rn2(gends_ok);
  19.      for (i = 0; i < ROLE_GENDERS; i++) {
  20.          if (ok_gend(rolenum, racenum, i, alignnum)) {
  21.              if (gends_ok == 0)
  22.                  return i;
  23.              else
  24.                  gends_ok--;
  25.          }
  26.      }
  27.      return ROLE_NONE;
  28.  }
  29.  

ok_align

  1.  /* is alignnum compatible with any rolenum/racenum/gendnum constraints? */
  2.  /* alignment and gender are not comparable (and also not constrainable) */
  3.  boolean
  4.  ok_align(rolenum, racenum, gendnum, alignnum)
  5.  int rolenum, racenum;
  6.  int gendnum UNUSED;
  7.  int alignnum;
  8.  {
  9.      int i;
  10.      short allow;
  11.  
  12.      if (alignnum >= 0 && alignnum < ROLE_ALIGNS) {
  13.          if (filter.mask & aligns[alignnum].allow)
  14.              return FALSE;
  15.          allow = aligns[alignnum].allow;
  16.          if (rolenum >= 0 && rolenum < SIZE(roles) - 1
  17.              && !(allow & roles[rolenum].allow & ROLE_ALIGNMASK))
  18.              return FALSE;
  19.          if (racenum >= 0 && racenum < SIZE(races) - 1
  20.              && !(allow & races[racenum].allow & ROLE_ALIGNMASK))
  21.              return FALSE;
  22.          return TRUE;
  23.      } else {
  24.          /* random; check whether any selection is possible */
  25.          for (i = 0; i < ROLE_ALIGNS; i++) {
  26.              if (filter.mask & aligns[i].allow)
  27.                  return FALSE;
  28.              allow = aligns[i].allow;
  29.              if (rolenum >= 0 && rolenum < SIZE(roles) - 1
  30.                  && !(allow & roles[rolenum].allow & ROLE_ALIGNMASK))
  31.                  continue;
  32.              if (racenum >= 0 && racenum < SIZE(races) - 1
  33.                  && !(allow & races[racenum].allow & ROLE_ALIGNMASK))
  34.                  continue;
  35.              return TRUE;
  36.          }
  37.          return FALSE;
  38.      }
  39.  }
  40.  

pick_align

  1.  /* pick a random alignment subject to any rolenum/racenum/gendnum constraints
  2.   */
  3.  /* alignment and gender are not comparable (and also not constrainable) */
  4.  /* If pickhow == PICK_RIGID an alignment is returned only if there is  */
  5.  /* a single possibility */
  6.  int
  7.  pick_align(rolenum, racenum, gendnum, pickhow)
  8.  int rolenum, racenum, gendnum, pickhow;
  9.  {
  10.      int i;
  11.      int aligns_ok = 0;
  12.  
  13.      for (i = 0; i < ROLE_ALIGNS; i++) {
  14.          if (ok_align(rolenum, racenum, gendnum, i))
  15.              aligns_ok++;
  16.      }
  17.      if (aligns_ok == 0 || (aligns_ok > 1 && pickhow == PICK_RIGID))
  18.          return ROLE_NONE;
  19.      aligns_ok = rn2(aligns_ok);
  20.      for (i = 0; i < ROLE_ALIGNS; i++) {
  21.          if (ok_align(rolenum, racenum, gendnum, i)) {
  22.              if (aligns_ok == 0)
  23.                  return i;
  24.              else
  25.                  aligns_ok--;
  26.          }
  27.      }
  28.      return ROLE_NONE;
  29.  }
  30.  

rigid_role_checks

  1.  void
  2.  rigid_role_checks()
  3.  {
  4.      /* Some roles are limited to a single race, alignment, or gender and
  5.       * calling this routine prior to XXX_player_selection() will help
  6.       * prevent an extraneous prompt that actually doesn't allow
  7.       * you to choose anything further. Note the use of PICK_RIGID which
  8.       * causes the pick_XX() routine to return a value only if there is one
  9.       * single possible selection, otherwise it returns ROLE_NONE.
  10.       *
  11.       */
  12.      if (flags.initrole == ROLE_RANDOM) {
  13.          /* If the role was explicitly specified as ROLE_RANDOM
  14.           * via -uXXXX-@ then choose the role in here to narrow down
  15.           * later choices. Pick a random role in this case.
  16.           */
  17.          flags.initrole = pick_role(flags.initrace, flags.initgend,
  18.                                     flags.initalign, PICK_RANDOM);
  19.          if (flags.initrole < 0)
  20.              flags.initrole = randrole_filtered();
  21.      }
  22.      if (flags.initrole != ROLE_NONE) {
  23.          if (flags.initrace == ROLE_NONE)
  24.              flags.initrace = pick_race(flags.initrole, flags.initgend,
  25.                                         flags.initalign, PICK_RIGID);
  26.          if (flags.initalign == ROLE_NONE)
  27.              flags.initalign = pick_align(flags.initrole, flags.initrace,
  28.                                           flags.initgend, PICK_RIGID);
  29.          if (flags.initgend == ROLE_NONE)
  30.              flags.initgend = pick_gend(flags.initrole, flags.initrace,
  31.                                         flags.initalign, PICK_RIGID);
  32.      }
  33.  }
  34.  

setrolefilter

  1.  boolean
  2.  setrolefilter(bufp)
  3.  const char *bufp;
  4.  {
  5.      int i;
  6.      boolean reslt = TRUE;
  7.  
  8.      if ((i = str2role(bufp)) != ROLE_NONE && i != ROLE_RANDOM)
  9.          filter.roles[i] = TRUE;
  10.      else if ((i = str2race(bufp)) != ROLE_NONE && i != ROLE_RANDOM)
  11.          filter.mask |= races[i].selfmask;
  12.      else if ((i = str2gend(bufp)) != ROLE_NONE && i != ROLE_RANDOM)
  13.          filter.mask |= genders[i].allow;
  14.      else if ((i = str2align(bufp)) != ROLE_NONE && i != ROLE_RANDOM)
  15.          filter.mask |= aligns[i].allow;
  16.      else
  17.          reslt = FALSE;
  18.      return reslt;
  19.  }
  20.  

gotrolefilter

  1.  boolean
  2.  gotrolefilter()
  3.  {
  4.      int i;
  5.  
  6.      if (filter.mask)
  7.          return TRUE;
  8.      for (i = 0; i < SIZE(roles); ++i)
  9.          if (filter.roles[i])
  10.              return TRUE;
  11.      return FALSE;
  12.  }
  13.  

clearrolefilter

  1.  void
  2.  clearrolefilter()
  3.  {
  4.      int i;
  5.  
  6.      for (i = 0; i < SIZE(roles); ++i)
  7.          filter.roles[i] = FALSE;
  8.      filter.mask = 0;
  9.  }
  10.  

promptsep

  1.  #define BP_ALIGN 0
  2.  #define BP_GEND 1
  3.  #define BP_RACE 2
  4.  #define BP_ROLE 3
  5.  #define NUM_BP 4
  6.  
  7.  STATIC_VAR char pa[NUM_BP], post_attribs;
1401. 			       
  1.  STATIC_OVL char *
  2.  promptsep(buf, num_post_attribs)
  3.  char *buf;
  4.  int num_post_attribs;
  5.  {
  6.      const char *conjuct = "and ";
  7.  
  8.      if (num_post_attribs > 1 && post_attribs < num_post_attribs
  9.          && post_attribs > 1)
  10.          Strcat(buf, ",");
  11.      Strcat(buf, " ");
  12.      --post_attribs;
  13.      if (!post_attribs && num_post_attribs > 1)
  14.          Strcat(buf, conjuct);
  15.      return buf;
  16.  }
  17.  

== role_gendercount

  1.  STATIC_OVL int
  2.  role_gendercount(rolenum)
  3.  int rolenum;
  4.  {
  5.      int gendcount = 0;
  6.  
  7.      if (validrole(rolenum)) {
  8.          if (roles[rolenum].allow & ROLE_MALE)
  9.              ++gendcount;
  10.          if (roles[rolenum].allow & ROLE_FEMALE)
  11.              ++gendcount;
  12.          if (roles[rolenum].allow & ROLE_NEUTER)
  13.              ++gendcount;
  14.      }
  15.      return gendcount;
  16.  }
  17.  

race_alignmentcount

  1.  STATIC_OVL int
  2.  race_alignmentcount(racenum)
  3.  int racenum;
  4.  {
  5.      int aligncount = 0;
  6.  
  7.      if (racenum != ROLE_NONE && racenum != ROLE_RANDOM) {
  8.          if (races[racenum].allow & ROLE_CHAOTIC)
  9.              ++aligncount;
  10.          if (races[racenum].allow & ROLE_LAWFUL)
  11.              ++aligncount;
  12.          if (races[racenum].allow & ROLE_NEUTRAL)
  13.              ++aligncount;
  14.      }
  15.      return aligncount;
  16.  }
  17.  

root_plselection_prompt

  1.  char *
  2.  root_plselection_prompt(suppliedbuf, buflen, rolenum, racenum, gendnum,
  3.                          alignnum)
  4.  char *suppliedbuf;
  5.  int buflen, rolenum, racenum, gendnum, alignnum;
  6.  {
  7.      int k, gendercount = 0, aligncount = 0;
  8.      char buf[BUFSZ];
  9.      static char err_ret[] = " character's";
  10.      boolean donefirst = FALSE;
  11.  
  12.      if (!suppliedbuf || buflen < 1)
  13.          return err_ret;
  14.  
  15.      /* initialize these static variables each time this is called */
  16.      post_attribs = 0;
  17.      for (k = 0; k < NUM_BP; ++k)
  18.          pa[k] = 0;
  19.      buf[0] = '\0';
  20.      *suppliedbuf = '\0';
  21.  
  22.      /* How many alignments are allowed for the desired race? */
  23.      if (racenum != ROLE_NONE && racenum != ROLE_RANDOM)
  24.          aligncount = race_alignmentcount(racenum);
  25.  
  26.      if (alignnum != ROLE_NONE && alignnum != ROLE_RANDOM
  27.          && ok_align(rolenum, racenum, gendnum, alignnum)) {
  28.          /* if race specified, and multiple choice of alignments for it */
  29.          if ((racenum >= 0) && (aligncount > 1)) {
  30.              if (donefirst)
  31.                  Strcat(buf, " ");
  32.              Strcat(buf, aligns[alignnum].adj);
  33.              donefirst = TRUE;
  34.          } else {
  35.              if (donefirst)
  36.                  Strcat(buf, " ");
  37.              Strcat(buf, aligns[alignnum].adj);
  38.              donefirst = TRUE;
  39.          }
  40.      } else {
  41.          /* in case we got here by failing the ok_align() test */
  42.          if (alignnum != ROLE_RANDOM)
  43.              alignnum = ROLE_NONE;
  44.          /* if alignment not specified, but race is specified
  45.             and only one choice of alignment for that race then
  46.             don't include it in the later list */
  47.          if ((((racenum != ROLE_NONE && racenum != ROLE_RANDOM)
  48.                && ok_race(rolenum, racenum, gendnum, alignnum))
  49.               && (aligncount > 1))
  50.              || (racenum == ROLE_NONE || racenum == ROLE_RANDOM)) {
  51.              pa[BP_ALIGN] = 1;
  52.              post_attribs++;
  53.          }
  54.      }
  55.      /* <your lawful> */
  56.  
  57.      /* How many genders are allowed for the desired role? */
  58.      if (validrole(rolenum))
  59.          gendercount = role_gendercount(rolenum);
  60.  
  61.      if (gendnum != ROLE_NONE && gendnum != ROLE_RANDOM) {
  62.          if (validrole(rolenum)) {
  63.              /* if role specified, and multiple choice of genders for it,
  64.                 and name of role itself does not distinguish gender */
  65.              if ((rolenum != ROLE_NONE) && (gendercount > 1)
  66.                  && !roles[rolenum].name.f) {
  67.                  if (donefirst)
  68.                      Strcat(buf, " ");
  69.                  Strcat(buf, genders[gendnum].adj);
  70.                  donefirst = TRUE;
  71.              }
  72.          } else {
  73.              if (donefirst)
  74.                  Strcat(buf, " ");
  75.              Strcat(buf, genders[gendnum].adj);
  76.              donefirst = TRUE;
  77.          }
  78.      } else {
  79.          /* if gender not specified, but role is specified
  80.                  and only one choice of gender then
  81.                  don't include it in the later list */
  82.          if ((validrole(rolenum) && (gendercount > 1))
  83.              || !validrole(rolenum)) {
  84.              pa[BP_GEND] = 1;
  85.              post_attribs++;
  86.          }
  87.      }
  88.      /* <your lawful female> */
  89.  
  90.      if (racenum != ROLE_NONE && racenum != ROLE_RANDOM) {
  91.          if (validrole(rolenum)
  92.              && ok_race(rolenum, racenum, gendnum, alignnum)) {
  93.              if (donefirst)
  94.                  Strcat(buf, " ");
  95.              Strcat(buf, (rolenum == ROLE_NONE) ? races[racenum].noun
  96.                                                 : races[racenum].adj);
  97.              donefirst = TRUE;
  98.          } else if (!validrole(rolenum)) {
  99.              if (donefirst)
  100.                  Strcat(buf, " ");
  101.              Strcat(buf, races[racenum].noun);
  102.              donefirst = TRUE;
  103.          } else {
  104.              pa[BP_RACE] = 1;
  105.              post_attribs++;
  106.          }
  107.      } else {
  108.          pa[BP_RACE] = 1;
  109.          post_attribs++;
  110.      }
  111.      /* <your lawful female gnomish> || <your lawful female gnome> */
  112.  
  113.      if (validrole(rolenum)) {
  114.          if (donefirst)
  115.              Strcat(buf, " ");
  116.          if (gendnum != ROLE_NONE) {
  117.              if (gendnum == 1 && roles[rolenum].name.f)
  118.                  Strcat(buf, roles[rolenum].name.f);
  119.              else
  120.                  Strcat(buf, roles[rolenum].name.m);
  121.          } else {
  122.              if (roles[rolenum].name.f) {
  123.                  Strcat(buf, roles[rolenum].name.m);
  124.                  Strcat(buf, "/");
  125.                  Strcat(buf, roles[rolenum].name.f);
  126.              } else
  127.                  Strcat(buf, roles[rolenum].name.m);
  128.          }
  129.          donefirst = TRUE;
  130.      } else if (rolenum == ROLE_NONE) {
  131.          pa[BP_ROLE] = 1;
  132.          post_attribs++;
  133.      }
  134.  
  135.      if ((racenum == ROLE_NONE || racenum == ROLE_RANDOM)
  136.          && !validrole(rolenum)) {
  137.          if (donefirst)
  138.              Strcat(buf, " ");
  139.          Strcat(buf, "character");
  140.          donefirst = TRUE;
  141.      }
  142.      /* <your lawful female gnomish cavewoman> || <your lawful female gnome>
  143.       *    || <your lawful female character>
  144.       */
  145.      if (buflen > (int) (strlen(buf) + 1)) {
  146.          Strcpy(suppliedbuf, buf);
  147.          return suppliedbuf;
  148.      } else
  149.          return err_ret;
  150.  }
  151.  

build_plselection_prompt

  1.  char *
  2.  build_plselection_prompt(buf, buflen, rolenum, racenum, gendnum, alignnum)
  3.  char *buf;
  4.  int buflen, rolenum, racenum, gendnum, alignnum;
  5.  {
  6.      const char *defprompt = "Shall I pick a character for you? [ynaq] ";
  7.      int num_post_attribs = 0;
  8.      char tmpbuf[BUFSZ], *p;
  9.  
  10.      if (buflen < QBUFSZ)
  11.          return (char *) defprompt;
  12.  
  13.      Strcpy(tmpbuf, "Shall I pick ");
  14.      if (racenum != ROLE_NONE || validrole(rolenum))
  15.          Strcat(tmpbuf, "your ");
  16.      else {
  17.          Strcat(tmpbuf, "a ");
  18.      }
  19.      /* <your> */
  20.  
  21.      (void) root_plselection_prompt(eos(tmpbuf), buflen - strlen(tmpbuf),
  22.                                     rolenum, racenum, gendnum, alignnum);
  23.      Sprintf(buf, "%s", s_suffix(tmpbuf));
  24.      /* don't bother splitting caveman/cavewoman or priest/priestess
  25.         in order to apply possessive suffix to both halves, but do
  26.         change "priest/priestess'" to "priest/priestess's" */
  27.      if ((p = strstri(buf, "priest/priestess'")) != 0
  28.          && p[sizeof "priest/priestess'" - sizeof ""] == '\0')
  29.          strkitten(buf, 's');
  30.  
  31.      /* buf should now be:
  32.       *    <your lawful female gnomish cavewoman's>
  33.       * || <your lawful female gnome's>
  34.       * || <your lawful female character's>
  35.       *
  36.       * Now append the post attributes to it
  37.       */
  38.      num_post_attribs = post_attribs;
  39.      if (post_attribs) {
  40.          if (pa[BP_RACE]) {
  41.              (void) promptsep(eos(buf), num_post_attribs);
  42.              Strcat(buf, "race");
  43.          }
  44.          if (pa[BP_ROLE]) {
  45.              (void) promptsep(eos(buf), num_post_attribs);
  46.              Strcat(buf, "role");
  47.          }
  48.          if (pa[BP_GEND]) {
  49.              (void) promptsep(eos(buf), num_post_attribs);
  50.              Strcat(buf, "gender");
  51.          }
  52.          if (pa[BP_ALIGN]) {
  53.              (void) promptsep(eos(buf), num_post_attribs);
  54.              Strcat(buf, "alignment");
  55.          }
  56.      }
  57.      Strcat(buf, " for you? [ynaq] ");
  58.      return buf;
  59.  }
  60.  
  61.  #undef BP_ALIGN
  62.  #undef BP_GEND
  63.  #undef BP_RACE
  64.  #undef BP_ROLE
  65.  #undef NUM_BP
  66.  

plnamesuffix

  1.  void
  2.  plnamesuffix()
  3.  {
  4.      char *sptr, *eptr;
  5.      int i;
  6.  
  7.  #ifdef GENERIC_USERNAMES
  8.      {
  9.          /* some generic user names will be ignored in favor of prompting */
  10.          const char *uptr = GENERIC_USERNAMES;
  11.  
  12.          i = (int) strlen(plname);
  13.          if ((sptr = strstri(uptr, plname)) != 0
  14.              && (sptr == uptr || sptr[-1] == ' ')
  15.              && (sptr[i] == ' ' || sptr[i] == '\0'))
  16.              *plname = '\0'; /* call askname() */
  17.      }
  18.  #endif
  19.  
  20.      do {
  21.          if (!*plname)
  22.              askname(); /* fill plname[] if necessary */
  23.  
  24.          /* Look for tokens delimited by '-' */
  25.          if ((eptr = index(plname, '-')) != (char *) 0)
  26.              *eptr++ = '\0';
  27.          while (eptr) {
  28.              /* Isolate the next token */
  29.              sptr = eptr;
  30.              if ((eptr = index(sptr, '-')) != (char *) 0)
  31.                  *eptr++ = '\0';
  32.  
  33.              /* Try to match it to something */
  34.              if ((i = str2role(sptr)) != ROLE_NONE)
  35.                  flags.initrole = i;
  36.              else if ((i = str2race(sptr)) != ROLE_NONE)
  37.                  flags.initrace = i;
  38.              else if ((i = str2gend(sptr)) != ROLE_NONE)
  39.                  flags.initgend = i;
  40.              else if ((i = str2align(sptr)) != ROLE_NONE)
  41.                  flags.initalign = i;
  42.          }
  43.      } while (!*plname);
  44.  
  45.      /* commas in the plname confuse the record file, convert to spaces */
  46.      for (sptr = plname; *sptr; sptr++) {
  47.          if (*sptr == ',')
  48.              *sptr = ' ';
  49.      }
  50.  }
  51.  

role_selection_prolog

  1.  /* show current settings for name, role, race, gender, and alignment
  2.     in the specified window */
  3.  void
  4.  role_selection_prolog(which, where)
  5.  int which;
  6.  winid where;
  7.  {
  8.      static const char NEARDATA choosing[] = " choosing now",
  9.                                 not_yet[] = " not yet specified",
  10.                                 rand_choice[] = " random";
  11.      char buf[BUFSZ];
  12.      int r, c, g, a, allowmask;
  13.  
  14.      r = flags.initrole;
  15.      c = flags.initrace;
  16.      g = flags.initgend;
  17.      a = flags.initalign;
  18.      if (r >= 0) {
  19.          allowmask = roles[r].allow;
  20.          if ((allowmask & ROLE_RACEMASK) == MH_HUMAN)
  21.              c = 0; /* races[human] */
  22.          else if (c >= 0 && !(allowmask & ROLE_RACEMASK & races[c].allow))
  23.              c = ROLE_RANDOM;
  24.          if ((allowmask & ROLE_GENDMASK) == ROLE_MALE)
  25.              g = 0; /* role forces male (hypothetical) */
  26.          else if ((allowmask & ROLE_GENDMASK) == ROLE_FEMALE)
  27.              g = 1; /* role forces female (valkyrie) */
  28.          if ((allowmask & ROLE_ALIGNMASK) == AM_LAWFUL)
  29.              a = 0; /* aligns[lawful] */
  30.          else if ((allowmask & ROLE_ALIGNMASK) == AM_NEUTRAL)
  31.              a = 1; /* aligns[neutral] */
  32.          else if ((allowmask & ROLE_ALIGNMASK) == AM_CHAOTIC)
  33.              a = 2; /* alings[chaotic] */
  34.      }
  35.      if (c >= 0) {
  36.          allowmask = races[c].allow;
  37.          if ((allowmask & ROLE_ALIGNMASK) == AM_LAWFUL)
  38.              a = 0; /* aligns[lawful] */
  39.          else if ((allowmask & ROLE_ALIGNMASK) == AM_NEUTRAL)
  40.              a = 1; /* aligns[neutral] */
  41.          else if ((allowmask & ROLE_ALIGNMASK) == AM_CHAOTIC)
  42.              a = 2; /* alings[chaotic] */
  43.          /* [c never forces gender] */
  44.      }
  45.      /* [g and a don't constrain anything sufficiently
  46.         to narrow something done to a single choice] */
  47.  
  48.      Sprintf(buf, "%12s ", "name:");
  49.      Strcat(buf, (which == RS_NAME) ? choosing : !*plname ? not_yet : plname);
  50.      putstr(where, 0, buf);
  51.      Sprintf(buf, "%12s ", "role:");
  52.      Strcat(buf, (which == RS_ROLE) ? choosing : (r == ROLE_NONE)
  53.                                                      ? not_yet
  54.                                                      : (r == ROLE_RANDOM)
  55.                                                            ? rand_choice
  56.                                                            : roles[r].name.m);
  57.      if (r >= 0 && roles[r].name.f) {
  58.          /* distinct female name [caveman/cavewoman, priest/priestess] */
  59.          if (g == 1)
  60.              /* female specified; replace male role name with female one */
  61.              Sprintf(index(buf, ':'), ": %s", roles[r].name.f);
  62.          else if (g < 0)
  63.              /* gender unspecified; append slash and female role name */
  64.              Sprintf(eos(buf), "/%s", roles[r].name.f);
  65.      }
  66.      putstr(where, 0, buf);
  67.      Sprintf(buf, "%12s ", "race:");
  68.      Strcat(buf, (which == RS_RACE) ? choosing : (c == ROLE_NONE)
  69.                                                      ? not_yet
  70.                                                      : (c == ROLE_RANDOM)
  71.                                                            ? rand_choice
  72.                                                            : races[c].noun);
  73.      putstr(where, 0, buf);
  74.      Sprintf(buf, "%12s ", "gender:");
  75.      Strcat(buf, (which == RS_GENDER) ? choosing : (g == ROLE_NONE)
  76.                                                        ? not_yet
  77.                                                        : (g == ROLE_RANDOM)
  78.                                                              ? rand_choice
  79.                                                              : genders[g].adj);
  80.      putstr(where, 0, buf);
  81.      Sprintf(buf, "%12s ", "alignment:");
  82.      Strcat(buf, (which == RS_ALGNMNT) ? choosing : (a == ROLE_NONE)
  83.                                                         ? not_yet
  84.                                                         : (a == ROLE_RANDOM)
  85.                                                               ? rand_choice
  86.                                                               : aligns[a].adj);
  87.      putstr(where, 0, buf);
  88.  }
  89.  

role_menu_extra

  1.  /* add a "pick alignment first"-type entry to the specified menu */
  2.  void
  3.  role_menu_extra(which, where)
  4.  int which;
  5.  winid where;
  6.  {
  7.      static NEARDATA const char RS_menu_let[] = {
  8.          '=',  /* name */
  9.          '?',  /* role */
  10.          '/',  /* race */
  11.          '\"', /* gender */
  12.          '[',  /* alignment */
  13.      };
  14.      anything any;
  15.      char buf[BUFSZ];
  16.      const char *what = 0, *constrainer = 0, *forcedvalue = 0;
  17.      int f = 0, r, c, g, a, i, allowmask;
  18.  
  19.      r = flags.initrole;
  20.      c = flags.initrace;
  21.      switch (which) {
  22.      case RS_NAME:
  23.          what = "name";
  24.          break;
  25.      case RS_ROLE:
  26.          what = "role";
  27.          f = r;
  28.          for (i = 0; i < SIZE(roles); ++i)
  29.              if (i != f && !filter.roles[i])
  30.                  break;
  31.          if (i == SIZE(roles)) {
  32.              constrainer = "filter";
  33.              forcedvalue = "role";
  34.          }
  35.          break;
  36.      case RS_RACE:
  37.          what = "race";
  38.          f = flags.initrace;
  39.          c = ROLE_NONE; /* override player's setting */
  40.          if (r >= 0) {
  41.              allowmask = roles[r].allow & ROLE_RACEMASK;
  42.              if (allowmask == MH_HUMAN)
  43.                  c = 0; /* races[human] */
  44.              if (c >= 0) {
  45.                  constrainer = "role";
  46.                  forcedvalue = races[c].noun;
  47.              } else if (f >= 0
  48.                         && (allowmask & ~filter.mask) == races[f].selfmask) {
  49.                  /* if there is only one race choice available due to user
  50.                     options disallowing others, race menu entry is disabled */
  51.                  constrainer = "filter";
  52.                  forcedvalue = "race";
  53.              }
  54.          }
  55.          break;
  56.      case RS_GENDER:
  57.          what = "gender";
  58.          f = flags.initgend;
  59.          g = ROLE_NONE;
  60.          if (r >= 0) {
  61.              allowmask = roles[r].allow & ROLE_GENDMASK;
  62.              if (allowmask == ROLE_MALE)
  63.                  g = 0; /* genders[male] */
  64.              else if (allowmask == ROLE_FEMALE)
  65.                  g = 1; /* genders[female] */
  66.              if (g >= 0) {
  67.                  constrainer = "role";
  68.                  forcedvalue = genders[g].adj;
  69.              } else if (f >= 0
  70.                         && (allowmask & ~filter.mask) == genders[f].allow) {
  71.                  /* if there is only one gender choice available due to user
  72.                     options disallowing other, gender menu entry is disabled */
  73.                  constrainer = "filter";
  74.                  forcedvalue = "gender";
  75.              }
  76.          }
  77.          break;
  78.      case RS_ALGNMNT:
  79.          what = "alignment";
  80.          f = flags.initalign;
  81.          a = ROLE_NONE;
  82.          if (r >= 0) {
  83.              allowmask = roles[r].allow & ROLE_ALIGNMASK;
  84.              if (allowmask == AM_LAWFUL)
  85.                  a = 0; /* aligns[lawful] */
  86.              else if (allowmask == AM_NEUTRAL)
  87.                  a = 1; /* aligns[neutral] */
  88.              else if (allowmask == AM_CHAOTIC)
  89.                  a = 2; /* aligns[chaotic] */
  90.              if (a >= 0)
  91.                  constrainer = "role";
  92.          }
  93.          if (c >= 0 && !constrainer) {
  94.              allowmask = races[c].allow & ROLE_ALIGNMASK;
  95.              if (allowmask == AM_LAWFUL)
  96.                  a = 0; /* aligns[lawful] */
  97.              else if (allowmask == AM_NEUTRAL)
  98.                  a = 1; /* aligns[neutral] */
  99.              else if (allowmask == AM_CHAOTIC)
  100.                  a = 2; /* aligns[chaotic] */
  101.              if (a >= 0)
  102.                  constrainer = "race";
  103.          }
  104.          if (f >= 0 && !constrainer
  105.              && (ROLE_ALIGNMASK & ~filter.mask) == aligns[f].allow) {
  106.              /* if there is only one alignment choice available due to user
  107.                 options disallowing others, algn menu entry is disabled */
  108.              constrainer = "filter";
  109.              forcedvalue = "alignment";
  110.          }
  111.          if (a >= 0)
  112.              forcedvalue = aligns[a].adj;
  113.          break;
  114.      }
  115.  
  116.      any = zeroany; /* zero out all bits */
  117.      if (constrainer) {
  118.          any.a_int = 0;
  119.          /* use four spaces of padding to fake a grayed out menu choice */
  120.          Sprintf(buf, "%4s%s forces %s", "", constrainer, forcedvalue);
  121.          add_menu(where, NO_GLYPH, &any, ' ', 0, ATR_NONE, buf,
  122.                   MENU_UNSELECTED);
  123.      } else if (what) {
  124.          any.a_int = RS_menu_arg(which);
  125.          Sprintf(buf, "Pick%s %s first", (f >= 0) ? " another" : "", what);
  126.          add_menu(where, NO_GLYPH, &any, RS_menu_let[which], 0, ATR_NONE, buf,
  127.                   MENU_UNSELECTED);
  128.      } else if (which == RS_filter) {
  129.          any.a_int = RS_menu_arg(RS_filter);
  130.          add_menu(where, NO_GLYPH, &any, '~', 0, ATR_NONE,
  131.                   "Reset role/race/&c filtering", MENU_UNSELECTED);
  132.      } else if (which == ROLE_RANDOM) {
  133.          any.a_int = ROLE_RANDOM;
  134.          add_menu(where, NO_GLYPH, &any, '*', 0, ATR_NONE, "Random",
  135.                   MENU_UNSELECTED);
  136.      } else if (which == ROLE_NONE) {
  137.          any.a_int = ROLE_NONE;
  138.          add_menu(where, NO_GLYPH, &any, 'q', 0, ATR_NONE, "Quit",
  139.                   MENU_UNSELECTED);
  140.      } else {
  141.          impossible("role_menu_extra: bad arg (%d)", which);
  142.      }
  143.  }
  144.  

role_init

  1.  /*
  2.   *      Special setup modifications here:
  3.   *
  4.   *      Unfortunately, this is going to have to be done
  5.   *      on each newgame or restore, because you lose the permonst mods
  6.   *      across a save/restore.  :-)
  7.   *
  8.   *      1 - The Rogue Leader is the Tourist Nemesis.
  9.   *      2 - Priests start with a random alignment - convert the leader and
  10.   *          guardians here.
  11.   *      3 - Priests also get their of deities from a randomly chosen role.
  12.   *      4 - [obsolete] Elves can have one of two different leaders,
  13.   *          but can't work it out here because it requires hacking the
  14.   *          level file data (see sp_lev.c).
  15.   *
  16.   * This code also replaces quest_init().
  17.   */
  18.  void
  19.  role_init()
  20.  {
  21.      int alignmnt;
  22.      struct permonst *pm;
  23.  
  24.      /* Strip the role letter out of the player name.
  25.       * This is included for backwards compatibility.
  26.       */
  27.      plnamesuffix();
  28.  
  29.      /* Check for a valid role.  Try flags.initrole first. */
  30.      if (!validrole(flags.initrole)) {
  31.          /* Try the player letter second */
  32.          if ((flags.initrole = str2role(pl_character)) < 0)
  33.              /* None specified; pick a random role */
  34.              flags.initrole = randrole_filtered();
  35.      }
  36.  
  37.      /* We now have a valid role index.  Copy the role name back. */
  38.      /* This should become OBSOLETE */
  39.      Strcpy(pl_character, roles[flags.initrole].name.m);
  40.      pl_character[PL_CSIZ - 1] = '\0';
  41.  
  42.      /* Check for a valid race */
  43.      if (!validrace(flags.initrole, flags.initrace))
  44.          flags.initrace = randrace(flags.initrole);
  45.  
  46.      /* Check for a valid gender.  If new game, check both initgend
  47.       * and female.  On restore, assume flags.female is correct. */
  48.      if (flags.pantheon == -1) { /* new game */
  49.          if (!validgend(flags.initrole, flags.initrace, flags.female))
  50.              flags.female = !flags.female;
  51.      }
  52.      if (!validgend(flags.initrole, flags.initrace, flags.initgend))
  53.          /* Note that there is no way to check for an unspecified gender. */
  54.          flags.initgend = flags.female;
  55.  
  56.      /* Check for a valid alignment */
  57.      if (!validalign(flags.initrole, flags.initrace, flags.initalign))
  58.          /* Pick a random alignment */
  59.          flags.initalign = randalign(flags.initrole, flags.initrace);
  60.      alignmnt = aligns[flags.initalign].value;
  61.  
  62.      /* Initialize urole and urace */
  63.      urole = roles[flags.initrole];
  64.      urace = races[flags.initrace];
  65.  
  66.      /* Fix up the quest leader */
  67.      if (urole.ldrnum != NON_PM) {
  68.          pm = &mons[urole.ldrnum];
  69.          pm->msound = MS_LEADER;
  70.          pm->mflags2 |= (M2_PEACEFUL);
  71.          pm->mflags3 |= M3_CLOSE;
  72.          pm->maligntyp = alignmnt * 3;
  73.          /* if gender is random, we choose it now instead of waiting
  74.             until the leader monster is created */
  75.          quest_status.ldrgend =
  76.              is_neuter(pm) ? 2 : is_female(pm) ? 1 : is_male(pm)
  77.                                                          ? 0
  78.                                                          : (rn2(100) < 50);
  79.      }
  80.  
  81.      /* Fix up the quest guardians */
  82.      if (urole.guardnum != NON_PM) {
  83.          pm = &mons[urole.guardnum];
  84.          pm->mflags2 |= (M2_PEACEFUL);
  85.          pm->maligntyp = alignmnt * 3;
  86.      }
  87.  
  88.      /* Fix up the quest nemesis */
  89.      if (urole.neminum != NON_PM) {
  90.          pm = &mons[urole.neminum];
  91.          pm->msound = MS_NEMESIS;
  92.          pm->mflags2 &= ~(M2_PEACEFUL);
  93.          pm->mflags2 |= (M2_NASTY | M2_STALK | M2_HOSTILE);
  94.          pm->mflags3 &= ~(M3_CLOSE);
  95.          pm->mflags3 |= M3_WANTSARTI | M3_WAITFORU;
  96.          /* if gender is random, we choose it now instead of waiting
  97.             until the nemesis monster is created */
  98.          quest_status.nemgend = is_neuter(pm) ? 2 : is_female(pm) ? 1
  99.                                     : is_male(pm) ? 0 : (rn2(100) < 50);
  100.      }
  101.  
  102.      /* Fix up the god names */
  103.      if (flags.pantheon == -1) {             /* new game */
  104.          flags.pantheon = flags.initrole;    /* use own gods */
  105.          while (!roles[flags.pantheon].lgod) /* unless they're missing */
  106.              flags.pantheon = randrole();
  107.      }
  108.      if (!urole.lgod) {
  109.          urole.lgod = roles[flags.pantheon].lgod;
  110.          urole.ngod = roles[flags.pantheon].ngod;
  111.          urole.cgod = roles[flags.pantheon].cgod;
  112.      }
  113.      /* 0 or 1; no gods are neuter, nor is gender randomized */
  114.      quest_status.godgend = !strcmpi(align_gtitle(alignmnt), "goddess");
  115.  
  116.      /* Fix up infravision */
  117.      if (mons[urace.malenum].mflags3 & M3_INFRAVISION) {
  118.          /* although an infravision intrinsic is possible, infravision
  119.           * is purely a property of the physical race.  This means that we
  120.           * must put the infravision flag in the player's current race
  121.           * (either that or have separate permonst entries for
  122.           * elven/non-elven members of each class).  The side effect is that
  123.           * all NPCs of that class will have (probably bogus) infravision,
  124.           * but since infravision has no effect for NPCs anyway we can
  125.           * ignore this.
  126.           */
  127.          mons[urole.malenum].mflags3 |= M3_INFRAVISION;
  128.          if (urole.femalenum != NON_PM)
  129.              mons[urole.femalenum].mflags3 |= M3_INFRAVISION;
  130.      }
  131.  
  132.      /* Artifacts are fixed in hack_artifacts() */
  133.  
  134.      /* Success! */
  135.      return;
  136.  }
  137.  

Hello

  1.  const char *
  2.  Hello(mtmp)
  3.  struct monst *mtmp;
  4.  {
  5.      switch (Role_switch) {
  6.      case PM_KNIGHT:
  7.          return "Salutations"; /* Olde English */
  8.      case PM_SAMURAI:
  9.          return (mtmp && mtmp->data == &mons[PM_SHOPKEEPER])
  10.                      ? "Irasshaimase"
  11.                      : "Konnichi wa"; /* Japanese */
  12.      case PM_TOURIST:
  13.          return "Aloha"; /* Hawaiian */
  14.      case PM_VALKYRIE:
  15.          return
  16.  #ifdef MAIL
  17.                 (mtmp && mtmp->data == &mons[PM_MAIL_DAEMON]) ? "Hallo" :
  18.  #endif
  19.                 "Velkommen"; /* Norse */
  20.      default:
  21.          return "Hello";
  22.      }
  23.  }
  24.  

Goodbye

  1.  const char *
  2.  Goodbye()
  3.  {
  4.      switch (Role_switch) {
  5.      case PM_KNIGHT:
  6.          return "Fare thee well"; /* Olde English */
  7.      case PM_SAMURAI:
  8.          return "Sayonara"; /* Japanese */
  9.      case PM_TOURIST:
  10.          return "Aloha"; /* Hawaiian */
  11.      case PM_VALKYRIE:
  12.          return "Farvel"; /* Norse */
  13.      default:
  14.          return "Goodbye";
  15.      }
  16.  }
  17.  
  18.  /* role.c */