/* NetHack 3.7 u_init.c $NHDT-Date: 1621131203 2021/05/16 02:13:23 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.75 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2017. */ /* NetHack may be freely redistributed. See license for details. */ #include "hack.h" struct trobj { short trotyp; schar trspe; char trclass; Bitfield(trquan, 6); Bitfield(trbless, 2); }; static void ini_inv(struct trobj *); static void knows_object(int); static void knows_class(char); static boolean restricted_spell_discipline(int); #define UNDEF_TYP 0 #define UNDEF_SPE '\177' #define UNDEF_BLESS 2 /* * Initial inventory for the various roles. */ static struct trobj Archeologist[] = { /* if adventure has a name... idea from tan@uvm-gen */ { BULLWHIP, 2, WEAPON_CLASS, 1, UNDEF_BLESS }, { LEATHER_JACKET, 0, ARMOR_CLASS, 1, UNDEF_BLESS }, { FEDORA, 0, ARMOR_CLASS, 1, UNDEF_BLESS }, { FOOD_RATION, 0, FOOD_CLASS, 3, 0 }, { PICK_AXE, UNDEF_SPE, TOOL_CLASS, 1, UNDEF_BLESS }, { TINNING_KIT, UNDEF_SPE, TOOL_CLASS, 1, UNDEF_BLESS }, { TOUCHSTONE, 0, GEM_CLASS, 1, 0 }, { SACK, 0, TOOL_CLASS, 1, 0 }, { 0, 0, 0, 0, 0 } }; static struct trobj Barbarian[] = { #define B_MAJOR 0 /* two-handed sword or battle-axe */ #define B_MINOR 1 /* matched with axe or short sword */ { TWO_HANDED_SWORD, 0, WEAPON_CLASS, 1, UNDEF_BLESS }, { AXE, 0, WEAPON_CLASS, 1, UNDEF_BLESS }, { RING_MAIL, 0, ARMOR_CLASS, 1, UNDEF_BLESS }, { FOOD_RATION, 0, FOOD_CLASS, 1, 0 }, { 0, 0, 0, 0, 0 } }; static struct trobj Cave_man[] = { #define C_AMMO 2 { CLUB, 1, WEAPON_CLASS, 1, UNDEF_BLESS }, { SLING, 2, WEAPON_CLASS, 1, UNDEF_BLESS }, { FLINT, 0, GEM_CLASS, 15, UNDEF_BLESS }, /* quan is variable */ { ROCK, 0, GEM_CLASS, 3, 0 }, /* yields 18..33 */ { LEATHER_ARMOR, 0, ARMOR_CLASS, 1, UNDEF_BLESS }, { 0, 0, 0, 0, 0 } }; static struct trobj Healer[] = { { SCALPEL, 0, WEAPON_CLASS, 1, UNDEF_BLESS }, { LEATHER_GLOVES, 1, ARMOR_CLASS, 1, UNDEF_BLESS }, { STETHOSCOPE, 0, TOOL_CLASS, 1, 0 }, { POT_HEALING, 0, POTION_CLASS, 4, UNDEF_BLESS }, { POT_EXTRA_HEALING, 0, POTION_CLASS, 4, UNDEF_BLESS }, { WAN_SLEEP, UNDEF_SPE, WAND_CLASS, 1, UNDEF_BLESS }, /* always blessed, so it's guaranteed readable */ { SPE_HEALING, 0, SPBOOK_CLASS, 1, 1 }, { SPE_EXTRA_HEALING, 0, SPBOOK_CLASS, 1, 1 }, { SPE_STONE_TO_FLESH, 0, SPBOOK_CLASS, 1, 1 }, { APPLE, 0, FOOD_CLASS, 5, 0 }, { 0, 0, 0, 0, 0 } }; static struct trobj Knight[] = { { LONG_SWORD, 1, WEAPON_CLASS, 1, UNDEF_BLESS }, { LANCE, 1, WEAPON_CLASS, 1, UNDEF_BLESS }, { RING_MAIL, 1, ARMOR_CLASS, 1, UNDEF_BLESS }, { HELMET, 0, ARMOR_CLASS, 1, UNDEF_BLESS }, { SMALL_SHIELD, 0, ARMOR_CLASS, 1, UNDEF_BLESS }, { LEATHER_GLOVES, 0, ARMOR_CLASS, 1, UNDEF_BLESS }, { APPLE, 0, FOOD_CLASS, 10, 0 }, { CARROT, 0, FOOD_CLASS, 10, 0 }, { 0, 0, 0, 0, 0 } }; static struct trobj Monk[] = { #define M_BOOK 2 { LEATHER_GLOVES, 2, ARMOR_CLASS, 1, UNDEF_BLESS }, { ROBE, 1, ARMOR_CLASS, 1, UNDEF_BLESS }, { UNDEF_TYP, UNDEF_SPE, SPBOOK_CLASS, 1, 1 }, { UNDEF_TYP, UNDEF_SPE, SCROLL_CLASS, 1, UNDEF_BLESS }, { POT_HEALING, 0, POTION_CLASS, 3, UNDEF_BLESS }, { FOOD_RATION, 0, FOOD_CLASS, 3, 0 }, { APPLE, 0, FOOD_CLASS, 5, UNDEF_BLESS }, { ORANGE, 0, FOOD_CLASS, 5, UNDEF_BLESS }, /* Yes, we know fortune cookies aren't really from China. They were * invented by George Jung in Los Angeles, California, USA in 1916. */ { FORTUNE_COOKIE, 0, FOOD_CLASS, 3, UNDEF_BLESS }, { 0, 0, 0, 0, 0 } }; static struct trobj Priest[] = { { MACE, 1, WEAPON_CLASS, 1, 1 }, { ROBE, 0, ARMOR_CLASS, 1, UNDEF_BLESS }, { SMALL_SHIELD, 0, ARMOR_CLASS, 1, UNDEF_BLESS }, { POT_WATER, 0, POTION_CLASS, 4, 1 }, /* holy water */ { CLOVE_OF_GARLIC, 0, FOOD_CLASS, 1, 0 }, { SPRIG_OF_WOLFSBANE, 0, FOOD_CLASS, 1, 0 }, { UNDEF_TYP, UNDEF_SPE, SPBOOK_CLASS, 2, UNDEF_BLESS }, { 0, 0, 0, 0, 0 } }; static struct trobj Ranger[] = { #define RAN_BOW 1 #define RAN_TWO_ARROWS 2 #define RAN_ZERO_ARROWS 3 { DAGGER, 1, WEAPON_CLASS, 1, UNDEF_BLESS }, { BOW, 1, WEAPON_CLASS, 1, UNDEF_BLESS }, { ARROW, 2, WEAPON_CLASS, 50, UNDEF_BLESS }, { ARROW, 0, WEAPON_CLASS, 30, UNDEF_BLESS }, { CLOAK_OF_DISPLACEMENT, 2, ARMOR_CLASS, 1, UNDEF_BLESS }, { CRAM_RATION, 0, FOOD_CLASS, 4, 0 }, { 0, 0, 0, 0, 0 } }; static struct trobj Rogue[] = { #define R_DAGGERS 1 { SHORT_SWORD, 0, WEAPON_CLASS, 1, UNDEF_BLESS }, { DAGGER, 0, WEAPON_CLASS, 10, 0 }, /* quan is variable */ { LEATHER_ARMOR, 1, ARMOR_CLASS, 1, UNDEF_BLESS }, { POT_SICKNESS, 0, POTION_CLASS, 1, 0 }, { LOCK_PICK, 0, TOOL_CLASS, 1, 0 }, { SACK, 0, TOOL_CLASS, 1, 0 }, { 0, 0, 0, 0, 0 } }; static struct trobj Samurai[] = { #define S_ARROWS 3 { KATANA, 0, WEAPON_CLASS, 1, UNDEF_BLESS }, { SHORT_SWORD, 0, WEAPON_CLASS, 1, UNDEF_BLESS }, /* wakizashi */ { YUMI, 0, WEAPON_CLASS, 1, UNDEF_BLESS }, { YA, 0, WEAPON_CLASS, 25, UNDEF_BLESS }, /* variable quan */ { SPLINT_MAIL, 0, ARMOR_CLASS, 1, UNDEF_BLESS }, { 0, 0, 0, 0, 0 } }; static struct trobj Tourist[] = { #define T_DARTS 0 { DART, 2, WEAPON_CLASS, 25, UNDEF_BLESS }, /* quan is variable */ { UNDEF_TYP, UNDEF_SPE, FOOD_CLASS, 10, 0 }, { POT_EXTRA_HEALING, 0, POTION_CLASS, 2, UNDEF_BLESS }, { SCR_MAGIC_MAPPING, 0, SCROLL_CLASS, 4, UNDEF_BLESS }, { HAWAIIAN_SHIRT, 0, ARMOR_CLASS, 1, UNDEF_BLESS }, { EXPENSIVE_CAMERA, UNDEF_SPE, TOOL_CLASS, 1, 0 }, { CREDIT_CARD, 0, TOOL_CLASS, 1, 0 }, { 0, 0, 0, 0, 0 } }; static struct trobj Valkyrie[] = { { SPEAR, 1, WEAPON_CLASS, 1, UNDEF_BLESS }, { DAGGER, 0, WEAPON_CLASS, 1, UNDEF_BLESS }, { SMALL_SHIELD, 3, ARMOR_CLASS, 1, UNDEF_BLESS }, { FOOD_RATION, 0, FOOD_CLASS, 1, 0 }, { 0, 0, 0, 0, 0 } }; static struct trobj Wizard[] = { #define W_MULTSTART 2 #define W_MULTEND 6 { QUARTERSTAFF, 1, WEAPON_CLASS, 1, 1 }, { CLOAK_OF_MAGIC_RESISTANCE, 0, ARMOR_CLASS, 1, UNDEF_BLESS }, { UNDEF_TYP, UNDEF_SPE, WAND_CLASS, 1, UNDEF_BLESS }, { UNDEF_TYP, UNDEF_SPE, RING_CLASS, 2, UNDEF_BLESS }, { UNDEF_TYP, UNDEF_SPE, POTION_CLASS, 3, UNDEF_BLESS }, { UNDEF_TYP, UNDEF_SPE, SCROLL_CLASS, 3, UNDEF_BLESS }, { SPE_FORCE_BOLT, 0, SPBOOK_CLASS, 1, 1 }, { UNDEF_TYP, UNDEF_SPE, SPBOOK_CLASS, 1, UNDEF_BLESS }, { 0, 0, 0, 0, 0 } }; /* * Optional extra inventory items. */ static struct trobj Tinopener[] = { { TIN_OPENER, 0, TOOL_CLASS, 1, 0 }, { 0, 0, 0, 0, 0 } }; static struct trobj Magicmarker[] = { { MAGIC_MARKER, UNDEF_SPE, TOOL_CLASS, 1, 0 }, { 0, 0, 0, 0, 0 } }; static struct trobj Lamp[] = { { OIL_LAMP, 1, TOOL_CLASS, 1, 0 }, { 0, 0, 0, 0, 0 } }; static struct trobj Blindfold[] = { { BLINDFOLD, 0, TOOL_CLASS, 1, 0 }, { 0, 0, 0, 0, 0 } }; static struct trobj Instrument[] = { { WOODEN_FLUTE, 0, TOOL_CLASS, 1, 0 }, { 0, 0, 0, 0, 0 } }; static struct trobj Xtra_food[] = { { UNDEF_TYP, UNDEF_SPE, FOOD_CLASS, 2, 0 }, { 0, 0, 0, 0, 0 } }; static struct trobj Leash[] = { { LEASH, 0, TOOL_CLASS, 1, 0 }, { 0, 0, 0, 0, 0 } }; static struct trobj Towel[] = { { TOWEL, 0, TOOL_CLASS, 1, 0 }, { 0, 0, 0, 0, 0 } }; static struct trobj Wishing[] = { { WAN_WISHING, 3, WAND_CLASS, 1, 0 }, { 0, 0, 0, 0, 0 } }; static struct trobj Money[] = { { GOLD_PIECE, 0, COIN_CLASS, 1, 0 }, { 0, 0, 0, 0, 0 } }; /* race-based substitutions for initial inventory; the weaker cloak for elven rangers is intentional--they shoot better */ static struct inv_sub { short race_pm, item_otyp, subs_otyp; } inv_subs[] = { { PM_ELF, DAGGER, ELVEN_DAGGER }, { PM_ELF, SPEAR, ELVEN_SPEAR }, { PM_ELF, SHORT_SWORD, ELVEN_SHORT_SWORD }, { PM_ELF, BOW, ELVEN_BOW }, { PM_ELF, ARROW, ELVEN_ARROW }, { PM_ELF, HELMET, ELVEN_LEATHER_HELM }, /* { PM_ELF, SMALL_SHIELD, ELVEN_SHIELD }, */ { PM_ELF, CLOAK_OF_DISPLACEMENT, ELVEN_CLOAK }, { PM_ELF, CRAM_RATION, LEMBAS_WAFER }, { PM_ORC, DAGGER, ORCISH_DAGGER }, { PM_ORC, SPEAR, ORCISH_SPEAR }, { PM_ORC, SHORT_SWORD, ORCISH_SHORT_SWORD }, { PM_ORC, BOW, ORCISH_BOW }, { PM_ORC, ARROW, ORCISH_ARROW }, { PM_ORC, HELMET, ORCISH_HELM }, { PM_ORC, SMALL_SHIELD, ORCISH_SHIELD }, { PM_ORC, RING_MAIL, ORCISH_RING_MAIL }, { PM_ORC, CHAIN_MAIL, ORCISH_CHAIN_MAIL }, { PM_ORC, CRAM_RATION, TRIPE_RATION }, { PM_ORC, LEMBAS_WAFER, TRIPE_RATION }, { PM_DWARF, SPEAR, DWARVISH_SPEAR }, { PM_DWARF, SHORT_SWORD, DWARVISH_SHORT_SWORD }, { PM_DWARF, HELMET, DWARVISH_IRON_HELM }, /* { PM_DWARF, SMALL_SHIELD, DWARVISH_ROUNDSHIELD }, */ /* { PM_DWARF, PICK_AXE, DWARVISH_MATTOCK }, */ { PM_DWARF, LEMBAS_WAFER, CRAM_RATION }, { PM_GNOME, BOW, CROSSBOW }, { PM_GNOME, ARROW, CROSSBOW_BOLT }, { NON_PM, STRANGE_OBJECT, STRANGE_OBJECT } }; static const struct def_skill Skill_A[] = { { P_DAGGER, P_BASIC }, { P_KNIFE, P_BASIC }, { P_PICK_AXE, P_EXPERT }, { P_SHORT_SWORD, P_BASIC }, { P_SCIMITAR, P_SKILLED }, { P_SABER, P_EXPERT }, { P_CLUB, P_SKILLED }, { P_QUARTERSTAFF, P_SKILLED }, { P_SLING, P_SKILLED }, { P_DART, P_BASIC }, { P_BOOMERANG, P_EXPERT }, { P_WHIP, P_EXPERT }, { P_UNICORN_HORN, P_SKILLED }, { P_ATTACK_SPELL, P_BASIC }, { P_HEALING_SPELL, P_BASIC }, { P_DIVINATION_SPELL, P_EXPERT }, { P_MATTER_SPELL, P_BASIC }, { P_RIDING, P_BASIC }, { P_TWO_WEAPON_COMBAT, P_BASIC }, { P_BARE_HANDED_COMBAT, P_EXPERT }, { P_NONE, 0 } }; static const struct def_skill Skill_B[] = { { P_DAGGER, P_BASIC }, { P_AXE, P_EXPERT }, { P_PICK_AXE, P_SKILLED }, { P_SHORT_SWORD, P_EXPERT }, { P_BROAD_SWORD, P_SKILLED }, { P_LONG_SWORD, P_SKILLED }, { P_TWO_HANDED_SWORD, P_EXPERT }, { P_SCIMITAR, P_SKILLED }, { P_SABER, P_BASIC }, { P_CLUB, P_SKILLED }, { P_MACE, P_SKILLED }, { P_MORNING_STAR, P_SKILLED }, { P_FLAIL, P_BASIC }, { P_HAMMER, P_EXPERT }, { P_QUARTERSTAFF, P_BASIC }, { P_SPEAR, P_SKILLED }, { P_TRIDENT, P_SKILLED }, { P_BOW, P_BASIC }, { P_ATTACK_SPELL, P_BASIC }, { P_ESCAPE_SPELL, P_BASIC }, /* special spell is haste self */ { P_RIDING, P_BASIC }, { P_TWO_WEAPON_COMBAT, P_BASIC }, { P_BARE_HANDED_COMBAT, P_MASTER }, { P_NONE, 0 } }; static const struct def_skill Skill_C[] = { { P_DAGGER, P_BASIC }, { P_KNIFE, P_SKILLED }, { P_AXE, P_SKILLED }, { P_PICK_AXE, P_BASIC }, { P_CLUB, P_EXPERT }, { P_MACE, P_EXPERT }, { P_MORNING_STAR, P_BASIC }, { P_FLAIL, P_SKILLED }, { P_HAMMER, P_SKILLED }, { P_QUARTERSTAFF, P_EXPERT }, { P_POLEARMS, P_SKILLED }, { P_SPEAR, P_EXPERT }, { P_TRIDENT, P_SKILLED }, { P_BOW, P_SKILLED }, { P_SLING, P_EXPERT }, { P_ATTACK_SPELL, P_BASIC }, { P_MATTER_SPELL, P_SKILLED }, { P_BOOMERANG, P_EXPERT }, { P_UNICORN_HORN, P_BASIC }, { P_BARE_HANDED_COMBAT, P_MASTER }, { P_NONE, 0 } }; static const struct def_skill Skill_H[] = { { P_DAGGER, P_SKILLED }, { P_KNIFE, P_EXPERT }, { P_SHORT_SWORD, P_SKILLED }, { P_SCIMITAR, P_BASIC }, { P_SABER, P_BASIC }, { P_CLUB, P_SKILLED }, { P_MACE, P_BASIC }, { P_QUARTERSTAFF, P_EXPERT }, { P_POLEARMS, P_BASIC }, { P_SPEAR, P_BASIC }, { P_TRIDENT, P_BASIC }, { P_SLING, P_SKILLED }, { P_DART, P_EXPERT }, { P_SHURIKEN, P_SKILLED }, { P_UNICORN_HORN, P_EXPERT }, { P_HEALING_SPELL, P_EXPERT }, { P_BARE_HANDED_COMBAT, P_BASIC }, { P_NONE, 0 } }; static const struct def_skill Skill_K[] = { { P_DAGGER, P_BASIC }, { P_KNIFE, P_BASIC }, { P_AXE, P_SKILLED }, { P_PICK_AXE, P_BASIC }, { P_SHORT_SWORD, P_SKILLED }, { P_BROAD_SWORD, P_SKILLED }, { P_LONG_SWORD, P_EXPERT }, { P_TWO_HANDED_SWORD, P_SKILLED }, { P_SCIMITAR, P_BASIC }, { P_SABER, P_SKILLED }, { P_CLUB, P_BASIC }, { P_MACE, P_SKILLED }, { P_MORNING_STAR, P_SKILLED }, { P_FLAIL, P_BASIC }, { P_HAMMER, P_BASIC }, { P_POLEARMS, P_SKILLED }, { P_SPEAR, P_SKILLED }, { P_TRIDENT, P_BASIC }, { P_LANCE, P_EXPERT }, { P_BOW, P_BASIC }, { P_CROSSBOW, P_SKILLED }, { P_ATTACK_SPELL, P_SKILLED }, { P_HEALING_SPELL, P_SKILLED }, { P_CLERIC_SPELL, P_SKILLED }, { P_RIDING, P_EXPERT }, { P_TWO_WEAPON_COMBAT, P_SKILLED }, { P_BARE_HANDED_COMBAT, P_EXPERT }, { P_NONE, 0 } }; static const struct def_skill Skill_Mon[] = { { P_QUARTERSTAFF, P_BASIC }, { P_SPEAR, P_BASIC }, { P_CROSSBOW, P_BASIC }, { P_SHURIKEN, P_BASIC }, { P_ATTACK_SPELL, P_BASIC }, { P_HEALING_SPELL, P_EXPERT }, { P_DIVINATION_SPELL, P_BASIC }, { P_ENCHANTMENT_SPELL, P_BASIC }, { P_CLERIC_SPELL, P_SKILLED }, { P_ESCAPE_SPELL, P_SKILLED }, { P_MATTER_SPELL, P_BASIC }, { P_MARTIAL_ARTS, P_GRAND_MASTER }, { P_NONE, 0 } }; static const struct def_skill Skill_P[] = { { P_CLUB, P_EXPERT }, { P_MACE, P_EXPERT }, { P_MORNING_STAR, P_EXPERT }, { P_FLAIL, P_EXPERT }, { P_HAMMER, P_EXPERT }, { P_QUARTERSTAFF, P_EXPERT }, { P_POLEARMS, P_SKILLED }, { P_SPEAR, P_SKILLED }, { P_TRIDENT, P_SKILLED }, { P_LANCE, P_BASIC }, { P_BOW, P_BASIC }, { P_SLING, P_BASIC }, { P_CROSSBOW, P_BASIC }, { P_DART, P_BASIC }, { P_SHURIKEN, P_BASIC }, { P_BOOMERANG, P_BASIC }, { P_UNICORN_HORN, P_SKILLED }, { P_HEALING_SPELL, P_EXPERT }, { P_DIVINATION_SPELL, P_EXPERT }, { P_CLERIC_SPELL, P_EXPERT }, { P_BARE_HANDED_COMBAT, P_BASIC }, { P_NONE, 0 } }; static const struct def_skill Skill_R[] = { { P_DAGGER, P_EXPERT }, { P_KNIFE, P_EXPERT }, { P_SHORT_SWORD, P_EXPERT }, { P_BROAD_SWORD, P_SKILLED }, { P_LONG_SWORD, P_SKILLED }, { P_TWO_HANDED_SWORD, P_BASIC }, { P_SCIMITAR, P_SKILLED }, { P_SABER, P_SKILLED }, { P_CLUB, P_SKILLED }, { P_MACE, P_SKILLED }, { P_MORNING_STAR, P_BASIC }, { P_FLAIL, P_BASIC }, { P_HAMMER, P_BASIC }, { P_POLEARMS, P_BASIC }, { P_SPEAR, P_BASIC }, { P_CROSSBOW, P_EXPERT }, { P_DART, P_EXPERT }, { P_SHURIKEN, P_SKILLED }, { P_DIVINATION_SPELL, P_SKILLED }, { P_ESCAPE_SPELL, P_SKILLED }, { P_MATTER_SPELL, P_SKILLED }, { P_RIDING, P_BASIC }, { P_TWO_WEAPON_COMBAT, P_EXPERT }, { P_BARE_HANDED_COMBAT, P_EXPERT }, { P_NONE, 0 } }; static const struct def_skill Skill_Ran[] = { { P_DAGGER, P_EXPERT }, { P_KNIFE, P_SKILLED }, { P_AXE, P_SKILLED }, { P_PICK_AXE, P_BASIC }, { P_SHORT_SWORD, P_BASIC }, { P_MORNING_STAR, P_BASIC }, { P_FLAIL, P_SKILLED }, { P_HAMMER, P_BASIC }, { P_QUARTERSTAFF, P_BASIC }, { P_POLEARMS, P_SKILLED }, { P_SPEAR, P_EXPERT }, { P_TRIDENT, P_BASIC }, { P_BOW, P_EXPERT }, { P_SLING, P_EXPERT }, { P_CROSSBOW, P_EXPERT }, { P_DART, P_EXPERT }, { P_SHURIKEN, P_SKILLED }, { P_BOOMERANG, P_EXPERT }, { P_WHIP, P_BASIC }, { P_HEALING_SPELL, P_BASIC }, { P_DIVINATION_SPELL, P_EXPERT }, { P_ESCAPE_SPELL, P_BASIC }, { P_RIDING, P_BASIC }, { P_BARE_HANDED_COMBAT, P_BASIC }, { P_NONE, 0 } }; static const struct def_skill Skill_S[] = { { P_DAGGER, P_BASIC }, { P_KNIFE, P_SKILLED }, { P_SHORT_SWORD, P_EXPERT }, { P_BROAD_SWORD, P_SKILLED }, { P_LONG_SWORD, P_EXPERT }, { P_TWO_HANDED_SWORD, P_EXPERT }, { P_SCIMITAR, P_BASIC }, { P_SABER, P_BASIC }, { P_FLAIL, P_SKILLED }, { P_QUARTERSTAFF, P_BASIC }, { P_POLEARMS, P_SKILLED }, { P_SPEAR, P_SKILLED }, { P_LANCE, P_SKILLED }, { P_BOW, P_EXPERT }, { P_SHURIKEN, P_EXPERT }, { P_ATTACK_SPELL, P_BASIC }, { P_DIVINATION_SPELL, P_BASIC }, /* special spell is clairvoyance */ { P_CLERIC_SPELL, P_SKILLED }, { P_RIDING, P_SKILLED }, { P_TWO_WEAPON_COMBAT, P_EXPERT }, { P_MARTIAL_ARTS, P_MASTER }, { P_NONE, 0 } }; static const struct def_skill Skill_T[] = { { P_DAGGER, P_EXPERT }, { P_KNIFE, P_SKILLED }, { P_AXE, P_BASIC }, { P_PICK_AXE, P_BASIC }, { P_SHORT_SWORD, P_EXPERT }, { P_BROAD_SWORD, P_BASIC }, { P_LONG_SWORD, P_BASIC }, { P_TWO_HANDED_SWORD, P_BASIC }, { P_SCIMITAR, P_SKILLED }, { P_SABER, P_SKILLED }, { P_MACE, P_BASIC }, { P_MORNING_STAR, P_BASIC }, { P_FLAIL, P_BASIC }, { P_HAMMER, P_BASIC }, { P_QUARTERSTAFF, P_BASIC }, { P_POLEARMS, P_BASIC }, { P_SPEAR, P_BASIC }, { P_TRIDENT, P_BASIC }, { P_LANCE, P_BASIC }, { P_BOW, P_BASIC }, { P_SLING, P_BASIC }, { P_CROSSBOW, P_BASIC }, { P_DART, P_EXPERT }, { P_SHURIKEN, P_BASIC }, { P_BOOMERANG, P_BASIC }, { P_WHIP, P_BASIC }, { P_UNICORN_HORN, P_SKILLED }, { P_DIVINATION_SPELL, P_BASIC }, { P_ENCHANTMENT_SPELL, P_BASIC }, { P_ESCAPE_SPELL, P_SKILLED }, { P_RIDING, P_BASIC }, { P_TWO_WEAPON_COMBAT, P_SKILLED }, { P_BARE_HANDED_COMBAT, P_SKILLED }, { P_NONE, 0 } }; static const struct def_skill Skill_V[] = { { P_DAGGER, P_EXPERT }, { P_AXE, P_EXPERT }, { P_PICK_AXE, P_SKILLED }, { P_SHORT_SWORD, P_SKILLED }, { P_BROAD_SWORD, P_SKILLED }, { P_LONG_SWORD, P_EXPERT }, { P_TWO_HANDED_SWORD, P_EXPERT }, { P_SCIMITAR, P_BASIC }, { P_SABER, P_BASIC }, { P_HAMMER, P_EXPERT }, { P_QUARTERSTAFF, P_BASIC }, { P_POLEARMS, P_SKILLED }, { P_SPEAR, P_EXPERT }, { P_TRIDENT, P_BASIC }, { P_LANCE, P_SKILLED }, { P_SLING, P_BASIC }, { P_ATTACK_SPELL, P_BASIC }, { P_ESCAPE_SPELL, P_BASIC }, { P_RIDING, P_SKILLED }, { P_TWO_WEAPON_COMBAT, P_SKILLED }, { P_BARE_HANDED_COMBAT, P_EXPERT }, { P_NONE, 0 } }; static const struct def_skill Skill_W[] = { { P_DAGGER, P_EXPERT }, { P_KNIFE, P_SKILLED }, { P_AXE, P_SKILLED }, { P_SHORT_SWORD, P_BASIC }, { P_CLUB, P_SKILLED }, { P_MACE, P_BASIC }, { P_QUARTERSTAFF, P_EXPERT }, { P_POLEARMS, P_SKILLED }, { P_SPEAR, P_BASIC }, { P_TRIDENT, P_BASIC }, { P_SLING, P_SKILLED }, { P_DART, P_EXPERT }, { P_SHURIKEN, P_BASIC }, { P_ATTACK_SPELL, P_EXPERT }, { P_HEALING_SPELL, P_SKILLED }, { P_DIVINATION_SPELL, P_EXPERT }, { P_ENCHANTMENT_SPELL, P_SKILLED }, { P_CLERIC_SPELL, P_SKILLED }, { P_ESCAPE_SPELL, P_EXPERT }, { P_MATTER_SPELL, P_EXPERT }, { P_RIDING, P_BASIC }, { P_BARE_HANDED_COMBAT, P_BASIC }, { P_NONE, 0 } }; static void knows_object(int obj) { discover_object(obj, TRUE, FALSE); objects[obj].oc_pre_discovered = 1; /* not a "discovery" */ } /* Know ordinary (non-magical) objects of a certain class, like all gems except the loadstone and luckstone. */ static void knows_class(char sym) { struct obj odummy, *o; int ct; odummy = cg.zeroobj; odummy.oclass = sym; o = &odummy; /* for use in various obj.h macros */ /* * Note: the exceptions here can be bypassed if necessary by * calling knows_object() directly. So an elven ranger, * for example, knows all elven weapons despite the bow, * arrow, and spear limitation below. */ for (ct = g.bases[(uchar) sym]; ct < g.bases[(uchar) sym + 1]; ct++) { /* not flagged as magic but shouldn't be pre-discovered */ if (ct == CORNUTHAUM || ct == DUNCE_CAP) continue; if (sym == WEAPON_CLASS) { odummy.otyp = ct; /* update 'o' */ /* arbitrary: only knights and samurai recognize polearms */ if ((!Role_if(PM_KNIGHT) && !Role_if(PM_SAMURAI)) && is_pole(o)) continue; /* rangers know all launchers (bows, &c), ammo (arrows, &c), and spears regardless of race/species, but not other weapons */ if (Role_if(PM_RANGER) && (!is_launcher(o) && !is_ammo(o) && !is_spear(o))) continue; /* rogues know daggers, regardless of racial variations */ if (Role_if(PM_ROGUE) && (objects[o->otyp].oc_skill != P_DAGGER)) continue; } if (objects[ct].oc_class == sym && !objects[ct].oc_magic) knows_object(ct); } } void u_init(void) { register int i; struct u_roleplay tmpuroleplay = u.uroleplay; /* set by rcfile options */ flags.female = flags.initgend; flags.beginner = 1; /* zero u, including pointer values -- * necessary when aborting from a failed restore */ (void) memset((genericptr_t) &u, 0, sizeof(u)); u.ustuck = (struct monst *) 0; (void) memset((genericptr_t) &ubirthday, 0, sizeof(ubirthday)); (void) memset((genericptr_t) &urealtime, 0, sizeof(urealtime)); u.uroleplay = tmpuroleplay; /* restore options set via rcfile */ #if 0 /* documentation of more zero values as desirable */ u.usick_cause[0] = 0; u.uluck = u.moreluck = 0; uarmu = 0; uarm = uarmc = uarmh = uarms = uarmg = uarmf = 0; uwep = uball = uchain = uleft = uright = 0; uswapwep = uquiver = 0; u.twoweap = FALSE; /* bypass set_twoweap() */ u.ublessed = 0; /* not worthy yet */ u.ugangr = 0; /* gods not angry */ u.ugifts = 0; /* no divine gifts bestowed */ u.uevent.uhand_of_elbereth = 0; u.uevent.uheard_tune = 0; u.uevent.uopened_dbridge = 0; u.uevent.udemigod = 0; /* not a demi-god yet... */ u.udg_cnt = 0; u.mh = u.mhmax = u.mtimedone = 0; u.uz.dnum = u.uz0.dnum = 0; u.utotype = UTOTYPE_NONE; #endif /* 0 */ u.uz.dlevel = 1; u.uz0.dlevel = 0; u.utolev = u.uz; u.umoved = FALSE; u.umortality = 0; u.ugrave_arise = NON_PM; u.umonnum = u.umonster = g.urole.mnum; u.ulycn = NON_PM; set_uasmon(); u.ulevel = 0; /* set up some of the initial attributes */ u.uhp = u.uhpmax = u.uhppeak = newhp(); u.uen = u.uenmax = u.uenpeak = newpw(); u.uspellprot = 0; adjabil(0, 1); u.ulevel = u.ulevelmax = 1; init_uhunger(); for (i = 0; i <= MAXSPELL; i++) g.spl_book[i].sp_id = NO_SPELL; u.ublesscnt = 300; /* no prayers just yet */ u.ualignbase[A_CURRENT] = u.ualignbase[A_ORIGINAL] = u.ualign.type = aligns[flags.initalign].value; #if defined(BSD) && !defined(POSIX_TYPES) (void) time((long *) &ubirthday); #else (void) time(&ubirthday); #endif /* * For now, everyone starts out with a night vision range of 1 and * their xray range disabled. */ u.nv_range = 1; u.xray_range = -1; /*** Role-specific initializations ***/ switch (Role_switch) { /* rn2(100) > 50 necessary for some choices because some * random number generators are bad enough to seriously * skew the results if we use rn2(2)... --KAA */ case PM_ARCHEOLOGIST: ini_inv(Archeologist); if (!rn2(10)) ini_inv(Tinopener); else if (!rn2(4)) ini_inv(Lamp); else if (!rn2(10)) ini_inv(Magicmarker); knows_object(SACK); knows_object(TOUCHSTONE); skill_init(Skill_A); break; case PM_BARBARIAN: if (rn2(100) >= 50) { /* see above comment */ Barbarian[B_MAJOR].trotyp = BATTLE_AXE; Barbarian[B_MINOR].trotyp = SHORT_SWORD; } ini_inv(Barbarian); if (!rn2(6)) ini_inv(Lamp); knows_class(WEAPON_CLASS); /* excluding polearms */ knows_class(ARMOR_CLASS); skill_init(Skill_B); break; case PM_CAVE_DWELLER: Cave_man[C_AMMO].trquan = rn1(11, 10); /* 10..20 */ ini_inv(Cave_man); skill_init(Skill_C); break; case PM_HEALER: u.umoney0 = rn1(1000, 1001); ini_inv(Healer); if (!rn2(25)) ini_inv(Lamp); knows_object(POT_FULL_HEALING); skill_init(Skill_H); break; case PM_KNIGHT: ini_inv(Knight); knows_class(WEAPON_CLASS); /* all weapons */ knows_class(ARMOR_CLASS); /* give knights chess-like mobility--idea from wooledge@..cwru.edu */ HJumping |= FROMOUTSIDE; skill_init(Skill_K); break; case PM_MONK: { static short M_spell[] = { SPE_HEALING, SPE_PROTECTION, SPE_CONFUSE_MONSTER }; Monk[M_BOOK].trotyp = M_spell[rn2(90) / 30]; /* [0..2] */ ini_inv(Monk); if (!rn2(5)) ini_inv(Magicmarker); else if (!rn2(10)) ini_inv(Lamp); knows_class(ARMOR_CLASS); /* sufficiently martial-arts oriented item to ignore language issue */ knows_object(SHURIKEN); skill_init(Skill_Mon); break; } case PM_CLERIC: ini_inv(Priest); if (!rn2(10)) ini_inv(Magicmarker); else if (!rn2(10)) ini_inv(Lamp); knows_object(POT_WATER); skill_init(Skill_P); /* KMH, conduct -- * Some may claim that this isn't agnostic, since they * are literally "priests" and they have holy water. * But we don't count it as such. Purists can always * avoid playing priests and/or confirm another player's * role in their YAAP. */ break; case PM_RANGER: Ranger[RAN_TWO_ARROWS].trquan = rn1(10, 50); Ranger[RAN_ZERO_ARROWS].trquan = rn1(10, 30); ini_inv(Ranger); knows_class(WEAPON_CLASS); /* bows, arrows, spears only */ skill_init(Skill_Ran); break; case PM_ROGUE: Rogue[R_DAGGERS].trquan = rn1(10, 6); u.umoney0 = 0; ini_inv(Rogue); if (!rn2(5)) ini_inv(Blindfold); knows_object(SACK); knows_class(WEAPON_CLASS); /* daggers only */ skill_init(Skill_R); break; case PM_SAMURAI: Samurai[S_ARROWS].trquan = rn1(20, 26); ini_inv(Samurai); if (!rn2(5)) ini_inv(Blindfold); knows_class(WEAPON_CLASS); /* all weapons */ knows_class(ARMOR_CLASS); skill_init(Skill_S); break; case PM_TOURIST: Tourist[T_DARTS].trquan = rn1(20, 21); u.umoney0 = rnd(1000); ini_inv(Tourist); if (!rn2(25)) ini_inv(Tinopener); else if (!rn2(25)) ini_inv(Leash); else if (!rn2(25)) ini_inv(Towel); else if (!rn2(25)) ini_inv(Magicmarker); skill_init(Skill_T); break; case PM_VALKYRIE: ini_inv(Valkyrie); if (!rn2(6)) ini_inv(Lamp); knows_class(WEAPON_CLASS); /* excludes polearms */ knows_class(ARMOR_CLASS); skill_init(Skill_V); break; case PM_WIZARD: ini_inv(Wizard); if (!rn2(5)) ini_inv(Magicmarker); if (!rn2(5)) ini_inv(Blindfold); skill_init(Skill_W); break; default: /* impossible */ break; } /*** Race-specific initializations ***/ switch (Race_switch) { case PM_HUMAN: /* Nothing special */ break; case PM_ELF: /* * Elves are people of music and song, or they are warriors. * Non-warriors get an instrument. We use a kludge to * get only non-magic instruments. */ if (Role_if(PM_CLERIC) || Role_if(PM_WIZARD)) { static int trotyp[] = { WOODEN_FLUTE, TOOLED_HORN, WOODEN_HARP, BELL, BUGLE, LEATHER_DRUM }; Instrument[0].trotyp = trotyp[rn2(SIZE(trotyp))]; ini_inv(Instrument); } /* Elves can recognize all elvish objects */ knows_object(ELVEN_SHORT_SWORD); knows_object(ELVEN_ARROW); knows_object(ELVEN_BOW); knows_object(ELVEN_SPEAR); knows_object(ELVEN_DAGGER); knows_object(ELVEN_BROADSWORD); knows_object(ELVEN_MITHRIL_COAT); knows_object(ELVEN_LEATHER_HELM); knows_object(ELVEN_SHIELD); knows_object(ELVEN_BOOTS); knows_object(ELVEN_CLOAK); break; case PM_DWARF: /* Dwarves can recognize all dwarvish objects */ knows_object(DWARVISH_SPEAR); knows_object(DWARVISH_SHORT_SWORD); knows_object(DWARVISH_MATTOCK); knows_object(DWARVISH_IRON_HELM); knows_object(DWARVISH_MITHRIL_COAT); knows_object(DWARVISH_CLOAK); knows_object(DWARVISH_ROUNDSHIELD); break; case PM_GNOME: break; case PM_ORC: /* compensate for generally inferior equipment */ if (!Role_if(PM_WIZARD)) ini_inv(Xtra_food); /* Orcs can recognize all orcish objects */ knows_object(ORCISH_SHORT_SWORD); knows_object(ORCISH_ARROW); knows_object(ORCISH_BOW); knows_object(ORCISH_SPEAR); knows_object(ORCISH_DAGGER); knows_object(ORCISH_CHAIN_MAIL); knows_object(ORCISH_RING_MAIL); knows_object(ORCISH_HELM); knows_object(ORCISH_SHIELD); knows_object(URUK_HAI_SHIELD); knows_object(ORCISH_CLOAK); break; default: /* impossible */ break; } if (discover) ini_inv(Wishing); if (wizard) read_wizkit(); if (u.umoney0) ini_inv(Money); u.umoney0 += hidden_gold(TRUE); /* in case sack has gold in it */ find_ac(); /* get initial ac value */ init_attr(75); /* init attribute values */ max_rank_sz(); /* set max str size for class ranks */ /* * Do we really need this? */ for (i = 0; i < A_MAX; i++) if (!rn2(20)) { register int xd = rn2(7) - 2; /* biased variation */ (void) adjattrib(i, xd, TRUE); if (ABASE(i) < AMAX(i)) AMAX(i) = ABASE(i); } /* make sure you can carry all you have - especially for Tourists */ while (inv_weight() > 0) { if (adjattrib(A_STR, 1, TRUE)) continue; if (adjattrib(A_CON, 1, TRUE)) continue; /* only get here when didn't boost strength or constitution */ break; } /* If we have at least one spell, force starting Pw to be enough, so hero can cast the level 1 spell they should have */ if (num_spells() && (u.uenmax < SPELL_LEV_PW(1))) u.uen = u.uenmax = u.uenpeak = u.ueninc[u.ulevel] = SPELL_LEV_PW(1); return; } /* skills aren't initialized, so we use the role-specific skill lists */ static boolean restricted_spell_discipline(int otyp) { const struct def_skill *skills; int this_skill = spell_skilltype(otyp); switch (Role_switch) { case PM_ARCHEOLOGIST: skills = Skill_A; break; case PM_BARBARIAN: skills = Skill_B; break; case PM_CAVE_DWELLER: skills = Skill_C; break; case PM_HEALER: skills = Skill_H; break; case PM_KNIGHT: skills = Skill_K; break; case PM_MONK: skills = Skill_Mon; break; case PM_CLERIC: skills = Skill_P; break; case PM_RANGER: skills = Skill_Ran; break; case PM_ROGUE: skills = Skill_R; break; case PM_SAMURAI: skills = Skill_S; break; case PM_TOURIST: skills = Skill_T; break; case PM_VALKYRIE: skills = Skill_V; break; case PM_WIZARD: skills = Skill_W; break; default: skills = 0; /* lint suppression */ break; } while (skills && skills->skill != P_NONE) { if (skills->skill == this_skill) return FALSE; ++skills; } return TRUE; } static void ini_inv(struct trobj *trop) { struct obj *obj; int otyp, i; boolean got_sp1 = FALSE; /* got a level 1 spellbook? */ while (trop->trclass) { otyp = (int) trop->trotyp; if (otyp != UNDEF_TYP) { obj = mksobj(otyp, TRUE, FALSE); } else { /* UNDEF_TYP */ int trycnt = 0; /* * For random objects, do not create certain overly powerful * items: wand of wishing, ring of levitation, or the * polymorph/polymorph control combination. Specific objects, * i.e. the discovery wishing, are still OK. * Also, don't get a couple of really useless items. (Note: * punishment isn't "useless". Some players who start out with * one will immediately read it and use the iron ball as a * weapon.) */ obj = mkobj(trop->trclass, FALSE); otyp = obj->otyp; while (otyp == WAN_WISHING || otyp == g.nocreate || otyp == g.nocreate2 || otyp == g.nocreate3 || otyp == g.nocreate4 || otyp == RIN_LEVITATION /* 'useless' items */ || otyp == POT_HALLUCINATION || otyp == POT_ACID || otyp == SCR_AMNESIA || otyp == SCR_FIRE || otyp == SCR_BLANK_PAPER || otyp == SPE_BLANK_PAPER || otyp == RIN_AGGRAVATE_MONSTER || otyp == RIN_HUNGER || otyp == WAN_NOTHING /* orcs start with poison resistance */ || (otyp == RIN_POISON_RESISTANCE && Race_if(PM_ORC)) /* Monks don't use weapons */ || (otyp == SCR_ENCHANT_WEAPON && Role_if(PM_MONK)) /* wizard patch -- they already have one */ || (otyp == SPE_FORCE_BOLT && Role_if(PM_WIZARD)) /* powerful spells are either useless to low level players or unbalancing; also spells in restricted skill categories */ || (obj->oclass == SPBOOK_CLASS && (objects[otyp].oc_level > (got_sp1 ? 3 : 1) || restricted_spell_discipline(otyp))) || otyp == SPE_NOVEL) { dealloc_obj(obj); obj = mkobj(trop->trclass, FALSE); otyp = obj->otyp; if (++trycnt > 1000) break; } /* Don't start with +0 or negative rings */ if (objects[otyp].oc_charged && obj->spe <= 0) obj->spe = rne(3); /* Heavily relies on the fact that 1) we create wands * before rings, 2) that we create rings before * spellbooks, and that 3) not more than 1 object of a * particular symbol is to be prohibited. (For more * objects, we need more nocreate variables...) */ switch (otyp) { case WAN_POLYMORPH: case RIN_POLYMORPH: case POT_POLYMORPH: g.nocreate = RIN_POLYMORPH_CONTROL; break; case RIN_POLYMORPH_CONTROL: g.nocreate = RIN_POLYMORPH; g.nocreate2 = SPE_POLYMORPH; g.nocreate3 = POT_POLYMORPH; } /* Don't have 2 of the same ring or spellbook */ if (obj->oclass == RING_CLASS || obj->oclass == SPBOOK_CLASS) g.nocreate4 = otyp; } if (g.urace.mnum != PM_HUMAN) { /* substitute race-specific items; this used to be in the 'if (otyp != UNDEF_TYP) { }' block above, but then substitutions didn't occur for randomly generated items (particularly food) which have racial substitutes */ for (i = 0; inv_subs[i].race_pm != NON_PM; ++i) if (inv_subs[i].race_pm == g.urace.mnum && otyp == inv_subs[i].item_otyp) { debugpline3("ini_inv: substituting %s for %s%s", OBJ_NAME(objects[inv_subs[i].subs_otyp]), (trop->trotyp == UNDEF_TYP) ? "random " : "", OBJ_NAME(objects[otyp])); otyp = obj->otyp = inv_subs[i].subs_otyp; break; } } /* nudist gets no armor */ if (u.uroleplay.nudist && obj->oclass == ARMOR_CLASS) { dealloc_obj(obj); trop++; continue; } if (trop->trclass == COIN_CLASS) { /* no "blessed" or "identified" money */ obj->quan = u.umoney0; } else { if (objects[otyp].oc_uses_known) obj->known = 1; obj->dknown = obj->bknown = obj->rknown = 1; if (Is_container(obj) || obj->otyp == STATUE) { obj->cknown = obj->lknown = 1; obj->otrapped = 0; } obj->cursed = 0; if (obj->opoisoned && u.ualign.type != A_CHAOTIC) obj->opoisoned = 0; if (obj->oclass == WEAPON_CLASS || obj->oclass == TOOL_CLASS) { obj->quan = (long) trop->trquan; trop->trquan = 1; } else if (obj->oclass == GEM_CLASS && is_graystone(obj) && obj->otyp != FLINT) { obj->quan = 1L; } if (trop->trspe != UNDEF_SPE) obj->spe = trop->trspe; if (trop->trbless != UNDEF_BLESS) obj->blessed = trop->trbless; } /* defined after setting otyp+quan + blessedness */ obj->owt = weight(obj); obj = addinv(obj); /* Make the type known if necessary */ if (OBJ_DESCR(objects[otyp]) && obj->known) discover_object(otyp, TRUE, FALSE); if (otyp == OIL_LAMP) discover_object(POT_OIL, TRUE, FALSE); if (obj->oclass == ARMOR_CLASS) { if (is_shield(obj) && !uarms && !(uwep && bimanual(uwep))) { setworn(obj, W_ARMS); /* Prior to 3.6.2 this used to unset uswapwep if it was set, but wearing a shield doesn't prevent having an alternate weapon ready to swap with the primary; just make sure we aren't two-weaponing (academic; no one starts that way) */ set_twoweap(FALSE); /* u.twoweap = FALSE */ } else if (is_helmet(obj) && !uarmh) setworn(obj, W_ARMH); else if (is_gloves(obj) && !uarmg) setworn(obj, W_ARMG); else if (is_shirt(obj) && !uarmu) setworn(obj, W_ARMU); else if (is_cloak(obj) && !uarmc) setworn(obj, W_ARMC); else if (is_boots(obj) && !uarmf) setworn(obj, W_ARMF); else if (is_suit(obj) && !uarm) setworn(obj, W_ARM); } if (obj->oclass == WEAPON_CLASS || is_weptool(obj) || otyp == TIN_OPENER || otyp == FLINT || otyp == ROCK) { if (is_ammo(obj) || is_missile(obj)) { if (!uquiver) setuqwep(obj); } else if (!uwep && (!uarms || !bimanual(obj))) { setuwep(obj); } else if (!uswapwep) { setuswapwep(obj); } } if (obj->oclass == SPBOOK_CLASS && obj->otyp != SPE_BLANK_PAPER) initialspell(obj); /* First spellbook should be level 1 - did we get it? */ if (obj->oclass == SPBOOK_CLASS && objects[obj->otyp].oc_level == 1) got_sp1 = TRUE; if (--trop->trquan) continue; /* make a similar object */ trop++; } } /*u_init.c*/