From 335b7bdaae97ddfaf4d388524cd146e84b328d38 Mon Sep 17 00:00:00 2001 From: j-p-e-g Date: Mon, 7 Apr 2008 20:54:43 +0000 Subject: Make vampires' metabolism dependant on their hunger state. Add several functions for later improved handling of stacks of !blood. git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@4109 c06c8d41-db1a-0410-9941-cceddc491573 --- crawl-ref/source/misc.cc | 354 +++++++++++++++++++++++++++++++++++++++----- crawl-ref/source/misc.h | 6 + crawl-ref/source/newgame.cc | 169 +++++++++++---------- crawl-ref/source/player.cc | 343 +++++++++++++++++++++++------------------- 4 files changed, 599 insertions(+), 273 deletions(-) diff --git a/crawl-ref/source/misc.cc b/crawl-ref/source/misc.cc index cc760a32ee..4af2cf122b 100644 --- a/crawl-ref/source/misc.cc +++ b/crawl-ref/source/misc.cc @@ -56,6 +56,7 @@ #include "items.h" #include "lev-pand.h" #include "macro.h" +#include "makeitem.h" #include "message.h" #include "mon-util.h" #include "monstuff.h" @@ -144,7 +145,7 @@ void turn_corpse_into_chunks( item_def &item ) // only fresh corpses bleed enough to colour the ground if (!food_is_rotten(item)) bleed_onto_floor(you.x_pos, you.y_pos, mons_class, max_chunks, true); - + item.base_type = OBJ_FOOD; item.sub_type = FOOD_CHUNK; item.quantity = 1 + random2( max_chunks ); @@ -158,6 +159,287 @@ void turn_corpse_into_chunks( item_def &item ) create_monster_hide(mons_class); } +// initialize blood potions with a vector of timers +void init_stack_blood_potions(item_def &stack, int age) +{ + ASSERT(stack.base_type == OBJ_POTIONS); + ASSERT(stack.sub_type == POT_BLOOD); + + CrawlHashTable &props = stack.props; + props.set_default_flags(SFLAG_CONST_TYPE); + props["timer"].new_vector(SV_LONG); + CrawlVector &timer = props["timer"]; + + // for a newly created stack, all potions use the same timer + const long max_age = you.num_turns + (age == -1 ? 1200 : age); + for (int i = 0; i < stack.quantity; i++) + timer.push_back(max_age); + + ASSERT(timer.size() == stack.quantity); + props.assert_validity(); +} + +// sort a CrawlVector, should probably be done properly with templates +static void _long_sort(CrawlVector &vec) +{ + std::vector help; + while (!vec.empty()) + help.push_back(vec.pop_back()); + + std::sort(help.begin(), help.end()); + + long val; + while (!help.empty()) + { + val = help[help.size() - 1]; + help.pop_back(); + vec.push_back(val); + } +} + +void maybe_coagulate_blood_floor(item_def &blood) +{ + ASSERT(is_valid_item(blood)); + ASSERT(blood.base_type == OBJ_POTIONS); + + ASSERT (blood.sub_type == POT_BLOOD + || blood.sub_type == POT_BLOOD_COAGULATED); + + CrawlHashTable &props = blood.props; + ASSERT(props.exists("timer")); + CrawlVector &timer = props["timer"]; + ASSERT(timer.size() == blood.quantity); + ASSERT(!timer.empty()); + + // blood.sub_type could be POT_BLOOD or POT_BLOOD_COAGULATED + // -> need different handling + int rot_limit = you.num_turns; + int coag_limit = you.num_turns + 200; // check 200 turns later + + // first count whether coagulating is even necessary + int rot_count = 0; + int coag_count = 0; + std::vector age_timer; + long current; + int size = timer.size(); + for (int i = 0; i < size; i++) + { + current = timer.pop_back(); + if (rot_limit >= current) + rot_count++; + else if (coag_limit >= current) + { + coag_count++; + age_timer.push_back(current); + } + else // still some time until rotting/coagulating + { + timer.push_back(current); + _long_sort(timer); + break; + } + } + + if (!rot_count && !coag_count) + return; // nothing to be done + + if (!coag_count) + { + dec_mitm_item_quantity(blood.link, rot_count); + // timer is already up to date + return; + } + + // coagulated blood cannot coagulate any further... + ASSERT(blood.sub_type == POT_BLOOD); + + // now that coagulating is necessary, check square for !coagulated blood + int o = igrd[blood.x][blood.y]; + while (o != NON_ITEM) + { + if (mitm[o].base_type == OBJ_POTIONS + && mitm[o].sub_type == POT_BLOOD_COAGULATED) + { + CrawlHashTable &props2 = mitm[o].props; + ASSERT(props2.exists("timer")); + CrawlVector &timer2 = props2["timer"]; + ASSERT(timer2.size() == mitm[o].quantity); + + // update timer -> push(pop) + long val; + while (!age_timer.empty()) + { + val = age_timer[age_timer.size() - 1]; + age_timer.pop_back(); + timer2.push_back(val); + } + _long_sort(timer2); + dec_mitm_item_quantity(blood.link, rot_count + coag_count); + return; + } + o = mitm[o].link; + } + + // if we got here nothing was found + // create a new stack of potions + o = get_item_slot( 100 + random2(200) ); + if (o == NON_ITEM) + return; + + // these values are common to all: {dlb} + mitm[o].base_type = OBJ_POTIONS; + mitm[o].sub_type = POT_BLOOD_COAGULATED; + mitm[o].quantity = coag_count; + mitm[o].plus = 0; + mitm[o].plus2 = 0; + mitm[o].special = 0; + mitm[o].flags = 0; + item_colour(mitm[o]); + + CrawlHashTable &props_new = mitm[o].props; + props_new.set_default_flags(SFLAG_CONST_TYPE); + props_new["timer"].new_vector(SV_LONG); + CrawlVector &timer_new = props_new["timer"]; + + long val; + while (!age_timer.empty()) + { + val = age_timer[age_timer.size() - 1]; + age_timer.pop_back(); + timer_new.push_back(val); + } + + ASSERT(timer_new.size() == coag_count); + props_new.assert_validity(); + move_item_to_grid( &o, blood.x, blood.y ); + + dec_mitm_item_quantity(blood.link, rot_count + coag_count); +} + +// used for (q)uaff, (f)ire, and Evaporate +void remove_oldest_potion_inv(item_def &stack) +{ + ASSERT(is_valid_item(stack)); + ASSERT(stack.base_type == OBJ_POTIONS); + + ASSERT (stack.sub_type == POT_BLOOD + || stack.sub_type == POT_BLOOD_COAGULATED); + + CrawlHashTable &props = stack.props; + ASSERT(props.exists("timer")); + CrawlVector &timer = props["timer"]; + ASSERT(timer.size() == stack.quantity); + ASSERT(!timer.empty()); + + // assuming already sorted, and first (oldest) potion valid + timer.pop_back(); + // the quantity will be decreased elsewhere +} + +// Should be called *after* drop_thing (and only if this returns true) +// unless the stack has been dropped in its entirety. +void drop_blood_potions_stack(int item, int quant) +{ + ASSERT(quant > 0); + // entire stack was dropped? + if (!is_valid_item(you.inv[item])) + return; + + item_def &stack = you.inv[item]; + ASSERT(stack.base_type == OBJ_POTIONS); + ASSERT(stack.sub_type == POT_BLOOD + || stack.sub_type == POT_BLOOD_COAGULATED); + + CrawlHashTable &props = stack.props; + ASSERT(props.exists("timer")); + CrawlVector &timer = props["timer"]; + ASSERT(!timer.empty()); + + // first check whether we can merge with an existing stack on the floor + int o = igrd[you.x_pos][you.y_pos]; + while (o != NON_ITEM) + { + if (mitm[o].base_type == OBJ_POTIONS + && mitm[o].sub_type == stack.sub_type) + { + CrawlHashTable &props2 = mitm[o].props; + ASSERT(props2.exists("timer")); + CrawlVector &timer2 = props2["timer"]; + + // update timer -> push(pop) + for (int i = 0; i < quant; i++) + timer2.push_back(timer.pop_back()); + + ASSERT(timer2.size() == mitm[o].quantity); + // re-sort timer + _long_sort(timer2); + + // now the stack timer should be correct again + ASSERT(timer.size() == stack.quantity); + return; + } + o = mitm[o].link; + } + + // If we got here nothing was found. + // Stuff could have been destroyed or offered, either case we'll + // have to reduce the timer vector anyway. + while (!timer.empty() && quant-- > 0) + timer.pop_back(); + + ASSERT(stack.quantity == timer.size()); +} + +// Should be called *after* move_item_to_player +// unless the stack has been picked up in its entirety. +void pick_up_blood_potions_stack(int item, int quant) +{ + ASSERT(quant > 0); + // entire stack was taken? + if (!is_valid_item(mitm[item])) + return; + + item_def &stack = mitm[item]; + ASSERT(stack.base_type == OBJ_POTIONS); + ASSERT(stack.sub_type == POT_BLOOD + || stack.sub_type == POT_BLOOD_COAGULATED); + + CrawlHashTable &props = stack.props; + ASSERT(props.exists("timer")); + CrawlVector &timer = props["timer"]; + ASSERT(!timer.empty()); + + // first check whether we can merge with an existing stack in inventory + for (int m = 0; m < ENDOFPACK; m++) + { + if (!is_valid_item(you.inv[m])) + continue; + + if (you.inv[m].base_type == OBJ_POTIONS + && you.inv[m].sub_type == stack.sub_type) + { + CrawlHashTable &props2 = you.inv[m].props; + ASSERT(props2.exists("timer")); + CrawlVector &timer2 = props2["timer"]; + + // update timer -> push(pop) + for (int i = 0; i < quant; i++) + timer2.push_back(timer.pop_back()); + + ASSERT(timer2.size() == you.inv[m].quantity); + // re-sort timer + _long_sort(timer2); + + // now the stack timer should be correct again + ASSERT(timer.size() == stack.quantity); + return; + } + } + + // If we got here nothing was found. Huh? + ASSERT(stack.quantity == timer.size()); +} + // Deliberately don't check for rottenness here, so this check // can also be used to verify whether you *could* have bottled // a now rotten corpse. @@ -172,7 +454,7 @@ bool can_bottle_blood_from_corpse(int mons_type) int chunk_type = mons_corpse_effect( mons_type ); if (chunk_type == CE_CLEAN || chunk_type == CE_CONTAMINATED) return (true); - + return (false); } @@ -195,7 +477,7 @@ void turn_corpse_into_blood_potions( item_def &item ) const int max_chunks = mons_weight( mons_class ) / 150; item.quantity = 1 + random2( max_chunks/3 ); item.quantity = stepdown_value( item.quantity, 2, 2, 6, 6 ); - + // lower number of potions obtained from contaminated chunk type corpses if (mons_corpse_effect( mons_class ) == CE_CONTAMINATED) { @@ -326,7 +608,7 @@ static bool allow_bleeding_on_square(int x, int y) // the good gods like to keep their altars pristine if (is_good_god(grid_altar_god(grd[x][y]))) return (false); - + return (true); } @@ -347,7 +629,7 @@ static void maybe_bloodify_square(int x, int y, int amount, bool spatter = false #endif if (allow_bleeding_on_square(x,y)) env.map[x][y].property = FPROP_BLOODY; - + // if old or new blood on square, the smell reaches further if (env.map[x][y].property == FPROP_BLOODY) blood_smell(12, x, y); @@ -362,7 +644,7 @@ static void maybe_bloodify_square(int x, int y, int amount, bool spatter = false { if (i == 0 && j == 0) // current square continue; - + // spattering onto walls etc. less likely if (grd[x+i][y+j] < DNGN_MINMOVE && one_chance_in(3)) continue; @@ -506,7 +788,7 @@ void in_a_cloud() if (hurted < 1) hurted = 0; else - ouch( (hurted * you.time_taken) / 10, cl, KILLED_BY_CLOUD, + ouch( (hurted * you.time_taken) / 10, cl, KILLED_BY_CLOUD, "noxious fumes" ); if (1 + random2(27) >= you.experience_level) @@ -549,7 +831,7 @@ void in_a_cloud() mpr("You are engulfed in poison gas!"); if (!player_res_poison()) { - ouch( (random2(10) * you.time_taken) / 10, cl, KILLED_BY_CLOUD, + ouch( (random2(10) * you.time_taken) / 10, cl, KILLED_BY_CLOUD, "poison gas" ); poison_player(1); } @@ -694,7 +976,7 @@ static void leaving_level_now() // markers to be discarded. const std::string newtype = env.markers.property_at(you.pos(), MAT_ANY, "dst"); - + dungeon_events.fire_position_event(DET_PLAYER_CLIMBS, you.pos()); dungeon_events.fire_event(DET_LEAVING_LEVEL); @@ -803,14 +1085,14 @@ void up_stairs(dungeon_feature_type force_stair, // the overloaded character makes an attempt... so we're doing this // check before that one. -- bwr if (!player_is_airborne() - && you.duration[DUR_CONF] - && (stair_find >= DNGN_STONE_STAIRS_UP_I + && you.duration[DUR_CONF] + && (stair_find >= DNGN_STONE_STAIRS_UP_I && stair_find <= DNGN_STONE_STAIRS_UP_III) && random2(100) > you.dex) { mpr("In your confused state, you trip and fall back down the stairs."); - ouch( roll_dice( 3 + you.burden_state, 5 ), 0, + ouch( roll_dice( 3 + you.burden_state, 5 ), 0, KILLED_BY_FALLING_DOWN_STAIRS ); you.turn_is_over = true; @@ -834,7 +1116,7 @@ void up_stairs(dungeon_feature_type force_stair, // Checks are done, the character is committed to moving between levels. leaving_level_now(); - + int old_level = you.your_level; // Interlevel travel data: @@ -859,7 +1141,7 @@ void up_stairs(dungeon_feature_type force_stair, for (i = 0; i < ENDOFPACK; i++) { - if (is_valid_item( you.inv[i] ) + if (is_valid_item( you.inv[i] ) && you.inv[i].base_type == OBJ_ORBS) { ouch(INSTANT_DEATH, 0, KILLED_BY_WINNING); @@ -959,7 +1241,7 @@ void up_stairs(dungeon_feature_type force_stair, // Tell stash-tracker and travel that we've changed levels. trackers_init_new_level(true); - + #ifdef USE_TILE TileNewLevel(newlevel); #endif // USE_TILE @@ -972,7 +1254,7 @@ void up_stairs(dungeon_feature_type force_stair, if (can_travel_interlevel()) { - LevelInfo &new_level_info = + LevelInfo &new_level_info = travel_cache.get_level_info(new_level_id); new_level_info.update(); @@ -981,7 +1263,7 @@ void up_stairs(dungeon_feature_type force_stair, // First we update the old level's stair. level_pos lp; lp.id = new_level_id; - lp.pos.x = you.x_pos; + lp.pos.x = you.x_pos; lp.pos.y = you.y_pos; bool guess = false; @@ -1121,7 +1403,7 @@ void down_stairs( int old_level, dungeon_feature_type force_stair, // Fire level-leaving trigger. leaving_level_now(); - + #ifdef DGL_MILESTONES if (!force_stair) { @@ -1195,7 +1477,7 @@ void down_stairs( int old_level, dungeon_feature_type force_stair, // Preserve abyss uniques now, since this Abyss level will be deleted. if (you.level_type == LEVEL_ABYSS) save_abyss_uniques(); - + if (you.level_type != LEVEL_DUNGEON && (you.level_type != LEVEL_PANDEMONIUM || stair_find != DNGN_TRANSIT_PANDEMONIUM)) @@ -1273,15 +1555,15 @@ void down_stairs( int old_level, dungeon_feature_type force_stair, mprf("Welcome back to %s!", branches[you.where_are_you].longname); if (!player_is_airborne() - && you.duration[DUR_CONF] + && you.duration[DUR_CONF] && !grid_is_escape_hatch(stair_find) && random2(100) > you.dex) { mpr("In your confused state, you trip and fall down the stairs."); - // Nastier than when climbing stairs, but you'll aways get to + // Nastier than when climbing stairs, but you'll aways get to // your destination, -- bwr - ouch( roll_dice( 6 + you.burden_state, 10 ), 0, + ouch( roll_dice( 6 + you.burden_state, 10 ), 0, KILLED_BY_FALLING_DOWN_STAIRS ); } @@ -1436,7 +1718,7 @@ void down_stairs( int old_level, dungeon_feature_type force_stair, { you.your_level--; } - + switch (you.level_type) { @@ -1491,7 +1773,7 @@ void down_stairs( int old_level, dungeon_feature_type force_stair, you.beheld_by.clear(); you.duration[DUR_BEHELD] = 0; } - + viewwindow(1, true); if (you.skills[SK_TRANSLOCATIONS] > 0 && !allow_control_teleport( true )) @@ -1511,20 +1793,20 @@ void down_stairs( int old_level, dungeon_feature_type force_stair, if (can_travel_interlevel()) { - LevelInfo &new_level_info = + LevelInfo &new_level_info = travel_cache.get_level_info(new_level_id); new_level_info.update(); // First we update the old level's stair. level_pos lp; lp.id = new_level_id; - lp.pos.x = you.x_pos; + lp.pos.x = you.x_pos; lp.pos.y = you.y_pos; old_level_info.update_stair(stair_x, stair_y, lp); // Then the new level's stair, assuming arbitrarily that going - // upstairs will land you on the same downstairs you took to begin + // upstairs will land you on the same downstairs you took to begin // with (not necessarily true). lp.id = old_level_id; lp.pos.x = stair_x; @@ -1557,7 +1839,7 @@ std::string level_description_string() { if (you.level_type_name == "bazaar") return "- a Bazaar"; - + return "- a Portal Chamber"; } @@ -1707,7 +1989,7 @@ bool go_berserk(bool intentional) if (Options.tutorial_left) Options.tut_berserk_counter++; - + mpr("A red film seems to cover your vision as you go berserk!"); mpr("You feel yourself moving faster!"); mpr("You feel mighty!"); @@ -1920,7 +2202,7 @@ bool i_feel_safe(bool announce, bool want_move) } return (mons.empty()); } - + return true; } @@ -1943,7 +2225,7 @@ int str_to_shoptype(const std::string &s) { if (s == "random" || s == "any") return (SHOP_RANDOM); - + for (unsigned i = 0; i < sizeof(shop_types) / sizeof (*shop_types); ++i) { if (s == shop_types[i]) @@ -2051,7 +2333,7 @@ void setup_environment_effects() continue; const int grid = grd[x][y]; - if (grid == DNGN_LAVA + if (grid == DNGN_LAVA || (grid == DNGN_SHALLOW_WATER && you.where_are_you == BRANCH_SWAMP)) { @@ -2069,10 +2351,10 @@ static void apply_environment_effect(const coord_def &c) { const int grid = grd[c.x][c.y]; if (grid == DNGN_LAVA) - check_place_cloud( CLOUD_BLACK_SMOKE, + check_place_cloud( CLOUD_BLACK_SMOKE, c.x, c.y, random_range( 4, 8 ), KC_OTHER ); else if (grid == DNGN_SHALLOW_WATER) - check_place_cloud( CLOUD_MIST, + check_place_cloud( CLOUD_MIST, c.x, c.y, random_range( 2, 5 ), KC_OTHER ); } @@ -2140,7 +2422,7 @@ coord_def pick_adjacent_free_square(int x, int y) // Converts a movement speed to a duration. i.e., answers the // question: if the monster is so fast, how much time has it spent in // its last movement? -// +// // If speed is 10 (normal), one movement is a duration of 10. // If speed is 1 (very slow), each movement is a duration of 100. // If speed is 15 (50% faster than normal), each movement is a duration of @@ -2151,7 +2433,7 @@ int speed_to_duration(int speed) speed = 10; else if (speed > 100) speed = 100; - + return div_rand_round(100, speed); } diff --git a/crawl-ref/source/misc.h b/crawl-ref/source/misc.h index 0a7ca790e5..f4cffde844 100644 --- a/crawl-ref/source/misc.h +++ b/crawl-ref/source/misc.h @@ -68,6 +68,12 @@ void trackers_init_new_level(bool transit); * *********************************************************************** */ void turn_corpse_into_chunks( item_def &item ); +void init_stack_blood_potions( item_def &stack, int age = -1 ); +void maybe_coagulate_blood_potions_floor( item_def &blood ); +void remove_oldest_potion_inv( item_def &stack ); +void drop_blood_potions_stack( int item, int quant ); +void pick_up_blood_potions_stack( int item, int quant ); + bool can_bottle_blood_from_corpse( int mons_type ); void turn_corpse_into_blood_potions ( item_def &item ); void split_blood_potions_into_decay( int obj, int amount = -1 ); diff --git a/crawl-ref/source/newgame.cc b/crawl-ref/source/newgame.cc index e4d6db96e1..e19980f525 100644 --- a/crawl-ref/source/newgame.cc +++ b/crawl-ref/source/newgame.cc @@ -263,7 +263,7 @@ static const char * Species_Abbrev_List[ NUM_SPECIES ] = int get_species_index_by_abbrev( const char *abbrev ) { COMPILE_CHECK(ARRAYSIZE(Species_Abbrev_List) == NUM_SPECIES, c1); - + for (unsigned i = 0; i < ARRAYSIZE(old_species_order); i++) { const int sp = (Options.use_old_selection_order ? old_species_order[i] @@ -350,13 +350,13 @@ static const char * Class_Name_List[ NUM_JOBS ] = int get_class_index_by_abbrev( const char *abbrev ) { COMPILE_CHECK(ARRAYSIZE(Class_Abbrev_List) == NUM_JOBS, c1); - + unsigned int job; for (unsigned int i = 0; i < ARRAYSIZE(old_jobs_order); i++) { job = (Options.use_old_selection_order ? old_jobs_order[i] : new_jobs_order[i]); - + if (tolower( abbrev[0] ) == tolower( Class_Abbrev_List[job][0] ) && tolower( abbrev[1] ) == tolower( Class_Abbrev_List[job][1] )) { @@ -393,7 +393,7 @@ int get_class_by_abbrev( const char *abbrev ) int get_class_index_by_name( const char *name ) { COMPILE_CHECK(ARRAYSIZE(Class_Name_List) == NUM_JOBS, c1); - + char *ptr; char lowered_buff[80]; char lowered_class[80]; @@ -526,7 +526,7 @@ static std::string _prev_startup_description(void) if (Options.prev_cls == '?') return "Random " + _get_opt_race_name(Options.prev_race); - + return _get_opt_race_name(Options.prev_race) + " " + _get_opt_class_name(Options.prev_cls); } @@ -535,7 +535,7 @@ static std::string _prev_startup_description(void) static void _print_character_info() { clrscr(); - + // At this point all of name, species and class should be decided. if (strlen(you.your_name) > 0 && you.char_class != JOB_UNKNOWN && you.species != SP_UNKNOWN) @@ -567,7 +567,7 @@ int give_first_conjuration_book() // choose randomly based on the species weighting, again // ignoring air/earth which are secondary in these books. -- bwr if (random2( species_skills( SK_ICE_MAGIC, you.species ) ) - < random2( species_skills( SK_FIRE_MAGIC, you.species ) )) + < random2( species_skills( SK_FIRE_MAGIC, you.species ) )) { book = BOOK_CONJURATIONS_II; } @@ -588,7 +588,7 @@ static bool _is_species_valid_choice(species_type species, bool display = true) return (false); // no problem with these - if (species <= SP_RED_DRACONIAN || species > SP_BASE_DRACONIAN) + if (species <= SP_RED_DRACONIAN || species > SP_BASE_DRACONIAN) return (true); // draconians other than red return false if display == true @@ -704,7 +704,7 @@ static unsigned char _random_potion_description() // in itemname.cc; this check ensures clear potions don't // get odd qualifiers. } - while ((colour == PDC_CLEAR && nature > PDQ_VISCOUS) + while ((colour == PDC_CLEAR && nature > PDQ_VISCOUS) || desc == PDESCS(PDC_CLEAR) || desc == PDESCQ(PDQ_GLUGGY, PDC_WHITE)); @@ -755,9 +755,9 @@ static int _get_random_coagulated_blood_desc() qualifier = PDQ_VISCOUS; break; } - + potion_description_colour_type colour = (coinflip() ? PDC_RED : PDC_BROWN); - + return PDESCQ(qualifier, colour); } @@ -781,7 +781,7 @@ static void _initialise_item_descriptions() NUM_JEWELLERY, you.item_description.height(), NUM_STAVES }; - + for (int i = 0; i < NUM_IDESC; i++) { // only loop until NUM_WANDS etc. @@ -945,7 +945,7 @@ static void _reassess_starting_skills() const int sp_diff = species_skills( i, you.species ); you.skills[i] = 0; - for (int lvl = 1; lvl <= 8; lvl++) + for (int lvl = 1; lvl <= 8; lvl++) { if (you.skill_points[i] > (skill_exp_needed(lvl+1) * sp_diff)/100) you.skills[i] = lvl; @@ -1161,7 +1161,7 @@ game_start: end(1, false, "Incompatible race and class specified in " "options file."); } - + // repeat until valid race/class combination found while (choose_race() && !choose_class()); } @@ -1177,7 +1177,7 @@ game_start: if (specs.length() > 79) specs = specs.substr(0, 79); - cprintf( "You are a%s %s %s." EOL, + cprintf( "You are a%s %s %s." EOL, (is_vowel( specs[0] )) ? "n" : "", specs.c_str(), you.class_name ); @@ -1224,7 +1224,7 @@ game_start: { // now choose again, name stays same const std::string old_name = you.your_name; - + Options.prev_randpick = false; Options.prev_race = ng_race; Options.prev_cls = ng_cls; @@ -1236,8 +1236,8 @@ game_start: _init_player(); Options.reset_startup_options(); - - // Restore old name + + // Restore old name strncpy(you.your_name, old_name.c_str(), kNameLen); you.your_name[kNameLen - 1] = 0; @@ -1270,7 +1270,7 @@ game_start: you.inv[i].flags |= ISFLAG_BEEN_IN_INV; // identify all items in pack - set_ident_type( you.inv[i].base_type, + set_ident_type( you.inv[i].base_type, you.inv[i].sub_type, ID_KNOWN_TYPE ); // link properly you.inv[i].x = -1; @@ -1295,14 +1295,14 @@ game_start: // make sure the starting player is fully charged up set_hp( you.hp_max, false ); - set_mp( you.max_magic_points, false ); + set_mp( you.max_magic_points, false ); _give_basic_spells(you.char_class); _give_basic_knowledge(you.char_class); // tmpfile purging removed in favour of marking tmp_file_pairs.init(false); - + _give_basic_mutations(you.species); _initialise_branch_depths(); @@ -1924,7 +1924,7 @@ static bool _choose_book( item_def& book, int firstbook, int numbooks ) if ( !Options.random_pick ) { _print_character_info(); - + textcolor( CYAN ); cprintf(EOL "You have a choice of books:" EOL); textcolor( LIGHTGREY ); @@ -1939,7 +1939,7 @@ static bool _choose_book( item_def& book, int firstbook, int numbooks ) cprintf(EOL "* - Random choice; " "Bksp - Back to species and class selection; " "X - Quit" EOL); - + if ( Options.prev_book != SBT_NO_SELECTION ) { cprintf("; Enter - %s", @@ -1950,7 +1950,7 @@ static bool _choose_book( item_def& book, int firstbook, int numbooks ) : "Buggy Book"); } cprintf(EOL); - + do { textcolor( CYAN ); @@ -1958,7 +1958,7 @@ static bool _choose_book( item_def& book, int firstbook, int numbooks ) textcolor( LIGHTGREY ); keyin = c_getch(); - + switch (keyin) { case 'X': @@ -1989,14 +1989,14 @@ static bool _choose_book( item_def& book, int firstbook, int numbooks ) ng_book = SBT_RANDOM; else ng_book = keyin - 'a' + 1; - + if ( Options.random_pick || keyin == '*' ) keyin = random2(numbooks) + 'a'; book.sub_type = firstbook + keyin - 'a'; return true; } - + static bool _choose_weapon() { const weapon_type startwep[5] = { WPN_SHORT_SWORD, WPN_MACE, @@ -2044,7 +2044,7 @@ static bool _choose_weapon() cprintf(EOL "* - Random choice; " "Bksp - Back to species and class selection; " "X - Quit" EOL); - + if (Options.prev_weapon != WPN_UNKNOWN) { cprintf("; Enter - %s", @@ -2052,7 +2052,7 @@ static bool _choose_weapon() weapon_base_name(Options.prev_weapon)); } cprintf(EOL); - + do { textcolor( CYAN ); @@ -2158,8 +2158,8 @@ static void _species_stat_init(species_type which_species) int ib = 0; // intelligence base int db = 0; // dexterity base - // Note: The stats in in this list aren't intended to sum the same - // for all races. The fact that Mummies and Ghouls are really low + // Note: The stats in in this list aren't intended to sum the same + // for all races. The fact that Mummies and Ghouls are really low // is considered acceptable (Mummies don't have to eat, and Ghouls // are supposted to be a really hard race). Also note that Demigods // and Demonspawn get seven more random points added later. -- bwr @@ -2339,7 +2339,6 @@ static void _give_basic_mutations(species_type speci) break; case SP_VAMPIRE: you.mutation[MUT_FANGS] = 3; - you.mutation[MUT_SLOW_METABOLISM] = 1; you.mutation[MUT_ACUTE_VISION] = 1; break; default: @@ -2467,7 +2466,7 @@ static void _opening_screen(void) const bool init_found = (init_file_location.find("not found") == std::string::npos); - + if (!init_found) msg += "Init file "; else @@ -2475,7 +2474,7 @@ static void _opening_screen(void) msg += init_file_location; msg += EOL; - + formatted_string::parse_string(msg).display(); textcolor( LIGHTGREY ); return; @@ -2498,7 +2497,7 @@ static void _show_name_prompt(int where, bool blankOK, } else { - cprintf(EOL + cprintf(EOL "Press to answer this after race and " "class are chosen." EOL); } @@ -2629,7 +2628,7 @@ static void _enter_player_name(bool blankOK) if (blankOK && (ask_name || !_is_good_name(you.your_name, false, false))) { existing_chars = find_saved_characters(); - if (existing_chars.empty()) + if (existing_chars.empty()) { cgotoxy(1,12); formatted_string::parse_string( @@ -2702,9 +2701,9 @@ static bool _validate_player_name(bool verbose) { char c = *pn; // Note that this includes systems which may be using the - // packaging system. The packaging system is very simple + // packaging system. The packaging system is very simple // and doesn't take the time to escape every characters that - // might be a problem for some random shell or OS... so we + // might be a problem for some random shell or OS... so we // play it very conservative here. -- bwr if (!isalnum(c) && c != '-' && c != '.' && c != '_' && c != ' ') { @@ -2860,7 +2859,7 @@ static void _make_rod(item_def &item, stave_type rod_type) item.quantity = 1; item.special = you.item_description[IDESC_STAVES][rod_type]; item.colour = BROWN; - + init_rod_mp(item); } @@ -2881,7 +2880,7 @@ static void _newgame_make_item(int slot, equipment_type eqslot, } ASSERT(slot != -1); } - + item_def &item(you.inv[slot]); item.base_type = base; item.sub_type = sub_type; @@ -3015,7 +3014,7 @@ static void _create_wanderer( void ) you.skills[skill] = you.skills[SK_INVOCATIONS]; you.skills[SK_INVOCATIONS] = 0; } - + // ogres and draconians cannot wear armour if ((you.species == SP_OGRE_MAGE || player_genus(GENPC_DRACONIAN)) && you.skills[ SK_ARMOUR ]) @@ -3130,13 +3129,13 @@ bool choose_race() you.char_class = _get_class(letter_to_index(Options.cls)); ng_cls = Options.cls; } - + if (Options.race != 0) printed = true; // the list musn't be longer than the number of actual species COMPILE_CHECK(ARRAYSIZE(old_species_order) <= NUM_SPECIES, c1); - + // check whether the two lists have the same size COMPILE_CHECK(ARRAYSIZE(old_species_order) == ARRAYSIZE(new_species_order), c2); @@ -3172,7 +3171,7 @@ spec_query: if (!shortgreet) cprintf("."); - + textcolor( WHITE ); // for the tutorial } else @@ -3193,7 +3192,7 @@ spec_query: for (int i = 0; i < num_species; ++i) { const species_type si = _get_species(i); - + if (!_is_species_valid_choice(si)) continue; @@ -3204,7 +3203,7 @@ spec_query: } char sletter = index_to_letter(i); - + if (sletter == Options.prev_race) prevraceok = true; @@ -3217,12 +3216,12 @@ spec_query: j++; } - + if (j % 2) cprintf(EOL); textcolor( BROWN ); - + if (you.char_class == JOB_UNKNOWN) cprintf(EOL "SPACE - Choose class first; * - Random Species; " @@ -3230,7 +3229,7 @@ spec_query: EOL); else cprintf(EOL - "* - Random; Bksp - Back to class selection; X - Quit" + "* - Random; Bksp - Back to class selection; X - Quit" EOL); if (Options.prev_race) @@ -3242,7 +3241,7 @@ spec_query: } if (_prev_startup_options_set()) { - cprintf("%sTAB - %s", + cprintf("%sTAB - %s", prevraceok? "; " : "", _prev_startup_description().c_str()); } @@ -3321,7 +3320,7 @@ spec_query: { return !pick_tutorial(); } - + bool randrace = (keyn == '*'); if (randrace) { @@ -3336,12 +3335,12 @@ spec_query: keyn = index_to_letter(index); } - + if (keyn >= 'a' && keyn <= 'z' || keyn >= 'A' && keyn <= 'Z') { you.species = _get_species(letter_to_index(keyn)); } - + if (!_is_species_valid_choice( you.species )) { if (Options.race != 0) @@ -3382,7 +3381,7 @@ bool choose_class(void) return true; ng_cls = 0; - + // the list musn't be longer than the number of actual classes COMPILE_CHECK(ARRAYSIZE(old_jobs_order) <= NUM_JOBS, c1); @@ -3458,7 +3457,7 @@ job_query: else { cprintf(EOL - "* - Random; Bksp - Back to species selection; X - Quit" + "* - Random; Bksp - Back to species selection; X - Quit" EOL); } @@ -3471,13 +3470,13 @@ job_query: } if (_prev_startup_options_set()) { - cprintf("%sTAB - %s", + cprintf("%sTAB - %s", prevclassok? "; " : "", _prev_startup_description().c_str()); } cprintf(EOL); } - + textcolor( CYAN ); cprintf(EOL "Which one? "); textcolor( LIGHTGREY ); @@ -3587,7 +3586,7 @@ job_query: } goto job_query; } - + if (you.species != SP_UNKNOWN && !_class_allowed(you.species, chosen_job)) { @@ -3617,7 +3616,7 @@ bool _give_items_skills() { case JOB_FIGHTER: _newgame_make_item(0, EQ_WEAPON, OBJ_WEAPONS, WPN_SHORT_SWORD); - + if (you.species == SP_OGRE || you.species == SP_TROLL) { _newgame_make_item(1, EQ_BODY_ARMOUR, OBJ_ARMOUR, ARM_ANIMAL_SKIN); @@ -3631,7 +3630,7 @@ bool _give_items_skills() { if (!_choose_weapon()) return (false); - + _newgame_make_item(1, EQ_BODY_ARMOUR, OBJ_ARMOUR, ARM_ROBE); _newgame_make_item(2, EQ_SHIELD, OBJ_ARMOUR, ARM_SHIELD); } @@ -3640,7 +3639,7 @@ bool _give_items_skills() { if (!_choose_weapon()) return false; - + _newgame_make_item(1, EQ_BODY_ARMOUR, OBJ_ARMOUR, ARM_LEATHER_ARMOUR); @@ -3678,7 +3677,7 @@ bool _give_items_skills() { if (you.species == SP_TROLL) //jmf: these guys get no weapon! you.skills[SK_UNARMED_COMBAT] += 3; - else + else you.skills[SK_FIGHTING] += 2; // BWR sez Ogres & Trolls should probably start w/ Dodge 2 -- GDL @@ -3696,10 +3695,10 @@ bool _give_items_skills() you.skills[(player_light_armour()? SK_DODGING : SK_ARMOUR)] = 2; you.skills[SK_THROWING] = 2; - + if (you.species != SP_VAMPIRE) you.skills[SK_SHIELDS] = 2; - + if (you.species == SP_VAMPIRE || coinflip()) you.skills[SK_STABBING]++; else @@ -3750,7 +3749,7 @@ bool _give_items_skills() if (player_genus(GENPC_DWARVEN)) you.skills[SK_MACES_FLAILS] = 1; - else + else you.skills[SK_SHORT_BLADES] = 1; you.skills[SK_STAVES] = 1; @@ -3767,12 +3766,12 @@ bool _give_items_skills() if (you.is_undead != US_UNDEAD) _newgame_make_item(2, EQ_NONE, OBJ_POTIONS, POT_HEALING, 2); - + you.skills[SK_FIGHTING] = 2; you.skills[SK_DODGING] = 1; you.skills[SK_INVOCATIONS] = 4; you.skills[ weapon_skill(you.inv[0]) ] = 2; - + // set gods if (you.species == SP_MUMMY || you.species == SP_DEMONSPAWN) { @@ -3789,17 +3788,17 @@ bool _give_items_skills() else if (Options.random_pick || Options.priest == GOD_RANDOM) { you.religion = coinflip() ? GOD_YREDELEMNUL : GOD_ZIN; - + // for orcs 50% chance of Beogh instead if (you.species == SP_HILL_ORC && coinflip()) you.religion = GOD_BEOGH; - + ng_pr = GOD_RANDOM; } else { _print_character_info(); - + textcolor( CYAN ); cprintf(EOL "Which god do you wish to serve?" EOL); @@ -3879,7 +3878,7 @@ bool _give_items_skills() } } while (you.religion == GOD_NO_GOD); - + ng_pr = (keyn == '*'? GOD_RANDOM : you.religion); } } @@ -3906,7 +3905,7 @@ bool _give_items_skills() case JOB_GLADIATOR: _newgame_make_item(0, EQ_WEAPON, OBJ_WEAPONS, WPN_SHORT_SWORD); - + if (!_choose_weapon()) return false; @@ -3929,7 +3928,7 @@ bool _give_items_skills() } else you.skills[SK_DODGING] = 1; - + you.skills[SK_FIGHTING] = 3; weap_skill = 3; @@ -4095,7 +4094,7 @@ bool _give_items_skills() you.inv[3].sub_type = MI_LARGE_ROCK; you.inv[3].quantity = 4; break; - + case SP_HALFLING: case SP_GNOME: you.inv[3].quantity += random2avg(15, 2); @@ -4219,7 +4218,7 @@ bool _give_items_skills() case JOB_EARTH_ELEMENTALIST: _newgame_make_item(2, EQ_NONE, OBJ_BOOKS, BOOK_GEOMANCY); _newgame_make_item(3, EQ_NONE, OBJ_MISSILES, MI_STONE, 20); - + if (you.species == SP_GNOME) { _newgame_make_item(1, EQ_NONE, OBJ_WEAPONS, WPN_SLING); @@ -4361,10 +4360,10 @@ bool _give_items_skills() case JOB_CRUSADER: _newgame_make_item(0, EQ_WEAPON, OBJ_WEAPONS, WPN_SHORT_SWORD); - + if (!_choose_weapon()) return false; - + weap_skill = 2; _newgame_make_item(1, EQ_BODY_ARMOUR, OBJ_ARMOUR, ARM_ROBE); _newgame_make_item(2, EQ_NONE, OBJ_BOOKS, BOOK_WAR_CHANTS); @@ -4380,7 +4379,7 @@ bool _give_items_skills() case JOB_DEATH_KNIGHT: _newgame_make_item(0, EQ_WEAPON, OBJ_WEAPONS, WPN_SHORT_SWORD); - + if (!_choose_weapon()) return false; @@ -4407,7 +4406,7 @@ bool _give_items_skills() else { _print_character_info(); - + textcolor( CYAN ); cprintf(EOL "From where do you draw your power?" EOL); @@ -4423,7 +4422,7 @@ bool _give_items_skills() if (Options.prev_dk != DK_NO_SELECTION) { textcolor(BROWN); - cprintf(EOL "Enter - %s" EOL, + cprintf(EOL "Enter - %s" EOL, Options.prev_dk == DK_NECROMANCY? "Necromancy" : Options.prev_dk == DK_YREDELEMNUL? "Yredelemnul" : "Random"); @@ -4431,7 +4430,7 @@ bool _give_items_skills() do { keyn = c_getch(); - + switch (keyn) { case 'X': @@ -4446,7 +4445,7 @@ bool _give_items_skills() case '\n': if (Options.prev_dk == DK_NO_SELECTION) break; - + if (Options.prev_dk != DK_RANDOM) { choice = Options.prev_dk; @@ -4468,7 +4467,7 @@ bool _give_items_skills() } } while (choice == DK_NO_SELECTION); - + ng_dk = (keyn == '*'? DK_RANDOM : choice); } @@ -4575,7 +4574,7 @@ bool _give_items_skills() case '\n': if (Options.prev_ck == GOD_NO_GOD) break; - + if (Options.prev_ck != GOD_RANDOM) { you.religion = static_cast(Options.prev_ck); @@ -4597,7 +4596,7 @@ bool _give_items_skills() } } while (you.religion == GOD_NO_GOD); - + ng_ck = (keyn == '*') ? GOD_RANDOM : you.religion; } diff --git a/crawl-ref/source/player.cc b/crawl-ref/source/player.cc index 6496247b33..fbd98aace0 100644 --- a/crawl-ref/source/player.cc +++ b/crawl-ref/source/player.cc @@ -99,7 +99,7 @@ std::string pronoun_you(description_level_type desc) static void _attribute_increase(); // Use this function whenever the player enters (or lands and thus re-enters) -// a grid. +// a grid. // // stepped - normal walking moves // allow_shift - allowed to scramble in any direction out of lava/water @@ -120,7 +120,7 @@ bool move_player_to_grid( int x, int y, bool stepped, bool allow_shift, ASSERT( you.can_pass_through_feat( new_grid ) ); // better not be an unsubmerged monster either: - ASSERT( mgrd[x][y] == NON_MONSTER + ASSERT( mgrd[x][y] == NON_MONSTER || mons_is_submerged( &menv[ mgrd[x][y] ] )); const int cloud = env.cgrid[x][y]; @@ -222,7 +222,7 @@ bool move_player_to_grid( int x, int y, bool stepped, bool allow_shift, // only consider terrain if player is not levitating if (!player_is_airborne()) { - // XXX: at some point we're going to need to fix the swimming + // XXX: at some point we're going to need to fix the swimming // code to handle burden states. if (is_grid_dangerous(new_grid)) { @@ -254,7 +254,7 @@ bool move_player_to_grid( int x, int y, bool stepped, bool allow_shift, // safer water effects if (you.species == SP_MERFOLK) { - if (old_grid != DNGN_SHALLOW_WATER + if (old_grid != DNGN_SHALLOW_WATER && old_grid != DNGN_DEEP_WATER) { if (stepped) @@ -498,7 +498,7 @@ bool is_player_same_species(const int mon, bool transform) break; // check real (non-transformed) form } } - + switch (you.species) { case SP_HUMAN: @@ -632,10 +632,10 @@ bool player_has_feet() { if (you.species == SP_NAGA || player_genus(GENPC_DRACONIAN)) return false; - + if (you.mutation[MUT_HOOVES] || you.mutation[MUT_TALONS]) return false; - + return true; } @@ -691,7 +691,7 @@ bool you_tran_can_wear(int eq, bool check_mutation) } return true; } - + if (transform == TRAN_STATUE) { if (eq == EQ_BODY_ARMOUR || eq == EQ_GLOVES || eq == EQ_SHIELD) @@ -722,13 +722,13 @@ bool player_weapon_wielded() if (wpn == -1) return (false); - if (you.inv[wpn].base_type != OBJ_WEAPONS + if (you.inv[wpn].base_type != OBJ_WEAPONS && you.inv[wpn].base_type != OBJ_STAVES) { return (false); } - // FIXME: This needs to go in eventually. + // FIXME: This needs to go in eventually. /* // should never have a bad "shape" weapon in hand ASSERT( check_weapon_shape( you.inv[wpn], false ) ); @@ -782,17 +782,17 @@ int player_equip( equipment_type slot, int sub_type, bool calc_unid ) break; case EQ_RINGS: - if (you.equip[EQ_LEFT_RING] != -1 + if (you.equip[EQ_LEFT_RING] != -1 && you.inv[you.equip[EQ_LEFT_RING]].sub_type == sub_type - && (calc_unid || + && (calc_unid || item_type_known(you.inv[you.equip[EQ_LEFT_RING]]))) { ret++; } - if (you.equip[EQ_RIGHT_RING] != -1 + if (you.equip[EQ_RIGHT_RING] != -1 && you.inv[you.equip[EQ_RIGHT_RING]].sub_type == sub_type - && (calc_unid || + && (calc_unid || item_type_known(you.inv[you.equip[EQ_RIGHT_RING]]))) { ret++; @@ -800,13 +800,13 @@ int player_equip( equipment_type slot, int sub_type, bool calc_unid ) break; case EQ_RINGS_PLUS: - if (you.equip[EQ_LEFT_RING] != -1 + if (you.equip[EQ_LEFT_RING] != -1 && you.inv[you.equip[EQ_LEFT_RING]].sub_type == sub_type) { ret += you.inv[you.equip[EQ_LEFT_RING]].plus; } - if (you.equip[EQ_RIGHT_RING] != -1 + if (you.equip[EQ_RIGHT_RING] != -1 && you.inv[you.equip[EQ_RIGHT_RING]].sub_type == sub_type) { ret += you.inv[you.equip[EQ_RIGHT_RING]].plus; @@ -814,13 +814,13 @@ int player_equip( equipment_type slot, int sub_type, bool calc_unid ) break; case EQ_RINGS_PLUS2: - if (you.equip[EQ_LEFT_RING] != -1 + if (you.equip[EQ_LEFT_RING] != -1 && you.inv[you.equip[EQ_LEFT_RING]].sub_type == sub_type) { ret += you.inv[you.equip[EQ_LEFT_RING]].plus2; } - if (you.equip[EQ_RIGHT_RING] != -1 + if (you.equip[EQ_RIGHT_RING] != -1 && you.inv[you.equip[EQ_RIGHT_RING]].sub_type == sub_type) { ret += you.inv[you.equip[EQ_RIGHT_RING]].plus2; @@ -832,9 +832,9 @@ int player_equip( equipment_type slot, int sub_type, bool calc_unid ) break; default: - if (you.equip[slot] != -1 + if (you.equip[slot] != -1 && you.inv[you.equip[slot]].sub_type == sub_type - && (calc_unid || + && (calc_unid || item_type_known(you.inv[you.equip[slot]]))) { ret++; @@ -885,7 +885,7 @@ int player_equip_ego_type( int slot, int special ) // Check all armour slots: for (int i = EQ_CLOAK; i <= EQ_BODY_ARMOUR; i++) { - if (you.equip[i] != -1 + if (you.equip[i] != -1 && get_armour_ego_type( you.inv[you.equip[i]] ) == special) { ret++; @@ -1006,7 +1006,7 @@ int player_hunger_rate(void) if (you.attribute[ATTR_TRANSFORMATION] == TRAN_BAT) return 1; - + // jmf: hunger isn't fair while you can't eat // Actually, it is since you can detransform any time you like -- bwr if (you.attribute[ATTR_TRANSFORMATION] == TRAN_AIR) @@ -1029,12 +1029,41 @@ int player_hunger_rate(void) hunger += 5; } - hunger += you.mutation[MUT_FAST_METABOLISM]; + if (you.species == SP_VAMPIRE) + { + switch (you.hunger_state) + { + case HS_STARVING: + case HS_NEAR_STARVING: + hunger -= 3; + break; + case HS_VERY_HUNGRY: + hunger -= 2; + break; + case HS_HUNGRY: + hunger--; + break; + case HS_SATIATED: + break; + case HS_FULL: + hunger++; + break; + case HS_VERY_FULL: + hunger += 2; + break; + case HS_ENGORGED: + hunger += 3; + } + } + else + { + hunger += you.mutation[MUT_FAST_METABOLISM]; - if (you.mutation[MUT_SLOW_METABOLISM] > 2) - hunger -= 2; - else if (you.mutation[MUT_SLOW_METABOLISM] > 0) - hunger--; + if (you.mutation[MUT_SLOW_METABOLISM] > 2) + hunger -= 2; + else if (you.mutation[MUT_SLOW_METABOLISM] > 0) + hunger--; + } // rings hunger += 2 * player_equip( EQ_RINGS, RING_REGENERATION ); @@ -1044,15 +1073,15 @@ int player_hunger_rate(void) // weapon ego types if (you.species != SP_VAMPIRE) { - hunger += 6 * player_equip_ego_type( EQ_WEAPON, SPWPN_VAMPIRICISM ); - hunger += 9 * player_equip_ego_type( EQ_WEAPON, SPWPN_VAMPIRES_TOOTH ); + hunger += 6 * player_equip_ego_type( EQ_WEAPON, SPWPN_VAMPIRICISM ); + hunger += 9 * player_equip_ego_type( EQ_WEAPON, SPWPN_VAMPIRES_TOOTH ); } else { hunger += 1 * player_equip_ego_type( EQ_WEAPON, SPWPN_VAMPIRICISM ); hunger += 2 * player_equip_ego_type( EQ_WEAPON, SPWPN_VAMPIRES_TOOTH ); } - + // troll leather armour if (you.species != SP_TROLL) hunger += player_equip( EQ_BODY_ARMOUR, ARM_TROLL_LEATHER_ARMOUR ); @@ -1238,7 +1267,7 @@ int player_res_fire(bool calc_unid, bool temp) break; } } - + if (rf < -3) rf = -3; else if (rf > 3) @@ -1258,7 +1287,7 @@ int player_res_cold(bool calc_unid) else if (you.hunger_state <= HS_HUNGRY) rc++; } - + /* rings of fire resistance/fire */ @@ -1289,7 +1318,7 @@ int player_res_cold(bool calc_unid) // mutations: rc += you.mutation[MUT_COLD_RESISTANCE]; - + if (you.mutation[MUT_SHAGGY_FUR] == 3) rc++; @@ -1326,7 +1355,7 @@ int player_res_acid(bool consider_unidentified_gear) int res = 0; if (!transform_changed_physiology()) { - if (you.species == SP_GOLDEN_DRACONIAN + if (you.species == SP_GOLDEN_DRACONIAN && you.experience_level >= 7) res += 2; @@ -1454,7 +1483,7 @@ int player_res_poison(bool calc_unid, bool temp) { rp++; } - + // ego armour: rp += player_equip_ego_type( EQ_ALL_ARMOUR, SPARM_POISON_RESISTANCE ); @@ -1596,7 +1625,7 @@ int player_spec_conj() /* Staves */ sc += player_equip( EQ_STAFF, STAFF_CONJURATION ); - // armour of the Archmagi + // armour of the Archmagi if (player_equip_ego_type( EQ_BODY_ARMOUR, SPARM_ARCHMAGI )) sc++; @@ -1745,7 +1774,7 @@ int player_ghost_base_movement_speed() // Cap speeds. if (speed < 6) speed = 6; - + if (speed > 13) speed = 13; @@ -1834,7 +1863,7 @@ int player_speed(void) if (you.duration[DUR_SLOW]) ps *= 2; - + if (you.duration[DUR_HASTE]) ps /= 2; @@ -1960,7 +1989,7 @@ int player_AC(void) { // Being a lich doesn't preclude the benefits of hide/scales -- bwr // - // Note: Even though necromutation is a high level spell, it does + // Note: Even though necromutation is a high level spell, it does // allow the character full armour (so the bonus is low). -- bwr if (you.attribute[ATTR_TRANSFORMATION] == TRAN_LICH) AC += (300 + 100 * you.skills[SK_NECROMANCY] / 6); // max 7 @@ -2078,7 +2107,7 @@ int player_AC(void) AC += (500 + 100 * (you.skills[SK_ICE_MAGIC] + 1) / 4); // max 12 if (you.duration[DUR_ICY_ARMOUR]) - AC += (100 + 100 * you.skills[SK_ICE_MAGIC] / 4); // max +7 + AC += (100 + 100 * you.skills[SK_ICE_MAGIC] / 4); // max +7 break; case TRAN_DRAGON: @@ -2162,7 +2191,7 @@ bool player_is_shapechanged(void) return (true); } -// psize defaults to PSIZE_TORSO, which checks the part of the body +// 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. @@ -2190,9 +2219,9 @@ int player_evasion() return ((ev < 1) ? 1 : ev); } - // Calculate the base bonus here, but it may be reduced by heavy + // Calculate the base bonus here, but it may be reduced by heavy // armour below. - int dodge_bonus = (you.skills[SK_DODGING] * you.dex + 7) + int dodge_bonus = (you.skills[SK_DODGING] * you.dex + 7) / (20 - size_factor); // Limit on bonus from dodging: @@ -2273,7 +2302,7 @@ int player_evasion() case TRAN_STATUE: ev -= 5; // stiff break; - + case TRAN_AIR: ev += 20; // vapourous break; @@ -2392,7 +2421,7 @@ int old_player_evasion(void) case TRAN_BAT: ev += 20 + (you.experience_level - 10); break; - + case TRAN_AIR: ev += 20; break; @@ -2414,7 +2443,7 @@ int player_magical_power( void ) ret += 13 * player_equip( EQ_STAFF, STAFF_POWER ); ret += 9 * player_equip( EQ_RINGS, RING_MAGICAL_POWER ); ret += scan_randarts( RAP_MAGICAL_POWER ); - + return (ret); } @@ -2513,7 +2542,7 @@ int player_see_invis(bool calc_unid) return si; } -// This does NOT do line of sight! It checks the monster's visibility +// This does NOT do line of sight! It checks the monster's visibility // with repect to the players perception, but doesn't do walls or range... // to find if the square the monster is in los see mons_near(). bool player_monster_visible( const monsters *mon ) @@ -2532,7 +2561,7 @@ bool player_beheld_by( const monsters *mon ) { if (!you.duration[DUR_BEHELD]) return false; - + // can this monster even behold you? if (mon->type != MONS_MERMAID) return false; @@ -2548,14 +2577,14 @@ bool player_beheld_by( const monsters *mon ) you.duration[DUR_BEHELD] = 0; return false; } - + for (unsigned int i = 0; i < you.beheld_by.size(); i++) { unsigned int which_mon = you.beheld_by[i]; if (monster_index(mon) == which_mon) return true; } - + return false; } @@ -2566,7 +2595,7 @@ void update_beholders(const monsters *mon, bool force) { if (!player_beheld_by(mon)) // not in list? return; - + // is an update even necessary? if (force || !mons_near(mon) || mons_friendly(mon) || mon->submerged() || mon->has_ench(ENCH_CONFUSION) || mons_is_paralysed(mon) || mon->asleep() @@ -2705,7 +2734,7 @@ int burden_change(void) if (old_burdenstate != you.burden_state) { mpr("You are being weighed down by all of your possessions."); learned_something_new(TUT_HEAVY_LOAD); - } + } } else { @@ -2743,8 +2772,8 @@ bool you_resist_magic(int power) #if DEBUG_DIAGNOSTICS mprf(MSGCH_DIAGNOSTICS, - "Power: %d, player's MR: %d, target: %d, roll: %d", - ench_power, player_res_magic(), mrchance, mrch2 ); + "Power: %d, player's MR: %d, target: %d, roll: %d", + ench_power, player_res_magic(), mrchance, mrch2 ); #endif if (mrch2 < mrchance) @@ -2770,7 +2799,7 @@ void forget_map(unsigned char chance_forgotten, bool force) env.map[xcount][ycount].clear(); } } - + #ifdef USE_TILE GmapInit(false); tile_clear_buf(); @@ -2837,7 +2866,7 @@ void level_change(bool skip_attribute_increase) if (!skip_attribute_increase) { - if (crawl_state.is_replaying_keys() + if (crawl_state.is_replaying_keys() || crawl_state.is_repeating_cmd()) { crawl_state.cancel_cmd_repeat(); @@ -3433,8 +3462,8 @@ void level_change(bool skip_attribute_increase) xom_is_stimulated(16); - learned_something_new(TUT_NEW_LEVEL); - + learned_something_new(TUT_NEW_LEVEL); + } redraw_skill( you.your_name, player_title() ); @@ -3598,10 +3627,10 @@ static const char * _get_rotting_how() return (" away quickly"); if (you.rotting > 4) return (" badly"); - + if (you.species == SP_GHOUL) return (" faster than usual"); - + return(""); } @@ -3615,57 +3644,67 @@ void display_char_status() mpr( "You are standing in death's doorway." ); else mpr( "You are alive." ); - + if (you.species == SP_VAMPIRE) { std::string msg = "At your current hunger state you "; std::vector attrib; - + switch (you.hunger_state) { - case HS_STARVING: - attrib.push_back("resist poison"); - attrib.push_back("are susceptible to fire"); - attrib.push_back("significantly resist cold"); - attrib.push_back("strongly resist negative energy"); - attrib.push_back("resist torment"); - if (you.experience_level >= 13) - attrib.push_back("are in touch with the powers of death"); - - if (you.attribute[ATTR_TRANSFORMATION] == TRAN_BAT) - attrib.push_back("heal slowly (as a bat)!"); - else - attrib.push_back("do not heal!"); - break; - case HS_NEAR_STARVING: - attrib.push_back("resist poison"); - attrib.push_back("significantly resist cold"); - attrib.push_back("strongly resist negative energy"); - if (you.experience_level >= 13) - attrib.push_back("are in touch with the powers of death"); - attrib.push_back("heal slowly!"); - break; - case HS_HUNGRY: - case HS_VERY_HUNGRY: - attrib.push_back("resist poison"); - attrib.push_back("resist cold"); - attrib.push_back("significantly resist negative energy"); - if (you.experience_level >= 13) - attrib.push_back("are in touch with the powers of death"); - attrib.push_back("heal slowly!"); - break; - case HS_SATIATED: - attrib.push_back("resist negative energy."); - break; - case HS_FULL: - case HS_VERY_FULL: - attrib.push_back("heal quickly."); - break; - case HS_ENGORGED: - attrib.push_back("heal extremely quickly."); - break; + case HS_STARVING: + attrib.push_back("resist poison"); + attrib.push_back("are susceptible to fire"); + attrib.push_back("significantly resist cold"); + attrib.push_back("strongly resist negative energy"); + attrib.push_back("resist torment"); + if (you.experience_level >= 13) + attrib.push_back("are in touch with the powers of death"); + + if (you.attribute[ATTR_TRANSFORMATION] == TRAN_BAT) + attrib.push_back("heal slowly (as a bat)!"); + else + attrib.push_back("do not heal!"); + break; + case HS_NEAR_STARVING: + attrib.push_back("resist poison"); + attrib.push_back("significantly resist cold"); + attrib.push_back("strongly resist negative energy"); + if (you.experience_level >= 13) + attrib.push_back("are in touch with the powers of death") + attrib.push_back("have an extremely slow metabolism"); + attrib.push_back("heal slowly!"); + break; + case HS_HUNGRY: + case HS_VERY_HUNGRY: + attrib.push_back("resist poison"); + attrib.push_back("resist cold"); + attrib.push_back("significantly resist negative energy"); + if (you.experience_level >= 13) + attrib.push_back("are in touch with the powers of death"); + if (you.hunger_state == HS_HUNGRY) + attrib.push_back("have a slow metabolism"); + else + attrib.push_back("have a very slow metabolism"); + attrib.push_back("heal slowly!"); + break; + case HS_SATIATED: + attrib.push_back("resist negative energy."); + break; + case HS_FULL: + attrib.push_back("have a fast metabolism"); + attrib.push_back("heal quickly."); + break; + case HS_VERY_FULL: + attrib.push_back("have a very fast metabolism"); + attrib.push_back("heal quickly."); + break; + case HS_ENGORGED: + attrib.push_back("have an extremely fast metabolism"); + attrib.push_back("heal extremely quickly."); + break; } - + if (!attrib.empty()) { msg += comma_separated_line(attrib.begin(), attrib.end(), @@ -3740,7 +3779,7 @@ void display_char_status() { mpr("You do not heal."); } - + if (you.duration[DUR_REGENERATION] && (you.species != SP_VAMPIRE || you.hunger_state > HS_STARVING)) { @@ -3749,7 +3788,7 @@ void display_char_status() else mpr("You are regenerating."); } - + if (you.duration[DUR_SWIFTNESS]) mpr( "You can move swiftly." ); @@ -3797,7 +3836,7 @@ void display_char_status() mpr( "You are paralysed." ); if (you.duration[DUR_SLEEP]) mpr( "You are asleep." ); - + if (you.duration[DUR_EXHAUSTED]) mpr( "You are exhausted." ); @@ -3821,7 +3860,7 @@ void display_char_status() mpr( "You are held in a net." ); if (you.duration[DUR_POISONING]) - { + { mprf("You are %s poisoned.", (you.duration[DUR_POISONING] > 10) ? "extremely" : (you.duration[DUR_POISONING] > 5) ? "very" : @@ -3873,8 +3912,8 @@ void display_char_status() (swim) ? "swimming" : (water) ? "wading" : (fly) ? "flying" : - (lev) ? "levitating" - : "movement", + (lev) ? "levitating" + : "movement", (water && !swim) ? "uncertain and " : (!water && swift) ? "aided by the wind" : "", @@ -3886,7 +3925,7 @@ void display_char_status() (move_cost < 8) ? "very quick" : (move_cost < 10) ? "quick" : (move_cost == 10) ? "average" : - (move_cost < 13) ? "slow" + (move_cost < 13) ? "slow" : "very slow" ); #if DEBUG_DIAGNOSTICS @@ -3894,7 +3933,7 @@ void display_char_status() mprf("To-hit: %d", to_hit); #endif /* - // Messages based largely on percentage chance of missing the + // Messages based largely on percentage chance of missing the // average EV 10 humanoid, and very agile EV 30 (pretty much // max EV for monsters currently). // @@ -3910,7 +3949,7 @@ void display_char_status() (to_hit < 30) ? "Very agile monsters are a bit awkward to hit" : (to_hit < 45) ? "Very agile monsters are a bit difficult to hit" : (to_hit < 60) ? "Very agile monsters are a bit hard to hit" : - (to_hit < 100) ? "You feel comfortable with your ability to fight" + (to_hit < 100) ? "You feel comfortable with your ability to fight" : "You feel confident with your ability to fight" ); */ @@ -3925,7 +3964,7 @@ void display_char_status() (mr < 140) ? "extremely" : "incredibly"); - // character evaluates their ability to sneak around: + // character evaluates their ability to sneak around: const int ustealth = check_stealth(); // XXX: made these values up, probably could be better. @@ -3936,8 +3975,8 @@ void display_char_status() (ustealth < 50) ? "fairly " : (ustealth < 80) ? "" : (ustealth < 120) ? "quite " : - (ustealth < 160) ? "very " : - (ustealth < 200) ? "extremely " + (ustealth < 160) ? "very " : + (ustealth < 200) ? "extremely " : "incredibly " ); #if DEBUG_DIAGNOSTICS @@ -3969,7 +4008,7 @@ int str_to_species(const std::string &species) } std::string species_name(species_type speci, int level, bool genus, bool adj) -// defaults: false false +// defaults: false false { std::string res; @@ -4045,8 +4084,8 @@ std::string species_name(species_type speci, int level, bool genus, bool adj) case SP_KOBOLD: res = "Kobold"; break; case SP_MUMMY: res = "Mummy"; break; case SP_NAGA: res = "Naga"; break; - // We've previously declared that these are radically - // different from Ogres... so we're not going to + // We've previously declared that these are radically + // different from Ogres... so we're not going to // refer to them as Ogres. -- bwr // Not the species, but genus... why not? -- jpeg case SP_OGRE_MAGE: res = (genus? "Ogre" : "Ogre-Mage"); break; @@ -4087,7 +4126,7 @@ bool player_item_conserve(bool calc_unid) int player_mental_clarity(bool calc_unid) { - const int ret = 3 * player_equip(EQ_AMULET, AMU_CLARITY, calc_unid) + const int ret = 3 * player_equip(EQ_AMULET, AMU_CLARITY, calc_unid) + you.mutation[ MUT_CLARITY ]; return ((ret > 3) ? 3 : ret); @@ -4190,12 +4229,12 @@ unsigned long exp_needed(int lev) // Section 2: levels 6-13, second derivative is exponential/doubling. // Section 3: levels 14-27, second derivative is constant at 6000. // - // Section three is constant so we end up with high levels at about + // Section three is constant so we end up with high levels at about // their old values (level 27 at 850k), without delta2 ever decreasing. - // The values that are considerably different (ie level 13 is now 29000, - // down from 41040 are because the second derivative goes from 9040 to + // The values that are considerably different (ie level 13 is now 29000, + // down from 41040 are because the second derivative goes from 9040 to // 1430 at that point in the original, and then slowly builds back - // up again). This function smoothes out the old level 10-15 area + // up again). This function smoothes out the old level 10-15 area // considerably. // Here's a table: @@ -4252,7 +4291,7 @@ unsigned long exp_needed(int lev) lev -= 4; level = 10 + 10 * lev + (60 << lev); } - else + else { lev -= 12; level = 15500 + 10500 * lev + 3000 * lev * lev; @@ -4302,7 +4341,7 @@ bool items_give_ability(const int slot, randart_prop_type abil) // only weapons give their effects when in our hands if (i == EQ_WEAPON && you.inv[ eq ].base_type != OBJ_WEAPONS) continue; - + if (eq == EQ_LEFT_RING || eq == EQ_RIGHT_RING) { if (abil == RAP_LEVITATE && you.inv[eq].sub_type == RING_LEVITATION) @@ -4352,7 +4391,7 @@ int scan_randarts(randart_prop_type which_property, bool calc_unid) continue; // Ignore unidentified items [TileCrawl dump enhancements]. - if (!item_ident(you.inv[ eq ], ISFLAG_KNOW_PROPERTIES) && + if (!item_ident(you.inv[ eq ], ISFLAG_KNOW_PROPERTIES) && !calc_unid) continue; @@ -4532,7 +4571,7 @@ void dec_mp(int mp_loss) you.magic_points = 0; if (Options.magic_point_warning - && you.magic_points < (you.max_magic_points + && you.magic_points < (you.max_magic_points * Options.magic_point_warning) / 100) { mpr( "* * * LOW MAGIC WARNING * * *", MSGCH_DANGER ); @@ -4729,7 +4768,7 @@ void set_hp(int new_amount, bool max_too) if ( max_too ) take_note(Note(NOTE_MAXHP_CHANGE, you.hp_max)); - + // must remain outside conditional, given code usage {dlb} you.redraw_hit_points = 1; @@ -4752,7 +4791,7 @@ void set_mp(int new_amount, bool max_too) if (you.magic_points > you.max_magic_points) you.magic_points = you.max_magic_points; - + take_note(Note(NOTE_MP_CHANGE, you.magic_points, you.max_magic_points)); if ( max_too ) take_note(Note(NOTE_MAXMP_CHANGE, you.max_magic_points)); @@ -4792,7 +4831,7 @@ void contaminate_player(int change, bool controlled, bool status_only) #if DEBUG_DIAGNOSTICS if (change > 0 || (change < 0 && you.magic_contamination)) { - mprf(MSGCH_DIAGNOSTICS, "change: %d radiation: %d", + mprf(MSGCH_DIAGNOSTICS, "change: %d radiation: %d", change, change + you.magic_contamination ); } #endif @@ -4947,7 +4986,7 @@ bool slow_player( int amount ) else if (you.duration[DUR_SLOW] >= 100) mpr( "You already are as slow as you could be." ); else - { + { if (you.duration[DUR_SLOW] == 0) mpr( "You feel yourself slow down." ); else @@ -5047,18 +5086,18 @@ bool disease_player( int amount ) void dec_disease_player( void ) { if (you.disease > 0) - { + { you.disease--; - + // kobolds and regenerators recuperate quickly if (you.disease > 5 - && (you.species == SP_KOBOLD + && (you.species == SP_KOBOLD || you.duration[ DUR_REGENERATION ] || you.mutation[ MUT_REGENERATION ] == 3)) { you.disease -= 2; } - + if (!you.disease) mpr("You feel your health improve.", MSGCH_RECOVERY); } @@ -5098,7 +5137,7 @@ int count_worn_ego( int which_ego ) { result++; } - + return result; } @@ -5120,7 +5159,7 @@ static int _strength_modifier() // mutations result += you.mutation[MUT_STRONG] - you.mutation[MUT_WEAK]; result += you.mutation[MUT_STRONG_STIFF]-you.mutation[MUT_FLEXIBLE_WEAK]; - + // transformations switch ( you.attribute[ATTR_TRANSFORMATION] ) { @@ -5156,12 +5195,12 @@ static int _dex_modifier() const int metallic_modifier[] = { 0, -2, -3, -4 }; const int yellow_modifier[] = { 0, 0, -1, -2 }; const int red2_modifier[] = { 0, 0, -1, -2 }; - + result -= grey2_modifier[you.mutation[MUT_GREY2_SCALES]]; result -= metallic_modifier[you.mutation[MUT_METALLIC_SCALES]]; result -= yellow_modifier[you.mutation[MUT_YELLOW_SCALES]]; result -= red2_modifier[you.mutation[MUT_RED2_SCALES]]; - + // transformations switch ( you.attribute[ATTR_TRANSFORMATION] ) { @@ -5296,7 +5335,7 @@ void player::init() entering_level = false; transit_stair = DNGN_UNSEEN; - + just_autoprayed = false; berserk_penalty = 0; disease = 0; @@ -5641,7 +5680,7 @@ bool player::cannot_speak() const if (you.duration[DUR_PARALYSIS]) // we allow talking during sleep ;) return (true); - + // No transform that prevents the player from speaking yet. return (false); } @@ -5696,7 +5735,7 @@ int player::damage_brand(int) int ret = SPWPN_NORMAL; const int wpn = equip[ EQ_WEAPON ]; - if (wpn != -1) + if (wpn != -1) { if ( !is_range_weapon(inv[wpn]) ) ret = get_weapon_brand( inv[wpn] ); @@ -5725,7 +5764,7 @@ int player::damage_brand(int) if (you.species == SP_VAMPIRE && one_chance_in(5)) ret = SPWPN_VAMPIRICISM; break; - + default: break; } @@ -5973,10 +6012,10 @@ int player::shield_bonus() const // Note that 0 is not quite no-blocking. if (incapacitated()) return (0); - + int stat = 0; if (const item_def *sh = const_cast(this)->shield()) - stat = + stat = sh->sub_type == ARM_BUCKLER? dex : sh->sub_type == ARM_LARGE_SHIELD? (3 * strength + dex) / 4: (dex + strength) / 2; @@ -6136,7 +6175,7 @@ int player::mons_species() const { if (player_genus(GENPC_DRACONIAN)) return (MONS_DRACONIAN); - + switch (species) { case SP_HILL_ORC: @@ -6144,7 +6183,7 @@ int player::mons_species() const case SP_HIGH_ELF: case SP_GREY_ELF: case SP_DEEP_ELF: case SP_SLUDGE_ELF: return (MONS_ELF); - + default: return (MONS_HUMAN); } @@ -6228,13 +6267,13 @@ void player::confuse(int str) void player::paralyse(int str) { int ¶lysis(duration[DUR_PARALYSIS]); - + mprf( "You %s the ability to move!", paralysis ? "still haven't" : "suddenly lose" ); - + if (str > paralysis && (paralysis < 3 || one_chance_in(paralysis))) paralysis = str; - + if (paralysis > 13) paralysis = 13; } @@ -6498,7 +6537,7 @@ const std::string PlaceInfo::short_name() const case LEVEL_LABYRINTH: return "Labyrinth"; - + case LEVEL_PORTAL_VAULT: return "Portal Vault"; -- cgit v1.2.3-54-g00ecf