summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source
diff options
context:
space:
mode:
authorRobert Vollmert <rvollmert@gmx.net>2009-10-24 12:42:13 +0200
committerRobert Vollmert <rvollmert@gmx.net>2009-10-24 14:31:30 +0200
commit394fb595f6d03fa9d266ed28726975e0b59bc798 (patch)
tree3a84b6c9ced49b07af9212a3447770ae53897ed5 /crawl-ref/source
parentea81f9787b7cba7a18ec7c098fcd0fe37fe7daef (diff)
downloadcrawl-ref-394fb595f6d03fa9d266ed28726975e0b59bc798.tar.gz
crawl-ref-394fb595f6d03fa9d266ed28726975e0b59bc798.zip
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.
Diffstat (limited to 'crawl-ref/source')
-rw-r--r--crawl-ref/source/abl-show.cc1
-rw-r--r--crawl-ref/source/actor.h2
-rw-r--r--crawl-ref/source/describe.cc6
-rw-r--r--crawl-ref/source/effects.cc2
-rw-r--r--crawl-ref/source/enum.h2
-rw-r--r--crawl-ref/source/fight.cc6
-rw-r--r--crawl-ref/source/item_use.cc16
-rw-r--r--crawl-ref/source/itemname.cc6
-rw-r--r--crawl-ref/source/itemprop.cc4
-rw-r--r--crawl-ref/source/jobs.cc4
-rw-r--r--crawl-ref/source/jobs.h3
-rw-r--r--crawl-ref/source/makefile.obj1
-rw-r--r--crawl-ref/source/mon-util.cc2
-rw-r--r--crawl-ref/source/monster.h2
-rw-r--r--crawl-ref/source/newgame.cc999
-rw-r--r--crawl-ref/source/newgame.h11
-rw-r--r--crawl-ref/source/ng-restr.cc929
-rw-r--r--crawl-ref/source/ng-restr.h25
-rw-r--r--crawl-ref/source/player.cc107
-rw-r--r--crawl-ref/source/player.h12
-rw-r--r--crawl-ref/source/species.cc92
-rw-r--r--crawl-ref/source/species.h18
22 files changed, 1169 insertions, 1081 deletions
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 <stdlib.h>
@@ -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<species_type>(sp),
+ if (is_good_combination(static_cast<species_type>(sp),
static_cast<job_type>(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,
@@ -1075,567 +1074,6 @@ game_start:
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);
- }
-
- case JOB_WANDERER:
- return (CC_RESTRICTED);
-
- default:
- return (CC_BANNED);
- }
-}
-
-static 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);
-}
-
static startup_book_type _book_to_start(int book)
{
switch (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