From 394fb595f6d03fa9d266ed28726975e0b59bc798 Mon Sep 17 00:00:00 2001 From: Robert Vollmert Date: Sat, 24 Oct 2009 12:42:13 +0200 Subject: Extract newgame character restrictions from newgame.cc. The functions in the new ng-restr.cc are "pure": They don't access global state; data is passed in via the new and incomplete newgame_def. Eventually, new_game should be split into something like newgame_def choose_game(); that doesn't access "you", and void setup_game(newgame_def); that sets up the player. Also get rid of player_size in favour of player::body_size. Rename player_size_type to size_part_type since it's not really player-specific (used in actor::body_size). Move parts of player_genus, player::has_claws, body_size out into species.cc. --- crawl-ref/source/abl-show.cc | 1 + crawl-ref/source/actor.h | 2 +- crawl-ref/source/describe.cc | 6 +- crawl-ref/source/effects.cc | 2 +- crawl-ref/source/enum.h | 2 +- crawl-ref/source/fight.cc | 6 +- crawl-ref/source/item_use.cc | 16 +- crawl-ref/source/itemname.cc | 6 +- crawl-ref/source/itemprop.cc | 4 +- crawl-ref/source/jobs.cc | 4 + crawl-ref/source/jobs.h | 3 + crawl-ref/source/makefile.obj | 1 + crawl-ref/source/mon-util.cc | 2 +- crawl-ref/source/monster.h | 2 +- crawl-ref/source/newgame.cc | 1051 +++-------------------------------------- crawl-ref/source/newgame.h | 11 + crawl-ref/source/ng-restr.cc | 929 ++++++++++++++++++++++++++++++++++++ crawl-ref/source/ng-restr.h | 25 + crawl-ref/source/player.cc | 107 +---- crawl-ref/source/player.h | 12 +- crawl-ref/source/species.cc | 92 +++- crawl-ref/source/species.h | 18 + 22 files changed, 1195 insertions(+), 1107 deletions(-) create mode 100644 crawl-ref/source/ng-restr.cc create mode 100644 crawl-ref/source/ng-restr.h (limited to 'crawl-ref') diff --git a/crawl-ref/source/abl-show.cc b/crawl-ref/source/abl-show.cc index 11dd60326f..e1499f2650 100644 --- a/crawl-ref/source/abl-show.cc +++ b/crawl-ref/source/abl-show.cc @@ -45,6 +45,7 @@ #include "player.h" #include "religion.h" #include "skills.h" +#include "species.h" #include "spl-cast.h" #include "spl-util.h" #include "spells1.h" diff --git a/crawl-ref/source/actor.h b/crawl-ref/source/actor.h index e3dde04ff3..c6d97b95f1 100644 --- a/crawl-ref/source/actor.h +++ b/crawl-ref/source/actor.h @@ -38,7 +38,7 @@ public: virtual bool is_habitable_feat(dungeon_feature_type actual_grid) const = 0; bool is_habitable(const coord_def &pos) const; - virtual size_type body_size(int psize = PSIZE_TORSO, + virtual size_type body_size(size_part_type psize = PSIZE_TORSO, bool base = false) const = 0; virtual int body_weight() const = 0; virtual int total_weight() const = 0; diff --git a/crawl-ref/source/describe.cc b/crawl-ref/source/describe.cc index 24588197ac..bcce934a0c 100644 --- a/crawl-ref/source/describe.cc +++ b/crawl-ref/source/describe.cc @@ -884,7 +884,7 @@ static std::string _describe_weapon(const item_def &item, bool verbose) if (!launcher) { - switch (hands_reqd(item, player_size())) + switch (hands_reqd(item, you.body_size())) { case HANDS_ONE: description += "It is a one handed weapon"; @@ -914,8 +914,8 @@ static std::string _describe_weapon(const item_def &item, bool verbose) description += ", and it is better for the dexterous"; description += "."; } - if (player_size(PSIZE_BODY) < SIZE_MEDIUM - && !check_weapon_wieldable_size(item, player_size(PSIZE_BODY))) + if (you.body_size(PSIZE_BODY) < SIZE_MEDIUM + && !check_weapon_wieldable_size(item, you.body_size(PSIZE_BODY))) { description += "$It is too large for you to wield."; } diff --git a/crawl-ref/source/effects.cc b/crawl-ref/source/effects.cc index c6307295bc..029d3a62b6 100644 --- a/crawl-ref/source/effects.cc +++ b/crawl-ref/source/effects.cc @@ -1178,7 +1178,7 @@ static bool _try_give_mundane_armour(item_def &arm) else { const item_def weapon = you.inv[you.equip[EQ_WEAPON]]; - const hands_reqd_type hand = hands_reqd(weapon, player_size()); + const hands_reqd_type hand = hands_reqd(weapon, you.body_size()); if (hand == HANDS_TWO || item_is_rod(weapon) || is_range_weapon(weapon)) { diff --git a/crawl-ref/source/enum.h b/crawl-ref/source/enum.h index 25f8840f68..888f492272 100644 --- a/crawl-ref/source/enum.h +++ b/crawl-ref/source/enum.h @@ -2471,7 +2471,7 @@ enum orb_type ORB_ZOT // 0 }; -enum player_size_type +enum size_part_type { PSIZE_BODY, // entire body size -- used for EV/size of target PSIZE_TORSO, // torso only (hybrids -- size of parts that use equip) diff --git a/crawl-ref/source/fight.cc b/crawl-ref/source/fight.cc index a1d8bbc914..f544fbd617 100644 --- a/crawl-ref/source/fight.cc +++ b/crawl-ref/source/fight.cc @@ -4014,7 +4014,7 @@ int melee_attack::player_calc_base_weapon_damage() // effective. if (shield && weapon->base_type == OBJ_WEAPONS && weapon_skill(*weapon) == SK_STAVES - && hands_reqd(*weapon, player_size()) == HANDS_HALF) + && hands_reqd(*weapon, you.body_size()) == HANDS_HALF) { damage /= 2; } @@ -5479,7 +5479,7 @@ int weapon_str_weight( object_class_type wpn_class, int wpn_type ) int ret; const int wpn_skill = weapon_skill( wpn_class, wpn_type ); - const int hands = hands_reqd( wpn_class, wpn_type, player_size() ); + const int hands = hands_reqd( wpn_class, wpn_type, you.body_size() ); // These are low values, because we'll be adding some bonus to the // larger weapons later. Remember also that 1-1/2-hand weapons get @@ -5550,7 +5550,7 @@ static inline int player_weapon_str_weight() int ret = weapon_str_weight(weapon->base_type, weapon->sub_type); - if (hands_reqd(*weapon, player_size()) == HANDS_HALF && !you.shield()) + if (hands_reqd(*weapon, you.body_size()) == HANDS_HALF && !you.shield()) ret += 1; return (ret); diff --git a/crawl-ref/source/item_use.cc b/crawl-ref/source/item_use.cc index 21aa961a73..700a828473 100644 --- a/crawl-ref/source/item_use.cc +++ b/crawl-ref/source/item_use.cc @@ -129,15 +129,15 @@ bool can_wield(item_def *weapon, bool say_reason, return (true); } - if (player_size(PSIZE_TORSO) < SIZE_LARGE && item_mass(*weapon) >= 300) + if (you.body_size(PSIZE_TORSO) < SIZE_LARGE && item_mass(*weapon) >= 300) { SAY(mpr("That's too large and heavy for you to wield.")); return (false); } // Small species wielding large weapons... - if (player_size(PSIZE_BODY) < SIZE_MEDIUM - && !check_weapon_wieldable_size(*weapon, player_size(PSIZE_BODY))) + if (you.body_size(PSIZE_BODY) < SIZE_MEDIUM + && !check_weapon_wieldable_size(*weapon, you.body_size(PSIZE_BODY))) { SAY(mpr("That's too large for you to wield.")); return (false); @@ -800,7 +800,7 @@ bool can_wear_armour(const item_def &item, bool verbose, bool ignore_temporary) else { can_wear = (fit_armour_size(item, - player_size(PSIZE_TORSO, ignore_temporary)) == 0); + you.body_size(PSIZE_TORSO, ignore_temporary)) == 0); } if (!can_wear) @@ -900,7 +900,7 @@ bool can_wear_armour(const item_def &item, bool verbose, bool ignore_temporary) } // Giant races and draconians. - if (player_size(PSIZE_TORSO, ignore_temporary) >= SIZE_LARGE + if (you.body_size(PSIZE_TORSO, ignore_temporary) >= SIZE_LARGE || player_genus(GENPC_DRACONIAN)) { if (sub_type >= ARM_LEATHER_ARMOUR @@ -919,7 +919,7 @@ bool can_wear_armour(const item_def &item, bool verbose, bool ignore_temporary) } // Tiny races. - if (player_size(PSIZE_TORSO, ignore_temporary) <= SIZE_LITTLE) + if (you.body_size(PSIZE_TORSO, ignore_temporary) <= SIZE_LITTLE) { if ((sub_type >= ARM_LEATHER_ARMOUR && sub_type <= ARM_PLATE_MAIL) @@ -1523,7 +1523,7 @@ int launcher_shield_slowdown(const item_def &launcher, const item_def *shield) return (speed_adjust); const int shield_type = shield->sub_type; - hands_reqd_type hands = hands_reqd(launcher, player_size()); + hands_reqd_type hands = hands_reqd(launcher, you.body_size()); switch (hands) { @@ -2296,7 +2296,7 @@ bool throw_it(bolt &pbolt, int throw_2, bool teleport, int acc_bonus, } else if (wepType == MI_THROWING_NET) { - max_range = range = 2 + player_size(PSIZE_BODY); + max_range = range = 2 + you.body_size(PSIZE_BODY); } else { diff --git a/crawl-ref/source/itemname.cc b/crawl-ref/source/itemname.cc index d87c786bb8..2b99f39f1d 100644 --- a/crawl-ref/source/itemname.cc +++ b/crawl-ref/source/itemname.cc @@ -2502,7 +2502,7 @@ bool is_useless_item(const item_def &item, bool temp) switch (item.base_type) { case OBJ_WEAPONS: - if (!check_weapon_wieldable_size(item, player_size(PSIZE_BODY, !temp)) + if (!check_weapon_wieldable_size(item, you.body_size(PSIZE_BODY, !temp)) && !is_throwable(&you, item)) { // Weapon is too large (or small) to be wielded and cannot be @@ -2528,11 +2528,11 @@ bool is_useless_item(const item_def &item, bool temp) switch (item.sub_type) { case MI_LARGE_ROCK: - return (player_size(PSIZE_BODY, !temp) < SIZE_LARGE + return (you.body_size(PSIZE_BODY, !temp) < SIZE_LARGE || !you.can_throw_large_rocks()); case MI_JAVELIN: case MI_THROWING_NET: - return (player_size(PSIZE_BODY, !temp) < SIZE_MEDIUM); + return (you.body_size(PSIZE_BODY, !temp) < SIZE_MEDIUM); } return (false); diff --git a/crawl-ref/source/itemprop.cc b/crawl-ref/source/itemprop.cc index b6f4ea7e9e..58b421ab80 100644 --- a/crawl-ref/source/itemprop.cc +++ b/crawl-ref/source/itemprop.cc @@ -2121,7 +2121,7 @@ int get_inv_hand_tool( void ) // assuring that bad "shape" weapons aren't in hand ASSERT( check_weapon_shape( you.inv[tool], false ) ); - if (!check_weapon_tool_size( you.inv[tool], player_size() )) + if (!check_weapon_tool_size( you.inv[tool], you.body_size() )) return (-1); } */ @@ -2799,7 +2799,7 @@ bool is_shield_incompatible(const item_def &weapon, const item_def *shield) if (!shield && !(shield = player_shield())) return (false); - hands_reqd_type hand = hands_reqd(weapon, player_size()); + hands_reqd_type hand = hands_reqd(weapon, you.body_size()); return (hand == HANDS_TWO && !item_is_rod(weapon) && !is_range_weapon(weapon)); diff --git a/crawl-ref/source/jobs.cc b/crawl-ref/source/jobs.cc index 07e1ae139e..5daaaada78 100644 --- a/crawl-ref/source/jobs.cc +++ b/crawl-ref/source/jobs.cc @@ -190,3 +190,7 @@ int ng_num_classes() return ARRAYSZ(old_jobs_order); } +bool is_valid_job(job_type job) +{ + return (job >= 0 && job < NUM_JOBS); +} diff --git a/crawl-ref/source/jobs.h b/crawl-ref/source/jobs.h index 70d87ab67b..4b02ac149b 100644 --- a/crawl-ref/source/jobs.h +++ b/crawl-ref/source/jobs.h @@ -10,4 +10,7 @@ int get_class_index_by_name(const char *name); const char *get_class_name(int which_job); job_type get_class_by_name(const char *name); +// job_type bounds checking. +bool is_valid_job(job_type job); + #endif diff --git a/crawl-ref/source/makefile.obj b/crawl-ref/source/makefile.obj index 3b64e04299..c017f736ed 100644 --- a/crawl-ref/source/makefile.obj +++ b/crawl-ref/source/makefile.obj @@ -86,6 +86,7 @@ mt19937ar.o \ mtransit.o \ mutation.o \ newgame.o \ +ng-restr.o \ jobs.o \ species.o \ notes.o \ diff --git a/crawl-ref/source/mon-util.cc b/crawl-ref/source/mon-util.cc index 67b4d25061..053ac96a28 100644 --- a/crawl-ref/source/mon-util.cc +++ b/crawl-ref/source/mon-util.cc @@ -3789,7 +3789,7 @@ bool monsters::can_drown() const || mons_holiness(this) == MH_DEMONIC); } -size_type monsters::body_size(int /* psize */, bool /* base */) const +size_type monsters::body_size(size_part_type /* psize */, bool /* base */) const { const monsterentry *e = get_monster_data(type); return (e ? e->size : SIZE_MEDIUM); diff --git a/crawl-ref/source/monster.h b/crawl-ref/source/monster.h index 028f4155fd..133c0df54f 100644 --- a/crawl-ref/source/monster.h +++ b/crawl-ref/source/monster.h @@ -201,7 +201,7 @@ public: bool extra_balanced() const; bool can_pass_through_feat(dungeon_feature_type grid) const; bool is_habitable_feat(dungeon_feature_type actual_grid) const; - size_type body_size(int psize = PSIZE_TORSO, bool base = false) const; + size_type body_size(size_part_type psize = PSIZE_TORSO, bool base = false) const; int body_weight() const; int total_weight() const; int damage_brand(int which_attack = -1); diff --git a/crawl-ref/source/newgame.cc b/crawl-ref/source/newgame.cc index b102608ff0..7682badd34 100644 --- a/crawl-ref/source/newgame.cc +++ b/crawl-ref/source/newgame.cc @@ -7,6 +7,7 @@ #include "AppHdr.h" #include "newgame.h" +#include "ng-restr.h" #include "jobs.h" #include @@ -61,17 +62,6 @@ extern std::string init_file_error; #define MIN_START_STAT 3 -enum char_choice_restriction -{ - CC_BANNED = 0, - CC_RESTRICTED, - CC_UNRESTRICTED -}; - -static char_choice_restriction _class_allowed(species_type speci, - job_type char_class); -static bool _is_good_combination( species_type spc, job_type cls, - bool good = false); static bool _validate_player_name(bool verbose); static void _enter_player_name(bool blankOK); static void _give_basic_knowledge(job_type which_job); @@ -90,6 +80,15 @@ static void _fix_up_god_name(void); // Remember player's startup options // +static newgame_def ng; + +// XXX: temporary to get data to ng-restr.cc. +void newgame_def::init(const player &p) +{ + species = p.species; + job = p.char_class; +} + static char ng_race, ng_cls; static bool ng_random; static int ng_ck, ng_dk; @@ -257,7 +256,7 @@ static void _pick_random_species_and_class( bool unrestricted_only ) for (int cl = JOB_FIGHTER; cl < NUM_JOBS; cl++) { - if (_is_good_combination(static_cast(sp), + if (is_good_combination(static_cast(sp), static_cast(cl), unrestricted_only)) { @@ -892,7 +891,7 @@ game_start: { if (Options.race != 0 && Options.cls != 0 && Options.race != '*' && Options.cls != '*' - && !_class_allowed(get_species(letter_to_index(Options.race)), + && !class_allowed(get_species(letter_to_index(Options.race)), get_class(letter_to_index(Options.cls)))) { end(1, false, @@ -1041,599 +1040,38 @@ game_start: // link properly you.inv[i].pos.set(-1, -1); you.inv[i].link = i; - you.inv[i].slot = index_to_letter(you.inv[i].link); - item_colour(you.inv[i]); // set correct special and colour - _apply_job_colour(you.inv[i]); - } - - // Apply autoinscribe rules to inventory. - request_autoinscribe(); - autoinscribe(); - - // Brand items as original equipment. - origin_set_inventory(origin_set_startequip); - - // We calculate hp and mp here; all relevant factors should be - // finalised by now. (GDL) - calc_hp(); - calc_mp(); - - // Make sure the starting player is fully charged up. - set_hp( you.hp_max, false ); - set_mp( you.max_magic_points, false ); - - // tmpfile purging removed in favour of marking - Generated_Levels.clear(); - - _initialise_branch_depths(); - init_level_connectivity(); - - // Generate the second name of Jiyva - _fix_up_god_name(); - - _save_newgame_options(); - return (true); -} - -static char_choice_restriction _class_allowed(species_type speci, - job_type char_class) -{ - switch (char_class) - { - case JOB_FIGHTER: - switch (speci) - { - case SP_DEEP_ELF: - case SP_SLUDGE_ELF: - case SP_DEEP_DWARF: - case SP_MERFOLK: - case SP_HALFLING: - case SP_KOBOLD: - case SP_SPRIGGAN: - case SP_NAGA: - case SP_OGRE: - case SP_RED_DRACONIAN: - case SP_MUMMY: - case SP_VAMPIRE: - return (CC_RESTRICTED); - default: - return (CC_UNRESTRICTED); - } - - case JOB_GLADIATOR: - switch (speci) - { - case SP_DEEP_ELF: - case SP_DEEP_DWARF: - case SP_HILL_ORC: - case SP_HALFLING: - case SP_KOBOLD: - case SP_SPRIGGAN: - case SP_NAGA: - case SP_CENTAUR: - case SP_TROLL: - case SP_RED_DRACONIAN: - case SP_GHOUL: - case SP_MUMMY: - return (CC_RESTRICTED); - default: - return (CC_UNRESTRICTED); - } - - case JOB_MONK: - switch (speci) - { - case SP_HUMAN: - case SP_HIGH_ELF: - case SP_DEEP_ELF: - case SP_MOUNTAIN_DWARF: - case SP_DEEP_DWARF: - case SP_HILL_ORC: - case SP_HALFLING: - case SP_KOBOLD: - case SP_SPRIGGAN: - case SP_NAGA: - case SP_RED_DRACONIAN: - case SP_DEMIGOD: - case SP_DEMONSPAWN: - case SP_MUMMY: - return (CC_RESTRICTED); - default: - return (CC_UNRESTRICTED); - } - - case JOB_BERSERKER: - switch (speci) - { - case SP_DEMIGOD: - return (CC_BANNED); - case SP_HIGH_ELF: - case SP_DEEP_ELF: - case SP_SLUDGE_ELF: - case SP_MERFOLK: - case SP_HALFLING: - case SP_KOBOLD: - case SP_SPRIGGAN: - case SP_NAGA: - case SP_CENTAUR: - case SP_RED_DRACONIAN: - case SP_MUMMY: - case SP_GHOUL: - case SP_VAMPIRE: - return (CC_RESTRICTED); - default: - return (CC_UNRESTRICTED); - } - - case JOB_PALADIN: - switch (speci) - { - case SP_DEMIGOD: - case SP_DEMONSPAWN: - case SP_MUMMY: - case SP_GHOUL: - case SP_VAMPIRE: - return (CC_BANNED); - case SP_DEEP_ELF: - case SP_SLUDGE_ELF: - case SP_HALFLING: - case SP_KOBOLD: - case SP_SPRIGGAN: - case SP_NAGA: - case SP_OGRE: - case SP_TROLL: - case SP_KENKU: - return (CC_RESTRICTED); - default: - return (CC_UNRESTRICTED); - } - - case JOB_PRIEST: - switch (speci) - { - case SP_DEMIGOD: - return (CC_BANNED); - case SP_DEEP_ELF: - case SP_DEEP_DWARF: - case SP_MERFOLK: - case SP_HALFLING: - case SP_SPRIGGAN: - case SP_NAGA: - case SP_OGRE: - case SP_TROLL: - case SP_KENKU: - case SP_GHOUL: - case SP_VAMPIRE: - return (CC_RESTRICTED); - default: - return (CC_UNRESTRICTED); - } - - case JOB_CHAOS_KNIGHT: - switch (speci) - { - case SP_DEMIGOD: - return (CC_BANNED); - case SP_DEEP_ELF: - case SP_SPRIGGAN: - case SP_NAGA: - case SP_KENKU: - return (CC_RESTRICTED); - default: - return (CC_UNRESTRICTED); - } - - case JOB_DEATH_KNIGHT: - switch (speci) - { - case SP_SPRIGGAN: - case SP_NAGA: - case SP_KENKU: - case SP_GHOUL: - return (CC_RESTRICTED); - default: - return (CC_UNRESTRICTED); - } - - case JOB_HEALER: - switch (speci) - { - case SP_DEMIGOD: - case SP_DEMONSPAWN: - case SP_MUMMY: - case SP_GHOUL: - case SP_VAMPIRE: - return (CC_BANNED); - case SP_DEEP_ELF: - case SP_HALFLING: - case SP_SPRIGGAN: - case SP_NAGA: - return (CC_RESTRICTED); - default: - return (CC_UNRESTRICTED); - } - - case JOB_CRUSADER: - switch (speci) - { - case SP_DEEP_ELF: - case SP_SLUDGE_ELF: - case SP_MOUNTAIN_DWARF: - case SP_DEEP_DWARF: - case SP_HILL_ORC: - case SP_SPRIGGAN: - case SP_NAGA: - case SP_CENTAUR: - case SP_OGRE: - case SP_TROLL: - case SP_MINOTAUR: - case SP_KENKU: - case SP_MUMMY: - case SP_GHOUL: - case SP_VAMPIRE: - return (CC_RESTRICTED); - default: - return (CC_UNRESTRICTED); - } - - case JOB_REAVER: - switch (speci) - { - case SP_HUMAN: - case SP_SLUDGE_ELF: - case SP_DEEP_DWARF: - case SP_HILL_ORC: - case SP_HALFLING: - case SP_KOBOLD: - case SP_SPRIGGAN: - case SP_NAGA: - case SP_CENTAUR: - case SP_OGRE: - case SP_TROLL: - case SP_MINOTAUR: - case SP_KENKU: - case SP_RED_DRACONIAN: - case SP_DEMONSPAWN: - case SP_MUMMY: - case SP_GHOUL: - case SP_VAMPIRE: - return (CC_RESTRICTED); - default: - return (CC_UNRESTRICTED); - } - - case JOB_WIZARD: - switch (speci) - { - case SP_MOUNTAIN_DWARF: - case SP_DEEP_DWARF: - case SP_HILL_ORC: - case SP_MERFOLK: - case SP_HALFLING: - case SP_KOBOLD: - case SP_SPRIGGAN: - case SP_CENTAUR: - case SP_TROLL: - case SP_OGRE: - case SP_MINOTAUR: - case SP_GHOUL: - return (CC_RESTRICTED); - default: - return (CC_UNRESTRICTED); - } - - case JOB_CONJURER: - switch (speci) - { - case SP_DEEP_DWARF: - case SP_HILL_ORC: - case SP_MERFOLK: - case SP_HALFLING: - case SP_SPRIGGAN: - case SP_CENTAUR: - case SP_TROLL: - case SP_MINOTAUR: - case SP_GHOUL: - case SP_VAMPIRE: - return (CC_RESTRICTED); - default: - return (CC_UNRESTRICTED); - } - - case JOB_ENCHANTER: - switch (speci) - { - case SP_SLUDGE_ELF: - case SP_MOUNTAIN_DWARF: - case SP_DEEP_DWARF: - case SP_HILL_ORC: - case SP_NAGA: - case SP_CENTAUR: - case SP_OGRE: - case SP_TROLL: - case SP_MINOTAUR: - case SP_KENKU: - case SP_RED_DRACONIAN: - case SP_DEMONSPAWN: - case SP_GHOUL: - case SP_MUMMY: - return (CC_RESTRICTED); - default: - return (CC_UNRESTRICTED); - } - - case JOB_SUMMONER: - switch (speci) - { - case SP_HUMAN: - case SP_HIGH_ELF: - case SP_MOUNTAIN_DWARF: - case SP_DEEP_DWARF: - case SP_HILL_ORC: - case SP_MERFOLK: - case SP_HALFLING: - case SP_SPRIGGAN: - case SP_CENTAUR: - case SP_TROLL: - case SP_MINOTAUR: - case SP_RED_DRACONIAN: - case SP_DEMIGOD: - case SP_DEMONSPAWN: - case SP_GHOUL: - return (CC_RESTRICTED); - default: - return (CC_UNRESTRICTED); - } - - case JOB_NECROMANCER: - switch (speci) - { - case SP_HIGH_ELF: - case SP_MOUNTAIN_DWARF: - case SP_MERFOLK: - case SP_HALFLING: - case SP_SPRIGGAN: - case SP_CENTAUR: - case SP_TROLL: - case SP_MINOTAUR: - case SP_GHOUL: - return (CC_RESTRICTED); - default: - return (CC_UNRESTRICTED); - } - - case JOB_WARPER: - switch (speci) - { - case SP_HUMAN: - case SP_DEEP_ELF: - case SP_SLUDGE_ELF: - case SP_MOUNTAIN_DWARF: - case SP_DEEP_DWARF: - case SP_HILL_ORC: - case SP_MERFOLK: - case SP_HALFLING: - case SP_KOBOLD: - case SP_CENTAUR: - case SP_OGRE: - case SP_TROLL: - case SP_MINOTAUR: - case SP_KENKU: - case SP_RED_DRACONIAN: - case SP_DEMONSPAWN: - case SP_MUMMY: - case SP_GHOUL: - case SP_VAMPIRE: - return (CC_RESTRICTED); - default: - return (CC_UNRESTRICTED); - } - - case JOB_TRANSMUTER: - switch (speci) - { - case SP_HUMAN: - case SP_HIGH_ELF: - case SP_DEEP_ELF: - case SP_MOUNTAIN_DWARF: - case SP_DEEP_DWARF: - case SP_HILL_ORC: - case SP_HALFLING: - case SP_KOBOLD: - case SP_SPRIGGAN: - case SP_CENTAUR: - case SP_TROLL: - case SP_MINOTAUR: - case SP_KENKU: - case SP_DEMONSPAWN: - case SP_MUMMY: - case SP_GHOUL: - case SP_VAMPIRE: - return (CC_RESTRICTED); - default: - return (CC_UNRESTRICTED); - } - - case JOB_FIRE_ELEMENTALIST: - switch (speci) - { - case SP_DEEP_DWARF: - case SP_MERFOLK: - case SP_HALFLING: - case SP_SPRIGGAN: - case SP_CENTAUR: - case SP_TROLL: - case SP_MINOTAUR: - case SP_GHOUL: - case SP_VAMPIRE: - return (CC_RESTRICTED); - default: - return (CC_UNRESTRICTED); - } - - case JOB_ICE_ELEMENTALIST: - switch (speci) - { - case SP_MOUNTAIN_DWARF: - case SP_DEEP_DWARF: - case SP_HILL_ORC: - case SP_HALFLING: - case SP_SPRIGGAN: - case SP_CENTAUR: - case SP_TROLL: - case SP_MINOTAUR: - case SP_GHOUL: - case SP_VAMPIRE: - return (CC_RESTRICTED); - default: - return (CC_UNRESTRICTED); - } - - case JOB_AIR_ELEMENTALIST: - switch (speci) - { - case SP_MOUNTAIN_DWARF: - case SP_DEEP_DWARF: - case SP_HILL_ORC: - case SP_MERFOLK: - case SP_CENTAUR: - case SP_TROLL: - case SP_MINOTAUR: - case SP_MUMMY: - case SP_GHOUL: - case SP_VAMPIRE: - return (CC_RESTRICTED); - default: - return (CC_UNRESTRICTED); - } - - case JOB_EARTH_ELEMENTALIST: - switch (speci) - { - case SP_HIGH_ELF: - case SP_DEEP_DWARF: - case SP_HILL_ORC: - case SP_MERFOLK: - case SP_HALFLING: - case SP_SPRIGGAN: - case SP_NAGA: - case SP_CENTAUR: - case SP_TROLL: - case SP_MINOTAUR: - case SP_KENKU: - case SP_RED_DRACONIAN: - case SP_GHOUL: - case SP_VAMPIRE: - return (CC_RESTRICTED); - default: - return (CC_UNRESTRICTED); - } - - case JOB_VENOM_MAGE: - switch (speci) - { - case SP_HIGH_ELF: - case SP_MOUNTAIN_DWARF: - case SP_DEEP_DWARF: - case SP_HILL_ORC: - case SP_HALFLING: - case SP_CENTAUR: - case SP_TROLL: - case SP_MINOTAUR: - case SP_GHOUL: - case SP_VAMPIRE: - return (CC_RESTRICTED); - default: - return (CC_UNRESTRICTED); - } - - case JOB_STALKER: - switch (speci) - { - case SP_HIGH_ELF: - case SP_MOUNTAIN_DWARF: - case SP_DEEP_DWARF: - case SP_HILL_ORC: - case SP_CENTAUR: - case SP_OGRE: - case SP_TROLL: - case SP_MINOTAUR: - case SP_RED_DRACONIAN: - case SP_MUMMY: - case SP_GHOUL: - case SP_VAMPIRE: - return (CC_RESTRICTED); - default: - return (CC_UNRESTRICTED); - } - - case JOB_THIEF: - return (CC_RESTRICTED); - - case JOB_ASSASSIN: - switch (speci) - { - case SP_HIGH_ELF: - case SP_DEEP_ELF: - case SP_MOUNTAIN_DWARF: - case SP_DEEP_DWARF: - case SP_HILL_ORC: - case SP_NAGA: - case SP_CENTAUR: - case SP_OGRE: - case SP_TROLL: - case SP_MINOTAUR: - case SP_RED_DRACONIAN: - return (CC_RESTRICTED); - default: - return (CC_UNRESTRICTED); - } - - case JOB_HUNTER: - switch (speci) - { - case SP_DEEP_DWARF: - case SP_KOBOLD: - case SP_NAGA: - case SP_RED_DRACONIAN: - case SP_MUMMY: - case SP_GHOUL: - case SP_VAMPIRE: - return (CC_RESTRICTED); - default: - return (CC_UNRESTRICTED); - } - - case JOB_ARTIFICER: - switch (speci) - { - case SP_CENTAUR: - case SP_TROLL: - case SP_MINOTAUR: - case SP_OGRE: - case SP_MUMMY: - case SP_GHOUL: - return (CC_RESTRICTED); - default: - return (CC_UNRESTRICTED); + you.inv[i].slot = index_to_letter(you.inv[i].link); + item_colour(you.inv[i]); // set correct special and colour + _apply_job_colour(you.inv[i]); } - case JOB_WANDERER: - return (CC_RESTRICTED); + // Apply autoinscribe rules to inventory. + request_autoinscribe(); + autoinscribe(); - default: - return (CC_BANNED); - } -} + // Brand items as original equipment. + origin_set_inventory(origin_set_startequip); -static bool _is_good_combination( species_type spc, job_type cls, bool good) -{ - const char_choice_restriction restrict = _class_allowed(spc, cls); + // We calculate hp and mp here; all relevant factors should be + // finalised by now. (GDL) + calc_hp(); + calc_mp(); + + // Make sure the starting player is fully charged up. + set_hp( you.hp_max, false ); + set_mp( you.max_magic_points, false ); + + // tmpfile purging removed in favour of marking + Generated_Levels.clear(); - if (good) - return (restrict == CC_UNRESTRICTED); + _initialise_branch_depths(); + init_level_connectivity(); + + // Generate the second name of Jiyva + _fix_up_god_name(); - return (restrict != CC_BANNED); + _save_newgame_options(); + return (true); } static startup_book_type _book_to_start(int book) @@ -1694,87 +1132,12 @@ static int _start_to_book(int firstbook, int booktype) } } -static char_choice_restriction _book_restriction(startup_book_type booktype) -{ - switch (booktype) - { - case SBT_FIRE: // Fire - switch (you.species) - { - case SP_HUMAN: - case SP_HIGH_ELF: - case SP_DEEP_ELF: - case SP_SLUDGE_ELF: - case SP_MOUNTAIN_DWARF: - case SP_HILL_ORC: - case SP_KOBOLD: - case SP_NAGA: - case SP_OGRE: - case SP_KENKU: - case SP_DEMIGOD: - case SP_DEMONSPAWN: - case SP_MUMMY: - return (CC_UNRESTRICTED); - - default: - if (player_genus(GENPC_DRACONIAN)) - return (CC_UNRESTRICTED); - return (CC_RESTRICTED); - } - break; - - case SBT_COLD: // Ice - switch (you.species) - { - case SP_HUMAN: - case SP_HIGH_ELF: - case SP_DEEP_ELF: - case SP_SLUDGE_ELF: - case SP_HILL_ORC: - case SP_MERFOLK: - case SP_KOBOLD: - case SP_NAGA: - case SP_OGRE: - case SP_KENKU: - case SP_DEMIGOD: - case SP_DEMONSPAWN: - case SP_MUMMY: - return (CC_UNRESTRICTED); - - default: - if (player_genus(GENPC_DRACONIAN)) - return (CC_UNRESTRICTED); - return (CC_RESTRICTED); - } - break; - - case SBT_SUMM: // Summoning - switch (you.species) - { - case SP_DEEP_ELF: - case SP_SLUDGE_ELF: - case SP_KOBOLD: - case SP_NAGA: - case SP_OGRE: - case SP_KENKU: - case SP_MUMMY: - case SP_VAMPIRE: - return (CC_UNRESTRICTED); - - default: - return (CC_RESTRICTED); - } - break; - - default: - return (CC_RESTRICTED); - } -} - static bool _choose_book( int slot, int firstbook, int numbooks ) { clrscr(); + ng.init(you); // XXX + item_def &book(you.inv[slot]); book.base_type = OBJ_BOOKS; book.sub_type = firstbook; @@ -1789,8 +1152,8 @@ static bool _choose_book( int slot, int firstbook, int numbooks ) char_choice_restriction book_restrictions[3]; for (int i = 0; i < numbooks; i++) { - book_restrictions[i] = _book_restriction( - _book_to_start(firstbook + i)); + book_restrictions[i] = book_restriction( + _book_to_start(firstbook + i), ng); } if (Options.book) @@ -1906,7 +1269,7 @@ static bool _choose_book( int slot, int firstbook, int numbooks ) { for (int i = 0; i < numbooks; i++) { - if (_book_restriction(_book_to_start(firstbook + i)) + if (book_restriction(_book_to_start(firstbook + i), ng) == CC_UNRESTRICTED && one_chance_in(++good_choices)) { @@ -1927,129 +1290,17 @@ static bool _choose_book( int slot, int firstbook, int numbooks ) return (true); } -static char_choice_restriction _weapon_restriction(weapon_type wpn) -{ - switch (wpn) - { - case WPN_UNARMED: - if (you.has_claws()) - return (CC_UNRESTRICTED); - return (CC_BANNED); - - case WPN_SHORT_SWORD: - switch (you.species) - { - case SP_NAGA: - case SP_VAMPIRE: - // The fighter's heavy armour hinders stabbing. - if (you.char_class == JOB_FIGHTER) - return (CC_RESTRICTED); - // else fall through - case SP_HIGH_ELF: - case SP_DEEP_ELF: - // Sludge elves have bad aptitudes with short swords (110) but are - // still better with them than any other starting weapon. - case SP_SLUDGE_ELF: - case SP_HALFLING: - case SP_KOBOLD: - case SP_SPRIGGAN: - return (CC_UNRESTRICTED); - - default: - return (CC_RESTRICTED); - } - - // Maces and hand axes usually share the same restrictions. - case WPN_MACE: - if (you.species == SP_TROLL) - return (CC_UNRESTRICTED); - if (you.species == SP_VAMPIRE) - return (CC_RESTRICTED); - // else fall-through - case WPN_HAND_AXE: - switch (you.species) - { - case SP_HUMAN: - case SP_MOUNTAIN_DWARF: - case SP_DEEP_DWARF: - case SP_HILL_ORC: - case SP_MUMMY: - case SP_CENTAUR: - case SP_NAGA: - case SP_MINOTAUR: - case SP_KENKU: - case SP_DEMIGOD: - case SP_DEMONSPAWN: - case SP_VAMPIRE: - return (CC_UNRESTRICTED); - - default: - return (player_genus(GENPC_DRACONIAN) ? CC_UNRESTRICTED - : CC_RESTRICTED); - } - - case WPN_SPEAR: - switch (you.species) - { - case SP_HUMAN: - case SP_HILL_ORC: - case SP_MERFOLK: - case SP_NAGA: - case SP_CENTAUR: - case SP_MINOTAUR: - case SP_KENKU: - case SP_DEMIGOD: - case SP_DEMONSPAWN: - case SP_MUMMY: - return (CC_UNRESTRICTED); - - default: - return (player_genus(GENPC_DRACONIAN) ? CC_UNRESTRICTED - : CC_RESTRICTED); - } - - case WPN_TRIDENT: - if (you.species != SP_MERFOLK - && (you.char_class != JOB_GLADIATOR - || player_size(PSIZE_BODY) < SIZE_MEDIUM)) - { - return (CC_BANNED); - } - - // Tridents are strictly better than spears, so unrestrict them - // for some species whose Polearm aptitudes are not too bad. - switch (you.species) - { - case SP_MOUNTAIN_DWARF: - case SP_OGRE: - case SP_GHOUL: - case SP_VAMPIRE: - return (CC_UNRESTRICTED); - default: - break; - } - - // Both are polearms, right? - return (_weapon_restriction(WPN_SPEAR)); - - case WPN_ANKUS: - if (player_genus(GENPC_OGRE)) - return (CC_UNRESTRICTED); - // intentional fall-through - default: - return (CC_BANNED); - } -} - static bool _choose_weapon() { weapon_type startwep[5] = { WPN_SHORT_SWORD, WPN_MACE, WPN_HAND_AXE, WPN_SPEAR, WPN_UNKNOWN }; + ng.init(you); + // Gladiators that are at least medium sized get to choose a trident // rather than a spear if (you.char_class == JOB_GLADIATOR - && player_size(PSIZE_BODY) >= SIZE_MEDIUM) + && you.body_size(PSIZE_BODY) >= SIZE_MEDIUM) { startwep[3] = WPN_TRIDENT; } @@ -2083,7 +1334,7 @@ static bool _choose_weapon() const int num_choices = (claws_allowed ? 5 : 4); for (int i = 0; i < num_choices; i++) - startwep_restrictions[i] = _weapon_restriction(startwep[i]); + startwep_restrictions[i] = weapon_restriction(startwep[i], ng); if (Options.weapon == WPN_UNARMED && claws_allowed) { @@ -2211,7 +1462,7 @@ static bool _choose_weapon() { for (int i = 0; i < num_choices; i++) { - if (_weapon_restriction(startwep[i]) == CC_UNRESTRICTED + if (weapon_restriction(startwep[i], ng) == CC_UNRESTRICTED && one_chance_in(++good_choices)) { keyin = i; @@ -2235,156 +1486,6 @@ static bool _choose_weapon() return (true); } -// Gods are not restricted but there are some choices that are banned (false). -// Everything else will be unrestricted. -static char_choice_restriction _religion_restriction(god_type god) -{ - // Sanity check. - if (you.species == SP_DEMIGOD) - return (CC_BANNED); - - switch (god) - { - case GOD_BEOGH: - if (you.species == SP_HILL_ORC) - return (CC_UNRESTRICTED); - return (CC_BANNED); - - case GOD_ZIN: - switch (you.species) - { - case SP_DEMONSPAWN: - case SP_MUMMY: - case SP_GHOUL: - case SP_VAMPIRE: - return (CC_BANNED); - case SP_SLUDGE_ELF: - case SP_MOUNTAIN_DWARF: - case SP_SPRIGGAN: - case SP_CENTAUR: - case SP_MINOTAUR: - case SP_OGRE: - return (CC_UNRESTRICTED); - default: - return (CC_RESTRICTED); - } - - case GOD_YREDELEMNUL: - switch (you.species) - { - case SP_HILL_ORC: - // Restrict in favour of Beogh, else unrestricted. - if (you.char_class == JOB_PRIEST) - return (CC_RESTRICTED); - return (CC_UNRESTRICTED); - - case SP_DEEP_ELF: - case SP_KENKU: - // Unrestrict these only for Priests as Zin is worse, but - // Necromancy (DK) the better choice. - if (you.char_class == JOB_PRIEST) - return (CC_UNRESTRICTED); - return (CC_RESTRICTED); - - case SP_HUMAN: - case SP_HIGH_ELF: - case SP_SLUDGE_ELF: - case SP_MOUNTAIN_DWARF: - case SP_DEEP_DWARF: - case SP_MERFOLK: - case SP_HALFLING: - case SP_KOBOLD: - case SP_SPRIGGAN: - case SP_CENTAUR: - case SP_OGRE: - case SP_TROLL: - case SP_MINOTAUR: - case SP_DEMONSPAWN: - case SP_MUMMY: - case SP_GHOUL: - case SP_VAMPIRE: - return (CC_UNRESTRICTED); - default: - if (player_genus(GENPC_DRACONIAN)) - return (CC_UNRESTRICTED); - return (CC_RESTRICTED); - } - - case GOD_XOM: - switch (you.species) - { - case SP_MOUNTAIN_DWARF: - case SP_HILL_ORC: - case SP_MERFOLK: - case SP_CENTAUR: - case SP_OGRE: - case SP_TROLL: - case SP_MINOTAUR: - case SP_KENKU: - case SP_DEMONSPAWN: - return (CC_UNRESTRICTED); - default: - if (player_genus(GENPC_DRACONIAN)) - return (CC_UNRESTRICTED); - return (CC_RESTRICTED); - } - - case GOD_MAKHLEB: - switch (you.species) - { - case SP_HUMAN: - case SP_HIGH_ELF: - case SP_DEEP_ELF: - case SP_SLUDGE_ELF: - case SP_MOUNTAIN_DWARF: - case SP_DEEP_DWARF: - case SP_HILL_ORC: - case SP_MERFOLK: - case SP_HALFLING: - case SP_KOBOLD: - case SP_NAGA: - case SP_CENTAUR: - case SP_OGRE: - case SP_TROLL: - case SP_MINOTAUR: - case SP_DEMONSPAWN: - case SP_MUMMY: - case SP_GHOUL: - case SP_VAMPIRE: - return (CC_UNRESTRICTED); - default: - if (player_genus(GENPC_DRACONIAN)) - return (CC_UNRESTRICTED); - return (CC_RESTRICTED); - } - - case GOD_LUGONU: - switch (you.species) - { - case SP_HUMAN: - case SP_MOUNTAIN_DWARF: - case SP_HILL_ORC: - case SP_MERFOLK: - case SP_SPRIGGAN: - case SP_CENTAUR: - case SP_OGRE: - case SP_TROLL: - case SP_MINOTAUR: - case SP_DEMONSPAWN: - case SP_GHOUL: - case SP_VAMPIRE: - return (CC_UNRESTRICTED); - default: - if (player_genus(GENPC_DRACONIAN)) - return (CC_UNRESTRICTED); - return (CC_RESTRICTED); - } - - default: - return (CC_RESTRICTED); - } -} - static bool _necromancy_okay() { switch (you.species) @@ -3094,7 +2195,7 @@ static void _newgame_make_item(int slot, equipment_type eqslot, // Don't replace shields with bucklers for large races or // draconians. if (sub_type != ARM_SHIELD - || player_size(PSIZE_TORSO) < SIZE_LARGE + || you.body_size(PSIZE_TORSO) < SIZE_LARGE && !player_genus(GENPC_DRACONIAN)) { item.sub_type = replacement; @@ -4198,7 +3299,7 @@ spec_query: // Dim text for restricted species if (you.char_class == JOB_UNKNOWN - || _class_allowed(si, you.char_class) == CC_UNRESTRICTED) + || class_allowed(si, you.char_class) == CC_UNRESTRICTED) { textcolor(LIGHTGREY); } @@ -4207,7 +3308,7 @@ spec_query: // Show banned races as "unavailable". if (you.char_class != JOB_UNKNOWN - && _class_allowed(si, you.char_class) == CC_BANNED) + && class_allowed(si, you.char_class) == CC_BANNED) { cprintf(" %s N/A", species_name(si, 1).c_str()); } @@ -4350,7 +3451,7 @@ spec_query: } while (!_is_species_valid_choice(get_species(index), false) || you.char_class != JOB_UNKNOWN - && !_is_good_combination(get_species(index), you.char_class, + && !is_good_combination(get_species(index), you.char_class, good_randrace)); keyn = index_to_letter(index); @@ -4370,7 +3471,7 @@ spec_query: } if (you.species != SP_UNKNOWN && you.char_class != JOB_UNKNOWN - && !_class_allowed(you.species, you.char_class)) + && !class_allowed(you.species, you.char_class)) { goto spec_query; } @@ -4439,7 +3540,7 @@ job_query: if (you.species == SP_UNKNOWN && which_job != JOB_THIEF && which_job != JOB_WANDERER || you.species != SP_UNKNOWN - && _class_allowed(you.species, which_job) == CC_UNRESTRICTED) + && class_allowed(you.species, which_job) == CC_UNRESTRICTED) { textcolor(LIGHTGREY); } @@ -4447,7 +3548,7 @@ job_query: textcolor(DARKGREY); // Show banned races as "unavailable". - if (_class_allowed(you.species, which_job) == CC_BANNED) + if (class_allowed(you.species, which_job) == CC_BANNED) { cprintf(" %s N/A", get_class_name(which_job)); } @@ -4599,7 +3700,7 @@ job_query: continue; if (you.species == SP_UNKNOWN - || _is_good_combination(you.species, job, good_random)) + || is_good_combination(you.species, job, good_random)) { job_count++; if (one_chance_in( job_count )) @@ -4622,7 +3723,7 @@ job_query: } if (you.species != SP_UNKNOWN - && !_class_allowed(you.species, chosen_job)) + && !class_allowed(you.species, chosen_job)) { if (Options.cls != 0) { @@ -4911,6 +4012,8 @@ bool _give_items_skills() int weap_skill = 0; int choice; // used for third-screen choices + ng.init(you); // XXX + switch (you.char_class) { case JOB_FIGHTER: @@ -4959,7 +4062,7 @@ bool _give_items_skills() } // Small races get stones, the others nets. - if (player_size(PSIZE_BODY) < SIZE_MEDIUM) + if (you.body_size(PSIZE_BODY) < SIZE_MEDIUM) _newgame_make_item(curr, EQ_NONE, OBJ_MISSILES, MI_STONE, -1, 20); else { @@ -5058,7 +4161,7 @@ bool _give_items_skills() const god_type gods[3] = { GOD_ZIN, GOD_YREDELEMNUL, GOD_BEOGH }; // Disallow invalid choices. - if (_religion_restriction(Options.priest) == CC_BANNED) + if (religion_restriction(Options.priest, ng) == CC_BANNED) Options.priest = GOD_NO_GOD; if (Options.priest != GOD_NO_GOD && Options.priest != GOD_RANDOM) @@ -5071,10 +4174,10 @@ bool _give_items_skills() int count = 0; for (int i = 0; i < 3; i++) { - if (_religion_restriction(gods[i]) == CC_BANNED) + if (religion_restriction(gods[i], ng) == CC_BANNED) continue; - if (_religion_restriction(gods[i]) == CC_UNRESTRICTED + if (religion_restriction(gods[i], ng) == CC_UNRESTRICTED && one_chance_in(++count)) { you.religion = gods[i]; @@ -5106,10 +4209,10 @@ bool _give_items_skills() for (int i = 0; i < 3; i++) { - if (_religion_restriction(gods[i]) == CC_BANNED) + if (religion_restriction(gods[i], ng) == CC_BANNED) continue; - if (_religion_restriction(gods[i]) == CC_UNRESTRICTED) + if (religion_restriction(gods[i], ng) == CC_UNRESTRICTED) textcolor(LIGHTGREY); else textcolor(DARKGREY); @@ -5123,7 +4226,7 @@ bool _give_items_skills() "Bksp - Back to species and class selection; " "X - Quit" EOL); - if (_religion_restriction(Options.prev_pr) == CC_BANNED) + if (religion_restriction(Options.prev_pr, ng) == CC_BANNED) Options.prev_pr = GOD_NO_GOD; if (Options.prev_pr != GOD_NO_GOD) @@ -5173,10 +4276,10 @@ bool _give_items_skills() int count = 0; for (int i = 0; i < 3; i++) { - if (_religion_restriction(gods[i]) == CC_BANNED) + if (religion_restriction(gods[i], ng) == CC_BANNED) continue; - if (_religion_restriction(gods[i]) + if (religion_restriction(gods[i], ng) == CC_UNRESTRICTED && one_chance_in(++count)) { @@ -5254,10 +4357,10 @@ bool _give_items_skills() int count = 0; for (int i = 0; i < 3; i++) { - if (_religion_restriction(gods[i]) == CC_BANNED) + if (religion_restriction(gods[i], ng) == CC_BANNED) continue; - if (_religion_restriction(gods[i]) == CC_UNRESTRICTED + if (religion_restriction(gods[i], ng) == CC_UNRESTRICTED && one_chance_in(++count)) { you.religion = gods[i]; @@ -5287,10 +4390,10 @@ bool _give_items_skills() for (int i = 0; i < 3; i++) { - if (_religion_restriction(gods[i]) == CC_BANNED) + if (religion_restriction(gods[i], ng) == CC_BANNED) continue; - if (_religion_restriction(gods[i]) == CC_UNRESTRICTED) + if (religion_restriction(gods[i], ng) == CC_UNRESTRICTED) textcolor(LIGHTGREY); else textcolor(DARKGREY); @@ -5347,10 +4450,10 @@ bool _give_items_skills() int count = 0; for (int i = 0; i < 3; i++) { - if (_religion_restriction(gods[i]) == CC_BANNED) + if (religion_restriction(gods[i], ng) == CC_BANNED) continue; - if (_religion_restriction(gods[i]) + if (religion_restriction(gods[i], ng) == CC_UNRESTRICTED && one_chance_in(++count)) { @@ -5462,7 +4565,7 @@ bool _give_items_skills() did_chose = true; } - if (_religion_restriction(GOD_YREDELEMNUL) == CC_UNRESTRICTED) + if (religion_restriction(GOD_YREDELEMNUL, ng) == CC_UNRESTRICTED) { if (!did_chose || coinflip()) choice = DK_YREDELEMNUL; @@ -5483,7 +4586,7 @@ bool _give_items_skills() cprintf("a - Necromantic magic" EOL); // Yredelemnul is an okay choice for everyone. - if (_religion_restriction(GOD_YREDELEMNUL) == CC_UNRESTRICTED) + if (religion_restriction(GOD_YREDELEMNUL, ng) == CC_UNRESTRICTED) textcolor(LIGHTGREY); else textcolor(DARKGREY); @@ -5540,7 +4643,7 @@ bool _give_items_skills() did_chose = true; } - if (_religion_restriction(GOD_YREDELEMNUL) + if (religion_restriction(GOD_YREDELEMNUL, ng) == CC_UNRESTRICTED) { if (!did_chose || coinflip()) diff --git a/crawl-ref/source/newgame.h b/crawl-ref/source/newgame.h index bb3feb5dbd..dfc9a2ac8e 100644 --- a/crawl-ref/source/newgame.h +++ b/crawl-ref/source/newgame.h @@ -9,6 +9,7 @@ #define NEWGAME_H +#include "enum.h" #include "itemprop.h" enum death_knight_type @@ -40,6 +41,16 @@ enum startup_wand_type SWT_RANDOM }; +class player; +struct newgame_def +{ + species_type species; + job_type job; + // TODO: fill in + + void init(const player &p); +}; + undead_state_type get_undead_state(const species_type sp); /* *********************************************************************** diff --git a/crawl-ref/source/ng-restr.cc b/crawl-ref/source/ng-restr.cc new file mode 100644 index 0000000000..fc43191023 --- /dev/null +++ b/crawl-ref/source/ng-restr.cc @@ -0,0 +1,929 @@ +/* + * File: ng-restr.cc + * Summary: Character choice restrictions. + * + * The functions in this file are "pure": They don't + * access any global data. + */ + +#include "AppHdr.h" + +#include "ng-restr.h" +#include "newgame.h" +#include "species.h" +#include "jobs.h" + +char_choice_restriction class_allowed(species_type speci, + job_type char_class) +{ + switch (char_class) + { + case JOB_FIGHTER: + switch (speci) + { + case SP_DEEP_ELF: + case SP_SLUDGE_ELF: + case SP_DEEP_DWARF: + case SP_MERFOLK: + case SP_HALFLING: + case SP_KOBOLD: + case SP_SPRIGGAN: + case SP_NAGA: + case SP_OGRE: + case SP_RED_DRACONIAN: + case SP_MUMMY: + case SP_VAMPIRE: + return (CC_RESTRICTED); + default: + return (CC_UNRESTRICTED); + } + + case JOB_GLADIATOR: + switch (speci) + { + case SP_DEEP_ELF: + case SP_DEEP_DWARF: + case SP_HILL_ORC: + case SP_HALFLING: + case SP_KOBOLD: + case SP_SPRIGGAN: + case SP_NAGA: + case SP_CENTAUR: + case SP_TROLL: + case SP_RED_DRACONIAN: + case SP_GHOUL: + case SP_MUMMY: + return (CC_RESTRICTED); + default: + return (CC_UNRESTRICTED); + } + + case JOB_MONK: + switch (speci) + { + case SP_HUMAN: + case SP_HIGH_ELF: + case SP_DEEP_ELF: + case SP_MOUNTAIN_DWARF: + case SP_DEEP_DWARF: + case SP_HILL_ORC: + case SP_HALFLING: + case SP_KOBOLD: + case SP_SPRIGGAN: + case SP_NAGA: + case SP_RED_DRACONIAN: + case SP_DEMIGOD: + case SP_DEMONSPAWN: + case SP_MUMMY: + return (CC_RESTRICTED); + default: + return (CC_UNRESTRICTED); + } + + case JOB_BERSERKER: + switch (speci) + { + case SP_DEMIGOD: + return (CC_BANNED); + case SP_HIGH_ELF: + case SP_DEEP_ELF: + case SP_SLUDGE_ELF: + case SP_MERFOLK: + case SP_HALFLING: + case SP_KOBOLD: + case SP_SPRIGGAN: + case SP_NAGA: + case SP_CENTAUR: + case SP_RED_DRACONIAN: + case SP_MUMMY: + case SP_GHOUL: + case SP_VAMPIRE: + return (CC_RESTRICTED); + default: + return (CC_UNRESTRICTED); + } + + case JOB_PALADIN: + switch (speci) + { + case SP_DEMIGOD: + case SP_DEMONSPAWN: + case SP_MUMMY: + case SP_GHOUL: + case SP_VAMPIRE: + return (CC_BANNED); + case SP_DEEP_ELF: + case SP_SLUDGE_ELF: + case SP_HALFLING: + case SP_KOBOLD: + case SP_SPRIGGAN: + case SP_NAGA: + case SP_OGRE: + case SP_TROLL: + case SP_KENKU: + return (CC_RESTRICTED); + default: + return (CC_UNRESTRICTED); + } + + case JOB_PRIEST: + switch (speci) + { + case SP_DEMIGOD: + return (CC_BANNED); + case SP_DEEP_ELF: + case SP_DEEP_DWARF: + case SP_MERFOLK: + case SP_HALFLING: + case SP_SPRIGGAN: + case SP_NAGA: + case SP_OGRE: + case SP_TROLL: + case SP_KENKU: + case SP_GHOUL: + case SP_VAMPIRE: + return (CC_RESTRICTED); + default: + return (CC_UNRESTRICTED); + } + + case JOB_CHAOS_KNIGHT: + switch (speci) + { + case SP_DEMIGOD: + return (CC_BANNED); + case SP_DEEP_ELF: + case SP_SPRIGGAN: + case SP_NAGA: + case SP_KENKU: + return (CC_RESTRICTED); + default: + return (CC_UNRESTRICTED); + } + + case JOB_DEATH_KNIGHT: + switch (speci) + { + case SP_SPRIGGAN: + case SP_NAGA: + case SP_KENKU: + case SP_GHOUL: + return (CC_RESTRICTED); + default: + return (CC_UNRESTRICTED); + } + + case JOB_HEALER: + switch (speci) + { + case SP_DEMIGOD: + case SP_DEMONSPAWN: + case SP_MUMMY: + case SP_GHOUL: + case SP_VAMPIRE: + return (CC_BANNED); + case SP_DEEP_ELF: + case SP_HALFLING: + case SP_SPRIGGAN: + case SP_NAGA: + return (CC_RESTRICTED); + default: + return (CC_UNRESTRICTED); + } + + case JOB_CRUSADER: + switch (speci) + { + case SP_DEEP_ELF: + case SP_SLUDGE_ELF: + case SP_MOUNTAIN_DWARF: + case SP_DEEP_DWARF: + case SP_HILL_ORC: + case SP_SPRIGGAN: + case SP_NAGA: + case SP_CENTAUR: + case SP_OGRE: + case SP_TROLL: + case SP_MINOTAUR: + case SP_KENKU: + case SP_MUMMY: + case SP_GHOUL: + case SP_VAMPIRE: + return (CC_RESTRICTED); + default: + return (CC_UNRESTRICTED); + } + + case JOB_REAVER: + switch (speci) + { + case SP_HUMAN: + case SP_SLUDGE_ELF: + case SP_DEEP_DWARF: + case SP_HILL_ORC: + case SP_HALFLING: + case SP_KOBOLD: + case SP_SPRIGGAN: + case SP_NAGA: + case SP_CENTAUR: + case SP_OGRE: + case SP_TROLL: + case SP_MINOTAUR: + case SP_KENKU: + case SP_RED_DRACONIAN: + case SP_DEMONSPAWN: + case SP_MUMMY: + case SP_GHOUL: + case SP_VAMPIRE: + return (CC_RESTRICTED); + default: + return (CC_UNRESTRICTED); + } + + case JOB_WIZARD: + switch (speci) + { + case SP_MOUNTAIN_DWARF: + case SP_DEEP_DWARF: + case SP_HILL_ORC: + case SP_MERFOLK: + case SP_HALFLING: + case SP_KOBOLD: + case SP_SPRIGGAN: + case SP_CENTAUR: + case SP_TROLL: + case SP_OGRE: + case SP_MINOTAUR: + case SP_GHOUL: + return (CC_RESTRICTED); + default: + return (CC_UNRESTRICTED); + } + + case JOB_CONJURER: + switch (speci) + { + case SP_DEEP_DWARF: + case SP_HILL_ORC: + case SP_MERFOLK: + case SP_HALFLING: + case SP_SPRIGGAN: + case SP_CENTAUR: + case SP_TROLL: + case SP_MINOTAUR: + case SP_GHOUL: + case SP_VAMPIRE: + return (CC_RESTRICTED); + default: + return (CC_UNRESTRICTED); + } + + case JOB_ENCHANTER: + switch (speci) + { + case SP_SLUDGE_ELF: + case SP_MOUNTAIN_DWARF: + case SP_DEEP_DWARF: + case SP_HILL_ORC: + case SP_NAGA: + case SP_CENTAUR: + case SP_OGRE: + case SP_TROLL: + case SP_MINOTAUR: + case SP_KENKU: + case SP_RED_DRACONIAN: + case SP_DEMONSPAWN: + case SP_GHOUL: + case SP_MUMMY: + return (CC_RESTRICTED); + default: + return (CC_UNRESTRICTED); + } + + case JOB_SUMMONER: + switch (speci) + { + case SP_HUMAN: + case SP_HIGH_ELF: + case SP_MOUNTAIN_DWARF: + case SP_DEEP_DWARF: + case SP_HILL_ORC: + case SP_MERFOLK: + case SP_HALFLING: + case SP_SPRIGGAN: + case SP_CENTAUR: + case SP_TROLL: + case SP_MINOTAUR: + case SP_RED_DRACONIAN: + case SP_DEMIGOD: + case SP_DEMONSPAWN: + case SP_GHOUL: + return (CC_RESTRICTED); + default: + return (CC_UNRESTRICTED); + } + + case JOB_NECROMANCER: + switch (speci) + { + case SP_HIGH_ELF: + case SP_MOUNTAIN_DWARF: + case SP_MERFOLK: + case SP_HALFLING: + case SP_SPRIGGAN: + case SP_CENTAUR: + case SP_TROLL: + case SP_MINOTAUR: + case SP_GHOUL: + return (CC_RESTRICTED); + default: + return (CC_UNRESTRICTED); + } + + case JOB_WARPER: + switch (speci) + { + case SP_HUMAN: + case SP_DEEP_ELF: + case SP_SLUDGE_ELF: + case SP_MOUNTAIN_DWARF: + case SP_DEEP_DWARF: + case SP_HILL_ORC: + case SP_MERFOLK: + case SP_HALFLING: + case SP_KOBOLD: + case SP_CENTAUR: + case SP_OGRE: + case SP_TROLL: + case SP_MINOTAUR: + case SP_KENKU: + case SP_RED_DRACONIAN: + case SP_DEMONSPAWN: + case SP_MUMMY: + case SP_GHOUL: + case SP_VAMPIRE: + return (CC_RESTRICTED); + default: + return (CC_UNRESTRICTED); + } + + case JOB_TRANSMUTER: + switch (speci) + { + case SP_HUMAN: + case SP_HIGH_ELF: + case SP_DEEP_ELF: + case SP_MOUNTAIN_DWARF: + case SP_DEEP_DWARF: + case SP_HILL_ORC: + case SP_HALFLING: + case SP_KOBOLD: + case SP_SPRIGGAN: + case SP_CENTAUR: + case SP_TROLL: + case SP_MINOTAUR: + case SP_KENKU: + case SP_DEMONSPAWN: + case SP_MUMMY: + case SP_GHOUL: + case SP_VAMPIRE: + return (CC_RESTRICTED); + default: + return (CC_UNRESTRICTED); + } + + case JOB_FIRE_ELEMENTALIST: + switch (speci) + { + case SP_DEEP_DWARF: + case SP_MERFOLK: + case SP_HALFLING: + case SP_SPRIGGAN: + case SP_CENTAUR: + case SP_TROLL: + case SP_MINOTAUR: + case SP_GHOUL: + case SP_VAMPIRE: + return (CC_RESTRICTED); + default: + return (CC_UNRESTRICTED); + } + + case JOB_ICE_ELEMENTALIST: + switch (speci) + { + case SP_MOUNTAIN_DWARF: + case SP_DEEP_DWARF: + case SP_HILL_ORC: + case SP_HALFLING: + case SP_SPRIGGAN: + case SP_CENTAUR: + case SP_TROLL: + case SP_MINOTAUR: + case SP_GHOUL: + case SP_VAMPIRE: + return (CC_RESTRICTED); + default: + return (CC_UNRESTRICTED); + } + + case JOB_AIR_ELEMENTALIST: + switch (speci) + { + case SP_MOUNTAIN_DWARF: + case SP_DEEP_DWARF: + case SP_HILL_ORC: + case SP_MERFOLK: + case SP_CENTAUR: + case SP_TROLL: + case SP_MINOTAUR: + case SP_MUMMY: + case SP_GHOUL: + case SP_VAMPIRE: + return (CC_RESTRICTED); + default: + return (CC_UNRESTRICTED); + } + + case JOB_EARTH_ELEMENTALIST: + switch (speci) + { + case SP_HIGH_ELF: + case SP_DEEP_DWARF: + case SP_HILL_ORC: + case SP_MERFOLK: + case SP_HALFLING: + case SP_SPRIGGAN: + case SP_NAGA: + case SP_CENTAUR: + case SP_TROLL: + case SP_MINOTAUR: + case SP_KENKU: + case SP_RED_DRACONIAN: + case SP_GHOUL: + case SP_VAMPIRE: + return (CC_RESTRICTED); + default: + return (CC_UNRESTRICTED); + } + + case JOB_VENOM_MAGE: + switch (speci) + { + case SP_HIGH_ELF: + case SP_MOUNTAIN_DWARF: + case SP_DEEP_DWARF: + case SP_HILL_ORC: + case SP_HALFLING: + case SP_CENTAUR: + case SP_TROLL: + case SP_MINOTAUR: + case SP_GHOUL: + case SP_VAMPIRE: + return (CC_RESTRICTED); + default: + return (CC_UNRESTRICTED); + } + + case JOB_STALKER: + switch (speci) + { + case SP_HIGH_ELF: + case SP_MOUNTAIN_DWARF: + case SP_DEEP_DWARF: + case SP_HILL_ORC: + case SP_CENTAUR: + case SP_OGRE: + case SP_TROLL: + case SP_MINOTAUR: + case SP_RED_DRACONIAN: + case SP_MUMMY: + case SP_GHOUL: + case SP_VAMPIRE: + return (CC_RESTRICTED); + default: + return (CC_UNRESTRICTED); + } + + case JOB_THIEF: + return (CC_RESTRICTED); + + case JOB_ASSASSIN: + switch (speci) + { + case SP_HIGH_ELF: + case SP_DEEP_ELF: + case SP_MOUNTAIN_DWARF: + case SP_DEEP_DWARF: + case SP_HILL_ORC: + case SP_NAGA: + case SP_CENTAUR: + case SP_OGRE: + case SP_TROLL: + case SP_MINOTAUR: + case SP_RED_DRACONIAN: + return (CC_RESTRICTED); + default: + return (CC_UNRESTRICTED); + } + + case JOB_HUNTER: + switch (speci) + { + case SP_DEEP_DWARF: + case SP_KOBOLD: + case SP_NAGA: + case SP_RED_DRACONIAN: + case SP_MUMMY: + case SP_GHOUL: + case SP_VAMPIRE: + return (CC_RESTRICTED); + default: + return (CC_UNRESTRICTED); + } + + case JOB_ARTIFICER: + switch (speci) + { + case SP_CENTAUR: + case SP_TROLL: + case SP_MINOTAUR: + case SP_OGRE: + case SP_MUMMY: + case SP_GHOUL: + return (CC_RESTRICTED); + default: + return (CC_UNRESTRICTED); + } + + case JOB_WANDERER: + return (CC_RESTRICTED); + + default: + return (CC_BANNED); + } +} + +bool is_good_combination(species_type spc, job_type cls, bool good) +{ + const char_choice_restriction restrict = class_allowed(spc, cls); + + if (good) + return (restrict == CC_UNRESTRICTED); + + return (restrict != CC_BANNED); +} + +// Is the given book restricted for the character defined by ng? +// Only uses ng.species. +char_choice_restriction book_restriction(startup_book_type booktype, + const newgame_def &ng) +{ + ASSERT(is_valid_species(ng.species)); + switch (booktype) + { + case SBT_FIRE: // Fire + switch (ng.species) + { + case SP_HUMAN: + case SP_HIGH_ELF: + case SP_DEEP_ELF: + case SP_SLUDGE_ELF: + case SP_MOUNTAIN_DWARF: + case SP_HILL_ORC: + case SP_KOBOLD: + case SP_NAGA: + case SP_OGRE: + case SP_KENKU: + case SP_DEMIGOD: + case SP_DEMONSPAWN: + case SP_MUMMY: + return (CC_UNRESTRICTED); + + default: + if (species_genus(ng.species) == GENPC_DRACONIAN) + return (CC_UNRESTRICTED); + return (CC_RESTRICTED); + } + break; + + case SBT_COLD: // Ice + switch (ng.species) + { + case SP_HUMAN: + case SP_HIGH_ELF: + case SP_DEEP_ELF: + case SP_SLUDGE_ELF: + case SP_HILL_ORC: + case SP_MERFOLK: + case SP_KOBOLD: + case SP_NAGA: + case SP_OGRE: + case SP_KENKU: + case SP_DEMIGOD: + case SP_DEMONSPAWN: + case SP_MUMMY: + return (CC_UNRESTRICTED); + + default: + if (species_genus(ng.species) == GENPC_DRACONIAN) + return (CC_UNRESTRICTED); + return (CC_RESTRICTED); + } + break; + + case SBT_SUMM: // Summoning + switch (ng.species) + { + case SP_DEEP_ELF: + case SP_SLUDGE_ELF: + case SP_KOBOLD: + case SP_NAGA: + case SP_OGRE: + case SP_KENKU: + case SP_MUMMY: + case SP_VAMPIRE: + return (CC_UNRESTRICTED); + + default: + return (CC_RESTRICTED); + } + break; + + default: + return (CC_RESTRICTED); + } +} + +// Is the given god restricted for the character defined by ng? +// Only uses ng.species and ng.job. +char_choice_restriction weapon_restriction(weapon_type wpn, + const newgame_def &ng) +{ + ASSERT(is_valid_species(ng.species)); + ASSERT(is_valid_job(ng.job)); + switch (wpn) + { + case WPN_UNARMED: + if (species_has_claws(ng.species)) + return (CC_UNRESTRICTED); + return (CC_BANNED); + + case WPN_SHORT_SWORD: + switch (ng.species) + { + case SP_NAGA: + case SP_VAMPIRE: + // The fighter's heavy armour hinders stabbing. + if (ng.job == JOB_FIGHTER) + return (CC_RESTRICTED); + // else fall through + case SP_HIGH_ELF: + case SP_DEEP_ELF: + // Sludge elves have bad aptitudes with short swords (110) but are + // still better with them than any other starting weapon. + case SP_SLUDGE_ELF: + case SP_HALFLING: + case SP_KOBOLD: + case SP_SPRIGGAN: + return (CC_UNRESTRICTED); + + default: + return (CC_RESTRICTED); + } + + // Maces and hand axes usually share the same restrictions. + case WPN_MACE: + if (ng.species == SP_TROLL) + return (CC_UNRESTRICTED); + if (ng.species == SP_VAMPIRE) + return (CC_RESTRICTED); + // else fall-through + case WPN_HAND_AXE: + switch (ng.species) + { + case SP_HUMAN: + case SP_MOUNTAIN_DWARF: + case SP_DEEP_DWARF: + case SP_HILL_ORC: + case SP_MUMMY: + case SP_CENTAUR: + case SP_NAGA: + case SP_MINOTAUR: + case SP_KENKU: + case SP_DEMIGOD: + case SP_DEMONSPAWN: + case SP_VAMPIRE: + return (CC_UNRESTRICTED); + + default: + return (species_genus(ng.species) == GENPC_DRACONIAN ? CC_UNRESTRICTED + : CC_RESTRICTED); + } + + case WPN_SPEAR: + switch (ng.species) + { + case SP_HUMAN: + case SP_HILL_ORC: + case SP_MERFOLK: + case SP_NAGA: + case SP_CENTAUR: + case SP_MINOTAUR: + case SP_KENKU: + case SP_DEMIGOD: + case SP_DEMONSPAWN: + case SP_MUMMY: + return (CC_UNRESTRICTED); + + default: + return (species_genus(ng.species) == GENPC_DRACONIAN ? CC_UNRESTRICTED + : CC_RESTRICTED); + } + + case WPN_TRIDENT: + if (ng.species != SP_MERFOLK + && (ng.job != JOB_GLADIATOR + || species_size(ng.species, PSIZE_BODY) < SIZE_MEDIUM)) + { + return (CC_BANNED); + } + + // Tridents are strictly better than spears, so unrestrict them + // for some species whose Polearm aptitudes are not too bad. + switch (ng.species) + { + case SP_MOUNTAIN_DWARF: + case SP_OGRE: + case SP_GHOUL: + case SP_VAMPIRE: + return (CC_UNRESTRICTED); + default: + break; + } + + // Both are polearms, right? + return (weapon_restriction(WPN_SPEAR, ng)); + + case WPN_ANKUS: + if (species_genus(ng.species) == GENPC_OGRE) + return (CC_UNRESTRICTED); + // intentional fall-through + default: + return (CC_BANNED); + } +} + +// Is the given god restricted for the character defined by ng? +// Only uses ng.species and ng.job. +char_choice_restriction religion_restriction(god_type god, + const newgame_def &ng) +{ + ASSERT(is_valid_species(ng.species)); + ASSERT(is_valid_job(ng.job)); + + // Sanity check. + if (ng.species == SP_DEMIGOD) + return (CC_BANNED); + + switch (god) + { + case GOD_BEOGH: + if (ng.species == SP_HILL_ORC) + return (CC_UNRESTRICTED); + return (CC_BANNED); + + case GOD_ZIN: + switch (ng.species) + { + case SP_DEMONSPAWN: + case SP_MUMMY: + case SP_GHOUL: + case SP_VAMPIRE: + return (CC_BANNED); + case SP_SLUDGE_ELF: + case SP_MOUNTAIN_DWARF: + case SP_SPRIGGAN: + case SP_CENTAUR: + case SP_MINOTAUR: + case SP_OGRE: + return (CC_UNRESTRICTED); + default: + return (CC_RESTRICTED); + } + + case GOD_YREDELEMNUL: + switch (ng.species) + { + case SP_HILL_ORC: + // Restrict in favour of Beogh, else unrestricted. + if (ng.job == JOB_PRIEST) + return (CC_RESTRICTED); + return (CC_UNRESTRICTED); + + case SP_DEEP_ELF: + case SP_KENKU: + // Unrestrict these only for Priests as Zin is worse, but + // Necromancy (DK) the better choice. + if (ng.job == JOB_PRIEST) + return (CC_UNRESTRICTED); + return (CC_RESTRICTED); + + case SP_HUMAN: + case SP_HIGH_ELF: + case SP_SLUDGE_ELF: + case SP_MOUNTAIN_DWARF: + case SP_DEEP_DWARF: + case SP_MERFOLK: + case SP_HALFLING: + case SP_KOBOLD: + case SP_SPRIGGAN: + case SP_CENTAUR: + case SP_OGRE: + case SP_TROLL: + case SP_MINOTAUR: + case SP_DEMONSPAWN: + case SP_MUMMY: + case SP_GHOUL: + case SP_VAMPIRE: + return (CC_UNRESTRICTED); + default: + if (species_genus(ng.species) == GENPC_DRACONIAN) + return (CC_UNRESTRICTED); + return (CC_RESTRICTED); + } + + case GOD_XOM: + switch (ng.species) + { + case SP_MOUNTAIN_DWARF: + case SP_HILL_ORC: + case SP_MERFOLK: + case SP_CENTAUR: + case SP_OGRE: + case SP_TROLL: + case SP_MINOTAUR: + case SP_KENKU: + case SP_DEMONSPAWN: + return (CC_UNRESTRICTED); + default: + if (species_genus(ng.species) == GENPC_DRACONIAN) + return (CC_UNRESTRICTED); + return (CC_RESTRICTED); + } + + case GOD_MAKHLEB: + switch (ng.species) + { + case SP_HUMAN: + case SP_HIGH_ELF: + case SP_DEEP_ELF: + case SP_SLUDGE_ELF: + case SP_MOUNTAIN_DWARF: + case SP_DEEP_DWARF: + case SP_HILL_ORC: + case SP_MERFOLK: + case SP_HALFLING: + case SP_KOBOLD: + case SP_NAGA: + case SP_CENTAUR: + case SP_OGRE: + case SP_TROLL: + case SP_MINOTAUR: + case SP_DEMONSPAWN: + case SP_MUMMY: + case SP_GHOUL: + case SP_VAMPIRE: + return (CC_UNRESTRICTED); + default: + if (species_genus(ng.species) == GENPC_DRACONIAN) + return (CC_UNRESTRICTED); + return (CC_RESTRICTED); + } + + case GOD_LUGONU: + switch (ng.species) + { + case SP_HUMAN: + case SP_MOUNTAIN_DWARF: + case SP_HILL_ORC: + case SP_MERFOLK: + case SP_SPRIGGAN: + case SP_CENTAUR: + case SP_OGRE: + case SP_TROLL: + case SP_MINOTAUR: + case SP_DEMONSPAWN: + case SP_GHOUL: + case SP_VAMPIRE: + return (CC_UNRESTRICTED); + default: + if (species_genus(ng.species) == GENPC_DRACONIAN) + return (CC_UNRESTRICTED); + return (CC_RESTRICTED); + } + + default: + return (CC_RESTRICTED); + } +} diff --git a/crawl-ref/source/ng-restr.h b/crawl-ref/source/ng-restr.h new file mode 100644 index 0000000000..c4593999d6 --- /dev/null +++ b/crawl-ref/source/ng-restr.h @@ -0,0 +1,25 @@ +#ifndef NG_RESTR_H +#define NG_RESTR_H + +#include "newgame.h" + +enum char_choice_restriction +{ + CC_BANNED = 0, + CC_RESTRICTED, + CC_UNRESTRICTED +}; + +char_choice_restriction class_allowed(species_type speci, + job_type char_class); +bool is_good_combination(species_type spc, job_type cls, + bool good = false); +char_choice_restriction book_restriction(startup_book_type booktype, + const newgame_def &ng); +char_choice_restriction weapon_restriction(weapon_type wpn, + const newgame_def &ng); +char_choice_restriction religion_restriction(god_type god, + const newgame_def &ng); + +#endif + diff --git a/crawl-ref/source/player.cc b/crawl-ref/source/player.cc index 3f196501c7..1e59167c7e 100644 --- a/crawl-ref/source/player.cc +++ b/crawl-ref/source/player.cc @@ -446,42 +446,13 @@ bool player_under_penance(void) return (false); } +// TODO: get rid of this. bool player_genus(genus_type which_genus, species_type species) { if (species == SP_UNKNOWN) species = you.species; - switch (species) - { - case SP_RED_DRACONIAN: - case SP_WHITE_DRACONIAN: - case SP_GREEN_DRACONIAN: - case SP_YELLOW_DRACONIAN: - case SP_GREY_DRACONIAN: - case SP_BLACK_DRACONIAN: - case SP_PURPLE_DRACONIAN: - case SP_MOTTLED_DRACONIAN: - case SP_PALE_DRACONIAN: - case SP_BASE_DRACONIAN: - return (which_genus == GENPC_DRACONIAN); - - case SP_HIGH_ELF: - case SP_DEEP_ELF: - case SP_SLUDGE_ELF: - return (which_genus == GENPC_ELVEN); - - case SP_MOUNTAIN_DWARF: - case SP_DEEP_DWARF: - return (which_genus == GENPC_DWARVEN); - - case SP_OGRE: - return (which_genus == GENPC_OGRE); - - default: - break; - } - - return (false); + return (species_genus(species) == which_genus); } // If transform is true, compare with current transformation instead @@ -683,7 +654,7 @@ bool you_tran_can_wear(const item_def &item) return (true); } - if (fit_armour_size(item, player_size()) != 0) + if (fit_armour_size(item, you.body_size()) != 0) return (false); return you_tran_can_wear(get_armour_slot(item), true); @@ -795,7 +766,7 @@ bool player_weapon_wielded() // should never have a bad "shape" weapon in hand ASSERT( check_weapon_shape( you.inv[wpn], false ) ); - if (!check_weapon_wieldable_size( you.inv[wpn], player_size() )) + if (!check_weapon_wieldable_size( you.inv[wpn], you.body_size() )) return (false); */ @@ -2385,21 +2356,12 @@ bool player_is_shapechanged(void) return (true); } -// psize defaults to PSIZE_TORSO, which checks the part of the body -// that wears armour and wields weapons (which is different for some hybrids). -// base defaults to "false", meaning consider our current size, not our -// natural one. -size_type player_size(int psize, bool base) -{ - return you.body_size(psize, base); -} - // New and improved 4.1 evasion model, courtesy Brent Ross. int player_evasion() { - // XXX: player_size() implementations are incomplete, fix. - const size_type size = player_size(PSIZE_BODY); - const size_type torso = player_size(PSIZE_TORSO); + // XXX: you.body_size() implementations are incomplete, fix. + const size_type size = you.body_size(PSIZE_BODY); + const size_type torso = you.body_size(PSIZE_TORSO); const int size_factor = SIZE_MEDIUM - size; int ev = 10 + 2 * size_factor; @@ -6140,48 +6102,16 @@ bool player::can_pass_through_feat(dungeon_feature_type grid) const return !feat_is_solid(grid); } -size_type player::body_size(int psize, bool base) const +size_type player::body_size(size_part_type psize, bool base) const { - size_type ret = base ? SIZE_CHARACTER : transform_size(psize); - - if (ret == SIZE_CHARACTER) + if (base) + return species_size(species, psize); + else { - // Transformation has size of character's species. - switch (species) - { - case SP_OGRE: - case SP_TROLL: - ret = SIZE_LARGE; - break; - - case SP_NAGA: - // Most of their body is on the ground giving them a low profile. - if (psize == PSIZE_TORSO || psize == PSIZE_PROFILE) - ret = SIZE_MEDIUM; - else - ret = SIZE_LARGE; - break; - - case SP_CENTAUR: - ret = (psize == PSIZE_TORSO) ? SIZE_MEDIUM : SIZE_LARGE; - break; - - case SP_SPRIGGAN: - ret = SIZE_LITTLE; - break; - - case SP_HALFLING: - case SP_KOBOLD: - ret = SIZE_SMALL; - break; - - default: - ret = SIZE_MEDIUM; - break; - } + size_type tf_size = transform_size(psize); + return (tf_size == SIZE_CHARACTER ? species_size(species, psize) + : tf_size); } - - return (ret); } int player::body_weight() const @@ -7102,11 +7032,10 @@ int player::has_claws(bool allow_tran) const } } - // these are the only other sources for claws - if (species == SP_TROLL) - return (3); - if (species == SP_GHOUL) - return (1); + // XXX: Some assumptions about mutations and species in here. + int sp_claws = species_has_claws(species); + if (sp_claws > 0) + return (sp_claws); return (player_mutation_level(MUT_CLAWS)); } diff --git a/crawl-ref/source/player.h b/crawl-ref/source/player.h index d44e5dbfe7..687615a6eb 100644 --- a/crawl-ref/source/player.h +++ b/crawl-ref/source/player.h @@ -10,6 +10,7 @@ #include "actor.h" #include "itemprop.h" +#include "species.h" #ifdef USE_TILE // This used to be in tiles.h. (jpeg) @@ -335,7 +336,7 @@ public: bool extra_balanced() const; bool can_pass_through_feat(dungeon_feature_type grid) const; bool is_habitable_feat(dungeon_feature_type actual_grid) const; - size_type body_size(int psize = PSIZE_TORSO, bool base = false) const; + size_type body_size(size_part_type psize = PSIZE_TORSO, bool base = false) const; int body_weight() const; int total_weight() const; int damage_brand(int which_attack = -1); @@ -496,14 +497,6 @@ struct player_save_info class monsters; struct item_def; -enum genus_type -{ - GENPC_DRACONIAN, // 0 - GENPC_ELVEN, // 1 - GENPC_DWARVEN, // 2 - GENPC_OGRE -}; - bool move_player_to_grid( const coord_def& p, bool stepped, bool allow_shift, bool force, bool swapping = false ); @@ -874,7 +867,6 @@ void dec_disease_player(); bool rot_player(int amount); bool player_has_spell(spell_type spell); -size_type player_size(int psize = PSIZE_TORSO, bool base = false); item_def *player_slot_item(equipment_type eq); diff --git a/crawl-ref/source/species.cc b/crawl-ref/source/species.cc index cc01bba653..f68dfa83f0 100644 --- a/crawl-ref/source/species.cc +++ b/crawl-ref/source/species.cc @@ -191,8 +191,9 @@ std::string species_name(species_type speci, int level, bool genus, bool adj) { std::string res; - if (player_genus(GENPC_DRACONIAN, speci)) + switch (species_genus(speci)) { + case GENPC_DRACONIAN: if (adj || genus) // adj doesn't care about exact species res = "Draconian"; else @@ -221,9 +222,8 @@ std::string species_name(species_type speci, int level, bool genus, bool adj) } } } - } - else if (player_genus( GENPC_ELVEN, speci )) - { + break; + case GENPC_ELVEN: if (adj) // doesn't care about species/genus res = "Elven"; else if (genus) @@ -238,9 +238,8 @@ std::string species_name(species_type speci, int level, bool genus, bool adj) default: res = "Elf"; break; } } - } - else if (player_genus(GENPC_DWARVEN, speci)) - { + break; + case GENPC_DWARVEN: if (adj) // doesn't care about species/genus res = "Dwarven"; else if (genus) @@ -254,9 +253,9 @@ std::string species_name(species_type speci, int level, bool genus, bool adj) default: res = "Dwarf"; break; } } - } - else - { + break; + case GENPC_NONE: + default: switch (speci) { case SP_HUMAN: res = "Human"; break; @@ -285,3 +284,76 @@ std::string species_name(species_type speci, int level, bool genus, bool adj) } return res; } + +int species_has_claws(species_type species) +{ + if (species == SP_TROLL) + return (3); + if (species == SP_GHOUL) + return (1); + return (0); +} + +genus_type species_genus(species_type species) +{ + switch (species) + { + case SP_RED_DRACONIAN: + case SP_WHITE_DRACONIAN: + case SP_GREEN_DRACONIAN: + case SP_YELLOW_DRACONIAN: + case SP_GREY_DRACONIAN: + case SP_BLACK_DRACONIAN: + case SP_PURPLE_DRACONIAN: + case SP_MOTTLED_DRACONIAN: + case SP_PALE_DRACONIAN: + case SP_BASE_DRACONIAN: + return (GENPC_DRACONIAN); + + case SP_HIGH_ELF: + case SP_DEEP_ELF: + case SP_SLUDGE_ELF: + return (GENPC_ELVEN); + + case SP_MOUNTAIN_DWARF: + case SP_DEEP_DWARF: + return (GENPC_DWARVEN); + + case SP_OGRE: + return (GENPC_OGRE); + + default: + return (GENPC_NONE); + } +} + +size_type species_size(species_type species, size_part_type psize) +{ + switch (species) + { + case SP_OGRE: + case SP_TROLL: + return (SIZE_LARGE); + case SP_NAGA: + // Most of their body is on the ground giving them a low profile. + if (psize == PSIZE_TORSO || psize == PSIZE_PROFILE) + return (SIZE_MEDIUM); + else + return (SIZE_LARGE); + case SP_CENTAUR: + return ((psize == PSIZE_TORSO) ? SIZE_MEDIUM : SIZE_LARGE); + case SP_SPRIGGAN: + return (SIZE_LITTLE); + case SP_HALFLING: + case SP_KOBOLD: + return (SIZE_SMALL); + + default: + return(SIZE_MEDIUM); + } +} + +bool is_valid_species(species_type species) +{ + return (species >= 0 && species < NUM_SPECIES); +} diff --git a/crawl-ref/source/species.h b/crawl-ref/source/species.h index d84219847c..6648fda35f 100644 --- a/crawl-ref/source/species.h +++ b/crawl-ref/source/species.h @@ -1,6 +1,20 @@ #ifndef SPECIES_H #define SPECIES_H +enum genus_type +{ + GENPC_DRACONIAN, + GENPC_ELVEN, + GENPC_DWARVEN, + GENPC_OGRE, + GENPC_NONE +}; + +genus_type species_genus(species_type species); +int species_has_claws(species_type species); +size_type species_size(species_type species, + size_part_type psize = PSIZE_TORSO); + // from newgame.cc species_type get_species(const int index); species_type random_draconian_player_species(); @@ -15,5 +29,9 @@ std::string species_name(species_type speci, int level, bool genus = false, bool adj = false); species_type str_to_species(const std::string &species); + +// species_type bounds checking. +bool is_valid_species(species_type); + #endif -- cgit v1.2.3-54-g00ecf