diff options
Diffstat (limited to 'crawl-ref/source/monstuff.cc')
-rw-r--r-- | crawl-ref/source/monstuff.cc | 854 |
1 files changed, 201 insertions, 653 deletions
diff --git a/crawl-ref/source/monstuff.cc b/crawl-ref/source/monstuff.cc index 11b60daf04..adf19e2e98 100644 --- a/crawl-ref/source/monstuff.cc +++ b/crawl-ref/source/monstuff.cc @@ -36,7 +36,6 @@ #include "debug.h" #include "delay.h" #include "describe.h" -#include "dgnevent.h" #include "fight.h" #include "hiscores.h" #include "it_use2.h" @@ -60,21 +59,19 @@ #include "spl-util.h" #include "spells2.h" #include "spells4.h" -#include "state.h" #include "stuff.h" #include "terrain.h" #include "traps.h" #include "tutorial.h" #include "view.h" #include "stash.h" -#include "xom.h" static bool handle_special_ability(monsters *monster, bolt & beem); static bool handle_pickup(monsters *monster); static void handle_behaviour(monsters *monster); static void set_nearest_monster_foe(monsters *monster); static void mons_in_cloud(monsters *monster); -static bool monster_move(monsters *monster); +static void monster_move(monsters *monster); static bool plant_spit(monsters *monster, bolt &pbolt); static int map_wand_to_mspell(int wand_type); @@ -89,7 +86,7 @@ static bool immobile_monster[MAX_MONSTERS]; #define FAR_AWAY 1000000 // used in monster_move() // This function creates an artificial item to represent a mimic's appearance. -// Eventually, mimics could be redone to be more like dancing weapons... +// Eventually, mimics could be redone to be more like Dancing wepaons... // there'd only be one type and it would look like the item it carries. -- bwr void get_mimic_item( const monsters *mimic, item_def &item ) { @@ -119,10 +116,7 @@ void get_mimic_item( const monsters *mimic, item_def &item ) if (prop < 20) { - make_item_randart(item); - // Override special - this could cause a "bad" (no-properties) - // randart, but we only need the name anyway. We have to - // do this in order to get a consistent name for the mimic item. + item.flags |= ISFLAG_RANDART; item.special = ((mimic->x << 8 + mimic->y) & RANDART_SEED_MASK); } else if (prop < 50) @@ -150,8 +144,7 @@ void get_mimic_item( const monsters *mimic, item_def &item ) if (prop < 20) { - make_item_randart(item); - // See comment above for randart weapon mimics. + item.flags |= ISFLAG_RANDART; item.special = ((mimic->x << 8 + mimic->y) & RANDART_SEED_MASK); } else if (prop < 40) @@ -247,10 +240,6 @@ bool curse_an_item( bool decay_potions ) /* don't change you.inv_special (just for fun) */ if (you.inv[item].base_type == OBJ_POTIONS) { - // Xom is amused by useful potions being ruined. - if (item_value(you.inv[item], true) / you.inv[item].quantity > 2) - xom_is_stimulated(32 * you.inv[item].quantity); - you.inv[item].sub_type = POT_DECAY; unset_ident_flags( you.inv[item], ISFLAG_IDENT_MASK ); // all different } @@ -272,8 +261,6 @@ static void monster_drop_ething(monsters *monster, hostile_grid = true; } - int midx = (int) monster_index(monster); - for (i = MSLOT_GOLD; i >= MSLOT_WEAPON; i--) { int item = monster->inv[i]; @@ -282,7 +269,6 @@ static void monster_drop_ething(monsters *monster, { if (hostile_grid) { - item_was_destroyed(mitm[item], midx); destroyed = true; destroy_item( item ); } @@ -308,6 +294,7 @@ static void monster_drop_ething(monsters *monster, static void place_monster_corpse(const monsters *monster) { int corpse_class = mons_species(monster->type); + if (corpse_class == MONS_DRACONIAN) corpse_class = draco_subspecies(monster); @@ -316,8 +303,12 @@ static void place_monster_corpse(const monsters *monster) else if (monster->has_ench(ENCH_GLOWING_SHAPESHIFTER)) corpse_class = MONS_GLOWING_SHAPESHIFTER; - if (mons_weight(corpse_class) == 0 || coinflip()) + if (mons_weight(corpse_class) == 0 + || grid_destroys_items(grd[monster->x][monster->y]) + || coinflip()) + { return; + } int o = get_item_slot(); if (o == NON_ITEM) @@ -335,13 +326,6 @@ static void place_monster_corpse(const monsters *monster) if (mitm[o].colour == BLACK) mitm[o].colour = monster->colour; - if (grid_destroys_items(grd[monster->x][monster->y])) - { - item_was_destroyed(mitm[o]); - mitm[o].base_type = OBJ_UNASSIGNED; - return; - } - // Don't care if 'o' is changed, and it shouldn't be (corpses don't stack) move_item_to_grid( &o, monster->x, monster->y ); if (see_grid(monster->x, monster->y)) @@ -491,8 +475,6 @@ void monster_die(monsters *monster, killer_type killer, int i, bool silent) if (net != NON_ITEM) remove_item_stationary(mitm[net]); } - // update list of monsters beholding player - update_beholders(monster, true); const int monster_killed = monster_index(monster); const bool death_message = @@ -555,13 +537,7 @@ void monster_die(monsters *monster, killer_type killer, int i, bool silent) } if (you.prev_targ == monster_killed) - { you.prev_targ = MHITNOT; - crawl_state.cancel_cmd_repeat(); - } - - if (killer == KILL_YOU) - crawl_state.cancel_cmd_repeat(); const bool pet_kill = is_pet_kill(killer, i); @@ -717,7 +693,7 @@ void monster_die(monsters *monster, killer_type killer, int i, bool silent) // no piety loss if god gifts killed by other monsters if (mons_friendly(monster) && !testbits(monster->flags,MF_GOD_GIFT)) did_god_conduct(DID_FRIEND_DIES, 1 + (monster->hit_dice / 2), - true, monster); + monster); // Trying to prevent summoning abuse here, so we're trying to // prevent summoned creatures from being being done_good kills. @@ -941,10 +917,6 @@ void monster_die(monsters *monster, killer_type killer, int i, bool silent) } } - dungeon_events.fire_event( - dgn_event(DET_MONSTER_DIED, monster->pos(), 0, - monster_index(monster), killer)); - const coord_def mwhere = monster->pos(); if (!hard_reset) monster_drop_ething(monster, YOU_KILL(killer) || pet_kill); @@ -993,7 +965,7 @@ static bool jelly_divide(monsters * parent) { // 10-50 for now - must take clouds into account: if (mgrd[parent->x + jex][parent->y + jey] == NON_MONSTER - && parent->can_pass_through(parent->x + jex, parent->y + jey) + && !grid_is_solid(grd[parent->x + jex][parent->y + jey]) && (parent->x + jex != you.x_pos || parent->y + jey != you.y_pos)) { foundSpot = true; @@ -1225,18 +1197,10 @@ bool monster_polymorph( monsters *monster, monster_type targetc, bool player_messaged = simple_monster_message(monster, str_polymon.c_str()); - // Even if the monster transforms from one type that can behold the - // player into a different type which can also behold the player, - // the polymorph disrupts the beholding process. Do this before - // changing monster->type, since unbeholding can only happen while - // the monster is still a mermaid. - update_beholders(monster, true); - // the actual polymorphing: const int old_hp = monster->hit_points; const int old_hp_max = monster->max_hit_points; const bool old_mon_caught = mons_is_caught(monster); - const char old_ench_countdown = monster->ench_countdown; /* deal with mons_sec */ monster->type = targetc; @@ -1252,8 +1216,6 @@ bool monster_polymorph( monsters *monster, monster_type targetc, monster->add_ench(abj); monster->add_ench(shifter); - monster->ench_countdown = old_ench_countdown; - if (mons_class_flag( monster->type, M_INVIS )) monster->add_ench(ENCH_INVIS); @@ -1360,94 +1322,31 @@ bool monster_blink(monsters *monster) // allow_adjacent: allow target to be adjacent to origin // restrict_LOS: restict target to be within PLAYER line of sight bool random_near_space(int ox, int oy, int &tx, int &ty, bool allow_adjacent, - bool restrict_LOS) + bool restrict_LOS) { + int tries = 0; - // This might involve ray tracing (via num_feats_between()), so - // cache results to avoid duplicating ray traces. - FixedArray<bool, 14, 14> tried; - tried.init(false); - - // Is the monster on the other side of a tranparent wall? - bool trans_wall_block = trans_wall_blocking(ox, oy); - bool origin_is_player = (you.pos() == coord_def(ox, oy)); - int min_walls_between = 0; - - // Skip ray tracing if possible. - if (trans_wall_block) - min_walls_between = num_feats_between(ox, oy, you.x_pos, you.y_pos, - DNGN_CLEAR_ROCK_WALL, - DNGN_CLEAR_PERMAROCK_WALL); - int tries = 0; - while (tries++ < 150) + do { - int dx = random2(14); - int dy = random2(14); - - tx = ox - 6 + dx; - ty = oy - 6 + dy; + tx = ox - 6 + random2(14); + ty = oy - 6 + random2(14); // origin is not 'near' if (tx == ox && ty == oy) continue; - if (tried[dx][dy]) - continue; - - tried[dx][dy] = true; + tries++; - if (!in_bounds(tx, ty) - || (!see_grid(tx, ty) && restrict_LOS) - || grd[tx][ty] < DNGN_SHALLOW_WATER - || mgrd[tx][ty] != NON_MONSTER - || (tx == you.x_pos && ty == you.y_pos) - || (!allow_adjacent && distance(ox, oy, tx, ty) <= 2)) - continue; - - if (!trans_wall_block && !origin_is_player) - return (true); - - // If the monster is on a visible square which is on the other - // side of one or more translucent from the player, then it - // can only blink through translucent walls if the end point - // is either not visible to the player, or there are at least - // as many translucent walls between the player and the end - // point as between the player and the start point. However, - // monsters can still blink through translucent walls to get - // away from the player, since in the absence of tranlucent - // walls monsters can blink to places which are not in either - // the monster's nor the player's LOS. - if (!see_grid(tx, ty) && !origin_is_player) - return (true); - - // Player can't randomly pass through translucent walls. - if (origin_is_player) - { - if (see_grid_no_trans(tx, ty)) - return (true); - - continue; - } - - int walls_passed = num_feats_between(tx, ty, ox, oy, - DNGN_CLEAR_ROCK_WALL, - DNGN_CLEAR_PERMAROCK_WALL); - if (walls_passed == 0) - return (true); - - // Player can't randomly pass through translucent walls. - if (origin_is_player) - continue; - - int walls_between = num_feats_between(tx, ty, you.x_pos, you.y_pos, - DNGN_CLEAR_ROCK_WALL, - DNGN_CLEAR_PERMAROCK_WALL); - - if (walls_between >= min_walls_between) - return (true); + if (tries > 149) + break; } + while ((!see_grid(tx, ty) && restrict_LOS) + || grd[tx][ty] < DNGN_SHALLOW_WATER + || mgrd[tx][ty] != NON_MONSTER + || (tx == you.x_pos && ty == you.y_pos) + || (!allow_adjacent && distance(ox, oy, tx, ty) <= 2)); - return (false); + return (tries < 150); } // end random_near_space() static bool habitat_okay( const monsters *monster, int targ ) @@ -1672,7 +1571,7 @@ void behaviour_event( monsters *mon, int event, int src, // will turn monster against <src>, unless they // are BOTH friendly and stupid, or else fleeing anyway. // Hitting someone over the head, of course, - // always triggers this code. + // always triggers this code. if ( event == ME_WHACK || ((isFriendly != sourceFriendly || isSmart) && (mon->behaviour != BEH_FLEE && mon->behaviour != BEH_PANIC))) @@ -1718,7 +1617,7 @@ void behaviour_event( monsters *mon, int event, int src, // if player is invisible. setTarget = true; if (see_grid(mon->x, mon->y)) - learned_something_new(TUT_FLEEING_MONSTER); + learned_something_new(TUT_FLEEING_MONSTER); break; case ME_CORNERED: @@ -1764,11 +1663,6 @@ void behaviour_event( monsters *mon, int event, int src, // 1. Evalutates current AI state // 2. Sets monster targetx,y based on current foe // -// XXX: Monsters of I_NORMAL or above should select a new target -// if their current target is another monser which is sitting in -// a wall and is immune to most attacks while in a wall -// (M_WALL_SHIELDED), unless the monster has a spell or special/nearby -// ability which isn't affected by M_WALL_SHIELDED. //--------------------------------------------------------------- static void handle_behaviour(monsters *mon) { @@ -2105,13 +1999,6 @@ static void handle_behaviour(monsters *mon) // we can jump back to WANDER if the foe // isn't present. - // XXX: If a monster can move through solid grids then it - // should preferentially flee towards the nearest solid grid - // it can move through. If it has M_WALL_SHIELDED is will - // be (mostly) safe as soon as it enters the wall, and even - // if it doesn't once it moves again it will be on the other - // side of the wall and likely beyond the reach of the player. - if (isFriendly) { // Special-cased below so that it will flee *towards* you @@ -2235,6 +2122,40 @@ bool simple_monster_message(const monsters *monster, const char *event, return (false); } // end simple_monster_message() +static bool handle_enchantment(monsters *monster) +{ + // Yes, this is the speed we want. This function will be called in + // two circumstances: (1) the monster can move and has enough energy, + // and (2) the monster cannot move (speed == 0) and the monster loop + // is running. + // + // In the first case we don't have to figure in the player's time, + // since the rate of call to this function already does that (ie. + // a bat would get here 6 times in 2 normal player turns, and if + // the player was twice as fast it would be 6 times every four player + // moves. So the only speed we care about is the monster vs the + // absolute time frame. + // + // In the second case, we're hacking things so that plants can suffer + // from sticky flame. The rate of call in this case is once every + // player action... so the time_taken by the player is the ratio to + // the absolute time frame. + // + // This will be used below for poison and sticky flame so that the + // damage is apparently in the absolute time frame. This is done + // by scaling the damage and the chance that the effect goes away. + // The result is that poison on a regular monster will be doing + // 1d3 damage every two rounds, and last eight rounds, and on + // a bat the same poison will be doing 1/3 the damage each action + // it gets (the mod fractions are randomized in), will have three + // turns to the other monster's one, and the effect will survive + // 3 times as many calls to this function (ie 8 rounds * 3 calls). + // + // -- bwr + monster->apply_enchantments(); + return (!monster->alive()); +} // end handle_enchantment() + //--------------------------------------------------------------- // // handle_movement @@ -2387,8 +2308,6 @@ static void handle_nearby_ability(monsters *monster) case MONS_LAVA_FISH: case MONS_LAVA_SNAKE: case MONS_SALAMANDER: - case MONS_MERFOLK: - case MONS_MERMAID: case MONS_BIG_FISH: case MONS_GIANT_GOLDFISH: case MONS_ELECTRICAL_EEL: @@ -2396,26 +2315,18 @@ static void handle_nearby_ability(monsters *monster) case MONS_WATER_ELEMENTAL: case MONS_SWAMP_WORM: if (monster_can_submerge(monster->type, grd[monster->x][monster->y]) - && ( !player_beheld_by(monster) // no submerging if player entranced - && (one_chance_in(5) - || ((grid_distance( monster->x, monster->y, - you.x_pos, you.y_pos ) > 1 - // FIXME This is better expressed as a - // function such as - // monster_has_ranged_attack: - && monster->type != MONS_ELECTRICAL_EEL - && monster->type != MONS_LAVA_SNAKE - && (monster->type != MONS_MERMAID - || you.species == SP_MERFOLK) - // Don't submerge if we just unsubmerged for - // the sake of shouting. - && monster->seen_context != "bursts forth shouting" - && !one_chance_in(20)) )) + && (one_chance_in(5) || (grid_distance( monster->x, monster->y, + you.x_pos, you.y_pos ) > 1 + // FIXME This is better expressed as a + // function such as + // monster_has_ranged_attack: + && monster->type != MONS_ELECTRICAL_EEL + && monster->type != MONS_LAVA_SNAKE + && !one_chance_in(20)) || monster->hit_points <= monster->max_hit_points / 2) || env.cgrid[monster->x][monster->y] != EMPTY_CLOUD) { monster->add_ench(ENCH_SUBMERGED); - update_beholders(monster); } break; @@ -2744,97 +2655,10 @@ static bool handle_special_ability(monsters *monster, bolt & beem) } break; - case MONS_MERMAID: - { - // won't sing if either of you silenced, or it's friendly or confused - if (monster->has_ench(ENCH_CONFUSION) || mons_friendly(monster) - || silenced(monster->x, monster->y) || silenced(you.x_pos, you.y_pos)) - { - break; - } - - // reduce probability because of spamminess - if (you.species == SP_MERFOLK && !one_chance_in(4)) - break; - - // a wounded invisible mermaid is less likely to give away her position - if (monster->invisible() - && monster->hit_points <= monster->max_hit_points / 2 - && !one_chance_in(3)) - { - break; - } - - bool already_beheld = player_beheld_by(monster); - - if (one_chance_in(5) - || monster->foe == MHITYOU && !already_beheld && coinflip()) - { - if (player_monster_visible(monster)) - { - simple_monster_message(monster, - make_stringf(" chants %s song.", - already_beheld? "her luring" : "a haunting").c_str(), - MSGCH_MONSTER_SPELL); - } - else - { - // if you're already beheld by an invisible mermaid she can - // still prolong the enchantment; otherwise you "resist" - if (already_beheld) - mpr("You hear a luring song.", MSGCH_SOUND); - else - { - if (one_chance_in(4)) // reduce spamminess - { - if (coinflip()) - mpr("You hear a haunting song.", MSGCH_SOUND); - else - mpr("You hear an eerie melody.", MSGCH_SOUND); - - canned_msg(MSG_YOU_RESIST); // flavour only - } - break; - } - } - - // once beheld by a particular monster, cannot resist anymore - if (!already_beheld - && (you.species == SP_MERFOLK || you_resist_magic(100))) - { - canned_msg(MSG_YOU_RESIST); - break; - } - - if (!you.duration[DUR_BEHELD]) - { - you.duration[DUR_BEHELD] = 7; - you.beheld_by.push_back(monster_index(monster)); - mpr("You are beheld!", MSGCH_WARN); - } - else - { - you.duration[DUR_BEHELD] += 5; - if (!already_beheld) - you.beheld_by.push_back(monster_index(monster)); - } - used = true; - - if (you.duration[DUR_BEHELD] > 12) - you.duration[DUR_BEHELD] = 12; - } - break; - } default: break; } - if (used) - { - monsterentry *entry = get_monster_data(monster->type); - monster->speed_increment -= entry->energy_usage.special; - } - return (used); } // end handle_special_ability() @@ -2936,9 +2760,6 @@ static bool handle_potion(monsters *monster, bolt & beem) if (ident != ID_UNKNOWN_TYPE && was_visible) set_ident_type(OBJ_POTIONS, potion_type, ident); - - monsterentry *entry = get_monster_data(monster->type); - monster->speed_increment -= entry->energy_usage.item; } return (imbibed); @@ -3079,9 +2900,6 @@ static bool handle_scroll(monsters *monster) if (ident != ID_UNKNOWN_TYPE && was_visible) set_ident_type(OBJ_SCROLLS, scroll_type, ident); - - monsterentry *entry = get_monster_data(monster->type); - monster->speed_increment -= entry->energy_usage.item; } return read; @@ -3144,13 +2962,12 @@ static bool handle_wand(monsters *monster, bolt &beem) beem.is_beam = theBeam.is_beam; beem.is_explosion = theBeam.is_explosion; + unsigned long old_flags = wand.flags; #if HISCORE_WEAPON_DETAIL - beem.aux_source = - wand.name(DESC_QUALNAME, false, true, false, false); + set_ident_flags( wand, ISFLAG_IDENT_MASK ); #else - beem.aux_source = - wand.name(DESC_QUALNAME, false, true, false, false, - ISFLAG_KNOW_CURSE | ISFLAG_KNOW_PLUSES); + unset_ident_flags( wand, ISFLAG_IDENT_MASK ); + set_ident_flags( wand, ISFLAG_KNOW_TYPE ); #endif beem.aux_source = wand.name(DESC_PLAIN); wand.flags = old_flags; @@ -3254,9 +3071,6 @@ static bool handle_wand(monsters *monster, bolt &beem) wand.plus2++; } - monsterentry *entry = get_monster_data(monster->type); - monster->speed_increment -= entry->energy_usage.item; - return (true); } } @@ -3775,9 +3589,6 @@ static bool handle_spell( monsters *monster, bolt & beem ) { simple_monster_message(monster, " blinks!"); monster_blink(monster); - - monsterentry *entry = get_monster_data(monster->type); - monster->speed_increment -= entry->energy_usage.spell; } else return (false); @@ -3787,8 +3598,6 @@ static bool handle_spell( monsters *monster, bolt & beem ) mons_cast(monster, beem, spell_cast); mmov_x = 0; mmov_y = 0; - monsterentry *entry = get_monster_data(monster->type); - monster->speed_increment -= entry->energy_usage.spell; } } // end "if mons_class_flag(monster->type, M_SPELLCASTER) ... @@ -3974,6 +3783,9 @@ static void monster_add_energy(monsters *monster) energy_gained = 1; monster->speed_increment += energy_gained; + + if (you.duration[DUR_SLOW] > 0) + monster->speed_increment += energy_gained; } // Do natural regeneration for monster. @@ -4012,29 +3824,6 @@ static void monster_regenerate(monsters *monster) } } -static void swim_or_move_energy(monsters *mon) -{ - monsterentry *entry = get_monster_data(mon->type); - dungeon_feature_type feat = grd[mon->x][mon->y]; - if (feat >= DNGN_LAVA && feat <= DNGN_SHALLOW_WATER - && !mon->airborne()) - { - mon->speed_increment -= entry->energy_usage.swim; - } - else - mon->speed_increment -= entry->energy_usage.move; -} - -#if DEBUG -# define DEBUG_ENERGY_USE(problem) \ - if (monster->speed_increment == old_energy) \ - mprf(MSGCH_DIAGNOSTICS, \ - problem " for monster '%s' consumed no energy", \ - monster->name(DESC_PLAIN).c_str(), true); -#else -# define DEBUG_ENERGY_USE(problem) ((void) 0) -#endif - static void handle_monster_move(int i, monsters *monster) { bool brkk = false; @@ -4053,7 +3842,7 @@ static void handle_monster_move(int i, monsters *monster) monster_add_energy(monster); - // Handle clouds on nonmoving monsters: + // Handle enchantments and clouds on nonmoving monsters: if (monster->speed == 0) { if (env.cgrid[monster->x][monster->y] != EMPTY_CLOUD @@ -4061,25 +3850,9 @@ static void handle_monster_move(int i, monsters *monster) { mons_in_cloud( monster ); } - } - - // Apply monster enchantments once for every normal-speed - // player turn. - monster->ench_countdown -= you.time_taken; - while (monster->ench_countdown < 0) - { - monster->ench_countdown += 10; - monster->apply_enchantments(); - // If the monster *merely* died just break from the loop - // rather than quit altogether, since we have to deal with - // giant spores and ball lightning exploding at the end of the - // function, but do return if the monster's data has been - // reset, since then the monster type is invalid. - if (monster->type == -1) + if (handle_enchantment( monster )) return; - else if (monster->hit_points < 1) - break; } // memory is decremented here for a reason -- we only want it @@ -4106,47 +3879,21 @@ static void handle_monster_move(int i, monsters *monster) } monster->check_speed(); - - monsterentry* entry = get_monster_data(monster->type); - - int old_energy = INT_MAX; - int non_move_energy = std::min(entry->energy_usage.move, - entry->energy_usage.swim); - + while (monster->has_action_energy()) { // The continues & breaks are WRT this. if (!monster->alive()) break; - if (monster->speed_increment >= old_energy) - { -#if DEBUG - if (monster->speed_increment == old_energy) - mprf(MSGCH_DIAGNOSTICS, "'%s' has same energy as last loop", - monster->name(DESC_PLAIN, true).c_str()); - else - mprf(MSGCH_DIAGNOSTICS, "'%s' has MORE energy than last loop", - monster->name(DESC_PLAIN, true).c_str()); -#endif - monster->speed_increment = old_energy - 10; - old_energy = monster->speed_increment; - continue; - } - old_energy = monster->speed_increment; + monster->speed_increment -= 10; if (env.cgrid[monster->x][monster->y] != EMPTY_CLOUD) { if (monster->has_ench(ENCH_SUBMERGED)) - { - monster->speed_increment -= entry->energy_usage.swim; break; - } if (monster->type == -1) - { - monster->speed_increment -= entry->energy_usage.move; break; // problem with vortices - } mons_in_cloud(monster); @@ -4164,13 +3911,13 @@ static void handle_monster_move(int i, monsters *monster) monster->colour = newcol; } + if (handle_enchantment(monster)) + break; + monster_regenerate(monster); if (mons_is_paralysed(monster)) - { - monster->speed_increment -= non_move_energy; continue; - } handle_behaviour(monster); @@ -4182,10 +3929,7 @@ static void handle_monster_move(int i, monsters *monster) } if (monster->speed >= 100) - { - monster->speed_increment -= non_move_energy; continue; - } if (monster->type == MONS_ZOMBIE_SMALL || monster->type == MONS_ZOMBIE_LARGE @@ -4207,17 +3951,11 @@ static void handle_monster_move(int i, monsters *monster) if (monster->attitude != ATT_FRIENDLY) { if (handle_pickup(monster)) - { - DEBUG_ENERGY_USE("handle_pickup()"); continue; - } } } - if (mons_is_caught(monster)) - // Struggling against the net takes time. - swim_or_move_energy(monster); - else + if (!mons_is_caught(monster)) { // calculates mmov_x, mmov_y based on monster target. handle_movement(monster); @@ -4236,7 +3974,7 @@ static void handle_monster_move(int i, monsters *monster) for (int xi = -1; xi <= 1; ++xi) { coord_def c = monster->pos() + coord_def(xi, yi); - if (in_bounds(c) && monster->can_pass_through(c) + if (in_bounds(c) && !grid_is_solid(grd(c)) && one_chance_in(++pfound)) { mmov_x = xi; @@ -4262,8 +4000,8 @@ static void handle_monster_move(int i, monsters *monster) mmov_y = 0; } - if (!monster->can_pass_through(monster->x + mmov_x, - monster->y + mmov_y)) + if (grid_is_solid( + grd[ monster->x + mmov_x ][ monster->y + mmov_y ])) { mmov_x = mmov_y = 0; } @@ -4274,11 +4012,10 @@ static void handle_monster_move(int i, monsters *monster) monsters_fight( i, mgrd[monster->x + mmov_x][monster->y + mmov_y]); - + brkk = true; mmov_x = 0; mmov_y = 0; - DEBUG_ENERGY_USE("monsters_fight()"); } } @@ -4311,40 +4048,24 @@ static void handle_monster_move(int i, monsters *monster) : handle_monster_spell(monster, beem) || handle_special_ability(monster, beem)) { - DEBUG_ENERGY_USE("spell or special"); continue; } if (handle_potion(monster, beem)) - { - DEBUG_ENERGY_USE("handle_potion()"); continue; - } if (handle_scroll(monster)) - { - DEBUG_ENERGY_USE("handle_scroll()"); continue; - } if (handle_wand(monster, beem)) - { - DEBUG_ENERGY_USE("handle_wand()"); continue; - } if (handle_reaching(monster)) - { - DEBUG_ENERGY_USE("handle_reaching()"); continue; - } } if (handle_throw(monster, beem)) - { - DEBUG_ENERGY_USE("handle_throw()"); continue; - } } if (!mons_is_caught(monster)) @@ -4369,7 +4090,6 @@ static void handle_monster_move(int i, monsters *monster) mmov_x = 0; mmov_y = 0; brkk = true; - DEBUG_ENERGY_USE("monsters_fight()"); } } @@ -4393,7 +4113,6 @@ static void handle_monster_move(int i, monsters *monster) monster->target_x = 10 + random2(GXM - 10); monster->target_y = 10 + random2(GYM - 10); } - DEBUG_ENERGY_USE("monster_attack()"); } if ((monster->type == MONS_GIANT_SPORE @@ -4419,17 +4138,10 @@ static void handle_monster_move(int i, monsters *monster) } if (invalid_monster(monster) || mons_is_stationary(monster)) - { - if (monster->speed_increment == old_energy) - monster->speed_increment -= non_move_energy; continue; - } - if (!monster_move(monster)) - monster->speed_increment -= non_move_energy; + monster_move(monster); } - update_beholders(monster); - // reevaluate behaviour, since the monster's // surroundings have changed (it may have moved, // or died for that matter. Don't bother for @@ -4447,7 +4159,7 @@ static void handle_monster_move(int i, monsters *monster) // detach monster from the grid first, so it // doesn't get hit by its own explosion (GDL) mgrd[monster->x][monster->y] = NON_MONSTER; - + spore_goes_pop( monster ); monster_cleanup( monster ); return; @@ -4456,7 +4168,7 @@ static void handle_monster_move(int i, monsters *monster) { monster_die( monster, KILL_MISC, 0 ); } - } + } } //--------------------------------------------------------------- @@ -4489,15 +4201,7 @@ void handle_monsters(void) // If the player got banished, discard pending monster actions. if (you.banished) - { - // clear list of beholding monsters - if (you.duration[DUR_BEHELD]) - { - you.beheld_by.clear(); - you.duration[DUR_BEHELD] = 0; - } break; - } } // end of for loop // Clear any summoning flags so that lower indiced @@ -4555,11 +4259,10 @@ static bool handle_pickup(monsters *monster) if (mons_itemuse(monster->type) == MONUSE_EATS_ITEMS) { - int midx = monster_index(monster); - int hps_gained = 0; - int max_eat = roll_dice( 1, 10 ); - int eaten = 0; - bool eaten_net = false; + int hps_gained = 0; + int max_eat = roll_dice( 1, 10 ); + int eaten = 0; + bool eaten_net = false; for (item = igrd[monster->x][monster->y]; item != NON_ITEM && eaten < max_eat && hps_gained < 50; @@ -4597,9 +4300,6 @@ static bool handle_pickup(monsters *monster) eaten++; } - if (quant >= mitm[item].quantity) - item_was_destroyed(mitm[item], midx); - dec_mitm_item_quantity( item, quant ); } @@ -4639,7 +4339,7 @@ static bool handle_pickup(monsters *monster) return (false); } // end "if jellies" - // Note: Monsters only look at stuff near the top of stacks. + // Note: Monsters only look at top of stacks. for (item = igrd[monster->x][monster->y]; item != NON_ITEM; ) { @@ -4751,8 +4451,6 @@ static bool monster_swaps_places( monsters *mon, int mx, int my ) return (false); // Okay, do the swap! - swim_or_move_energy(mon); - mon->x = nx; mon->y = ny; mgrd[nx][ny] = monster_index(mon); @@ -4771,52 +4469,55 @@ static bool monster_swaps_places( monsters *mon, int mx, int my ) return (false); } -static bool do_move_monster(monsters *monster, int xi, int yi) +static void do_move_monster(monsters *monster, int xi, int yi) { const int fx = monster->x + xi, fy = monster->y + yi; if (!in_bounds(fx, fy)) - return false; + return; if (fx == you.x_pos && fy == you.y_pos) { monster_attack( monster_index(monster) ); - return true; + return; } if (!xi && !yi) { const int mx = monster_index(monster); monsters_fight( mx, mx ); - return true; + return; } if (mgrd[fx][fy] != NON_MONSTER) { monsters_fight( monster_index(monster), mgrd[fx][fy] ); - return true; + return; } if (!xi && !yi) - return false; - - /* this appears to be the real one, ie where the movement occurs: */ - swim_or_move_energy(monster); + return; mgrd[monster->x][monster->y] = NON_MONSTER; + /* this appears to be the real one, ie where the movement occurs: */ monster->x = fx; monster->y = fy; + if (monster->type == MONS_CURSE_TOE) + { + // Curse toes are a special case; they can only move at half their + // attack rate. To simulate that, the toe loses more energy. + monster->speed_increment -= 5; + } + /* need to put in something so that monster picks up multiple items (eg ammunition) identical to those it's carrying. */ mgrd[monster->x][monster->y] = monster_index(monster); monster->check_redraw(monster->pos() - coord_def(xi, yi)); monster->apply_location_effects(); - - return true; } void mons_check_pool(monsters *mons, killer_type killer, int killnum) @@ -4872,129 +4573,28 @@ void mons_check_pool(monsters *mons, killer_type killer, int killnum) } } -// returns true for monsters that obviously (to the player) feel -// "thematically at home" in a branch -// currently used for native monsters recognizing traps -static bool is_native_in_branch(const monsters *monster, const branch_type branch) -{ - switch (branch) - { - case BRANCH_ELVEN_HALLS: - if (mons_species(monster->type) == MONS_ELF) - return true; - return false; - - case BRANCH_ORCISH_MINES: - if (mons_species(monster->type) == MONS_ORC) - return true; - return false; - - case BRANCH_SLIME_PITS: - if (mons_species(monster->type) == MONS_JELLY) - return true; - return false; - - case BRANCH_SNAKE_PIT: - if (mons_species(monster->type) == MONS_NAGA - || mons_species(monster->type) == MONS_SNAKE) - { - return true; - } - return false; - - case BRANCH_HALL_OF_ZOT: - if (mons_species(monster->type) == MONS_DRACONIAN) - return true; - return false; - - case BRANCH_TOMB: - if (mons_species(monster->type) == MONS_MUMMY) - return true; - return false; - - case BRANCH_HIVE: - if (monster->type == MONS_KILLER_BEE - || monster->type == MONS_KILLER_BEE_LARVA) - { - return true; - } - return false; - - case BRANCH_HALL_OF_BLADES: - if (monster->type == MONS_DANCING_WEAPON) - return true; - return false; - - default: - return false; - } -} - -// randomize potential damage -static int estimated_trap_damage(trap_type trap) -{ - switch (trap) - { - case TRAP_BLADE: - return (10 + random2(30)); - case TRAP_DART: - return (random2(4)); - case TRAP_ARROW: - return (random2(7)); - case TRAP_SPEAR: - return (random2(10)); - case TRAP_BOLT: - return (random2(13)); - case TRAP_AXE: - return (random2(15)); - default: - return (0); - } -} - -static bool mon_can_move_to_pos(const monsters *monster, const int count_x, - const int count_y, bool just_check = false); +static bool mon_can_move_to_pos(const monsters *monster, const int okmove, + const int count_x, const int count_y, + bool just_check = false); // Check whether a given trap (described by trap position) can be // regarded as safe. Takes in account monster intelligence and allegiance. -// (just_check is used for intelligent monsters trying to avoid traps.) +// (just_check is used for intelligent friendlies trying to avoid traps.) static bool is_trap_safe(const monsters *monster, const int trap_x, - const int trap_y, bool just_check = false) + const int trap_y, const int okmove, + bool just_check = false) { - const int intel = mons_intel(monster->type); + const trap_struct &trap = env.trap[trap_at_xy(trap_x,trap_y)]; // Dumb monsters don't care at all. - if (intel == I_PLANT) + if (mons_intel(monster->type) == I_PLANT) return (true); - - const trap_struct &trap = env.trap[trap_at_xy(trap_x,trap_y)]; - if (trap.type == TRAP_SHAFT && monster->will_trigger_shaft()) - { - if (mons_is_fleeing(monster) && intel >= I_NORMAL) - return (true); - return (false); - } - - // Monsters are not afraid of non-mechanical traps. XXX: If we add - // any non-mechanical traps that can damage monsters, must add - // check here. - const bool mechanical = trap_category(trap.type) == DNGN_TRAP_MECHANICAL; - - const bool player_knows_trap = (grd[trap_x][trap_y] != DNGN_UNDISCOVERED_TRAP); - - // Smarter trap handling for intelligent monsters - // * monsters native to a branch can be assumed to know the trap - // locations and thus be able to avoid them - // * permanent friendlies can be assumed to have been warned by the - // player about all traps s/he knows about - // * very intelligent monsters can be assumed to have a high T&D skill - // (or have memorized part of the dungeon layout ;) ) - if (intel >= I_NORMAL && mechanical - && (is_native_in_branch(monster, you.where_are_you) - || monster->attitude == ATT_FRIENDLY - && player_knows_trap - || intel >= I_HIGH && one_chance_in(3))) + // permanent intelligent friendlies will try to avoid traps + // the player knows about (we're assuming s/he warned them about them) + if (grd[trap_x][trap_y] != DNGN_UNDISCOVERED_TRAP + && trap_category(trap.type) != DNGN_TRAP_MAGICAL // magic doesn't matter + && intelligent_ally(monster)) { if (just_check) return false; // square is blocked @@ -5022,10 +4622,10 @@ static bool is_trap_safe(const monsters *monster, const int trap_x, // If a monster still gets stuck in a corridor it will usually be // because it has less than half its maximum hp - if ((mon_can_move_to_pos(monster, x-1, y, true) - || mon_can_move_to_pos(monster, x+1,y, true)) - && (mon_can_move_to_pos(monster, x,y-1, true) - || mon_can_move_to_pos(monster, x,y+1, true))) + if ((mon_can_move_to_pos(monster, okmove, x-1, y, true) + || mon_can_move_to_pos(monster, okmove, x+1, y, true)) + && (mon_can_move_to_pos(monster, okmove, x, y-1, true) + || mon_can_move_to_pos(monster, okmove, x, y+1, true))) { return (false); } @@ -5034,19 +4634,22 @@ static bool is_trap_safe(const monsters *monster, const int trap_x, // friendlies will try not to be parted from you if (intelligent_ally(monster) && trap.type == TRAP_TELEPORT - && player_knows_trap && mons_near(monster)) + && mons_near(monster)) { return (false); } - - // Healthy monsters don't mind a little pain. - if (mechanical && monster->hit_points >= monster->max_hit_points / 2 - && (intel == I_ANIMAL - || monster->hit_points > estimated_trap_damage(trap.type))) - { + + // Healthy monsters don't mind a little pain. XXX: Smart humanoids + // with low hp should probably not try to go through high-damage + // traps. + if (monster->hit_points >= monster->max_hit_points / 2) return (true); - } - + + // Monsters are not afraid of non-mechanical traps. XXX: If we add + // any non-mechanical traps that can damage monsters, must add + // check here. + const bool mechanical = trap_category(trap.type) == DNGN_TRAP_MECHANICAL; + // Friendly monsters don't enjoy Zot trap perks, handle accordingly. if (mons_friendly(monster)) return (mechanical? mons_flies(monster) : trap.type != TRAP_ZOT); @@ -5054,41 +4657,22 @@ static bool is_trap_safe(const monsters *monster, const int trap_x, return (!mechanical || mons_flies(monster)); } -static void mons_open_door(monsters* monster, const coord_def &pos) +static void mons_open_door(const coord_def &pos) { - bool was_secret = (grd(pos) == DNGN_SECRET_DOOR); - - if (was_secret && !see_grid(pos)) + if (grd(pos) == DNGN_SECRET_DOOR && !see_grid(pos)) set_terrain_changed(pos); grd(pos) = DNGN_OPEN_DOOR; - - if (see_grid(pos)) - { - viewwindow(true, false); - - if (was_secret) - mpr("The rock wall was actually a secret door!"); - - if (!you.can_see(monster)) - { - mpr("Something unseen opens the door."); - interrupt_activity(AI_FORCE_INTERRUPT); - } - } - - monsterentry *entry = get_monster_data(monster->type); - monster->speed_increment -= entry->energy_usage.move; } // Check whether a monster can move to given square (described by its relative // coordinates to the current monster position). just_check is true only for // calls from is_trap_safe when checking the surrounding squares of a trap. -bool mon_can_move_to_pos(const monsters *monster, const int count_x, - const int count_y, bool just_check) +bool mon_can_move_to_pos(const monsters *monster, const int okmove, + const int count_x, const int count_y, bool just_check) { const int targ_x = monster->x + count_x; const int targ_y = monster->y + count_y; - + // bounds check - don't consider moving out of grid! if (targ_x < 0 || targ_x >= GXM || targ_y < 0 || targ_y >= GYM) return false; @@ -5097,13 +4681,6 @@ bool mon_can_move_to_pos(const monsters *monster, const int count_x, const int habitat = monster_habitat( monster->type ); - // effectively slows down monster movement across water. - // Fire elementals can't cross at all. - bool no_water = false; - if (monster->type == MONS_FIRE_ELEMENTAL || one_chance_in(5)) - //okmove = DNGN_WATER_STUCK; - no_water = true; - const int targ_cloud_num = env.cgrid[ targ_x ][ targ_y ]; const int targ_cloud_type = targ_cloud_num == EMPTY_CLOUD? CLOUD_NONE @@ -5115,8 +4692,7 @@ bool mon_can_move_to_pos(const monsters *monster, const int count_x, : env.cloud[curr_cloud_num].type; if (monster->type == MONS_BORING_BEETLE - && (target_grid == DNGN_ROCK_WALL - || target_grid == DNGN_CLEAR_ROCK_WALL)) + && target_grid == DNGN_ROCK_WALL) { // don't burrow out of bounds if (targ_x <= 7 || targ_x >= (GXM - 8) @@ -5127,21 +4703,13 @@ bool mon_can_move_to_pos(const monsters *monster, const int count_x, // don't burrow at an angle (legacy behaviour) if (count_x != 0 && count_y != 0) - { return false; - } } - else if (!monster->can_pass_through(target_grid) - || (no_water && target_grid >= DNGN_DEEP_WATER - && target_grid <= DNGN_WATER_STUCK)) - { + else if (grd[ targ_x ][ targ_y ] < okmove) return false; - } else if (!habitat_okay( monster, target_grid )) - { return false; - } - + if (monster->type == MONS_WANDERING_MUSHROOM && see_grid(targ_x, targ_y)) { @@ -5180,7 +4748,7 @@ bool mon_can_move_to_pos(const monsters *monster, const int count_x, { return false; } - + // smacking the player is always a good move if we're // hostile (even if we're heading somewhere else) // also friendlies want to keep close to the player @@ -5194,7 +4762,7 @@ bool mon_can_move_to_pos(const monsters *monster, const int count_x, { if (targ_x == monster->x && targ_y == monster->y) return true; - + return false; // blocks square } @@ -5208,11 +4776,12 @@ bool mon_can_move_to_pos(const monsters *monster, const int count_x, return false; } } - + // wandering through a trap is OK if we're pretty healthy, // really stupid, or immune to the trap const int which_trap = trap_at_xy(targ_x,targ_y); - if (which_trap >= 0 && !is_trap_safe(monster, targ_x, targ_y, just_check)) + if (which_trap >= 0 + && !is_trap_safe(monster, targ_x, targ_y, okmove, just_check)) { return false; } @@ -5271,7 +4840,7 @@ bool mon_can_move_to_pos(const monsters *monster, const int count_x, if (monster->hit_points >= random2avg(19, 2)) return true; break; - + default: return true; // harmless clouds } @@ -5281,16 +4850,16 @@ bool mon_can_move_to_pos(const monsters *monster, const int count_x, if (mons_intel(monster->type) != I_PLANT) return false; } - + // if we end up here the monster can safely move return true; } -static bool monster_move(monsters *monster) +static void monster_move(monsters *monster) { FixedArray < bool, 3, 3 > good_move; int count_x, count_y, count; - int okmove = DNGN_SHALLOW_WATER; // what does this actually do? + int okmove = DNGN_SHALLOW_WATER; const int habitat = monster_habitat( monster->type ); bool deep_water_available = false; @@ -5328,15 +4897,27 @@ static bool monster_move(monsters *monster) && (habitat == DNGN_FLOOR || monster_habitable_grid(monster, grd(newpos)))) { - return do_move_monster(monster, mmov_x, mmov_y); + do_move_monster(monster, mmov_x, mmov_y); } } - return false; + return; } // let's not even bother with this if mmov_x and mmov_y are zero. if (mmov_x == 0 && mmov_y == 0) - return false; + return; + + // effectively slows down monster movement across water. + // Fire elementals can't cross at all. + if (monster->type == MONS_FIRE_ELEMENTAL || one_chance_in(5)) + okmove = DNGN_WATER_STUCK; + + // effectively slows down monster movement across water. + // Fire elementals can't cross at all. + bool no_water = false; + if (monster->type == MONS_FIRE_ELEMENTAL || one_chance_in(5)) + //okmove = DNGN_WATER_STUCK; + no_water = true; if (mons_flies(monster) > 0 || habitat != DNGN_FLOOR @@ -5349,26 +4930,28 @@ static bool monster_move(monsters *monster) { for (count_y = 0; count_y < 3; count_y++) { - const int targ_x = monster->x + count_x - 1; - const int targ_y = monster->y + count_y - 1; + const int targ_x = monster->x + count_x - 1; + const int targ_y = monster->y + count_y - 1; - // [ds] Bounds check was after grd[targ_x][targ_y] which would - // trigger an ASSERT. Moved it up. + // [ds] Bounds check was after grd[targ_x][targ_y] which would + // trigger an ASSERT. Moved it up. - // bounds check - don't consider moving out of grid! - if (targ_x < 0 || targ_x >= GXM || targ_y < 0 || targ_y >= GYM) - { - good_move[count_x][count_y] = false; - continue; - } - dungeon_feature_type target_grid = grd[targ_x][targ_y]; + // bounds check - don't consider moving out of grid! + if (targ_x < 0 || targ_x >= GXM || targ_y < 0 || targ_y >= GYM) + { + good_move[count_x][count_y] = false; + continue; + } + + int target_grid = grd[targ_x][targ_y]; + + if (target_grid == DNGN_DEEP_WATER) + deep_water_available = true; - if (target_grid == DNGN_DEEP_WATER) - deep_water_available = true; + const monsters* mons = dynamic_cast<const monsters*>(monster); + good_move[count_x][count_y] = + mon_can_move_to_pos(mons, okmove, count_x-1, count_y-1); - const monsters* mons = dynamic_cast<const monsters*>(monster); - good_move[count_x][count_y] = - mon_can_move_to_pos(mons, count_x-1, count_y-1); } } // now we know where we _can_ move. @@ -5391,14 +4974,14 @@ static bool monster_move(monsters *monster) // for zombies, monster type is kept in mon->number if (mons_itemuse(monster->number) >= MONUSE_OPEN_DOORS) { - mons_open_door(monster, newpos); - return true; + mons_open_door(newpos); + return; } } else if (mons_itemuse(monster->type) >= MONUSE_OPEN_DOORS) { - mons_open_door(monster, newpos); - return true; + mons_open_door(newpos); + return; } } // endif - secret/closed doors @@ -5410,17 +4993,6 @@ static bool monster_move(monsters *monster) grd[monster->x + mmov_x][monster->y + mmov_y] = DNGN_FLOOR; jelly_grows(monster); - - if (see_grid(monster->x + mmov_x, monster->y + mmov_y)) - { - viewwindow(true, false); - - if (!you.can_see(monster)) - { - mpr("The door mysteriously vanishes."); - interrupt_activity( AI_FORCE_INTERRUPT ); - } - } } // done door-eating jellies @@ -5566,9 +5138,7 @@ forget_it: // take care of beetle burrowing if (monster->type == MONS_BORING_BEETLE) { - dungeon_feature_type feat = - grd[monster->x + mmov_x][monster->y + mmov_y]; - if ((feat == DNGN_ROCK_WALL || feat == DNGN_ROCK_WALL) + if (grd[monster->x + mmov_x][monster->y + mmov_y] == DNGN_ROCK_WALL && good_move[mmov_x + 1][mmov_y + 1] == true) { grd[monster->x + mmov_x][monster->y + mmov_y] = DNGN_FLOOR; @@ -5579,14 +5149,13 @@ forget_it: } } - bool ret = false; if (good_move[mmov_x + 1][mmov_y + 1] && !(mmov_x == 0 && mmov_y == 0)) { // check for attacking player if (monster->x + mmov_x == you.x_pos && monster->y + mmov_y == you.y_pos) { - ret = monster_attack( monster_index(monster) ); + monster_attack( monster_index(monster) ); mmov_x = 0; mmov_y = 0; } @@ -5604,19 +5173,18 @@ forget_it: #ifdef DEBUG_DIAGNOSTICS mprf(MSGCH_DIAGNOSTICS, "BUG: %s was marked as follower when not following!", - monster->name(DESC_PLAIN).c_str(), true); + monster->name(DESC_PLAIN).c_str()); #endif } else { - ret = true; mmov_x = 0; mmov_y = 0; #if DEBUG_DIAGNOSTICS mprf(MSGCH_DIAGNOSTICS, "%s is skipping movement in order to follow.", - monster->name(DESC_CAP_THE).c_str(), true ); + monster->name(DESC_CAP_THE).c_str() ); #endif } } @@ -5626,12 +5194,9 @@ forget_it: if (targmon != NON_MONSTER) { if (mons_aligned(monster_index(monster), targmon)) - ret = monster_swaps_places(monster, mmov_x, mmov_y); + monster_swaps_places(monster, mmov_x, mmov_y); else - { monsters_fight(monster_index(monster), targmon); - ret = true; - } // If the monster swapped places, the work's already done. mmov_x = 0; @@ -5663,9 +5228,7 @@ forget_it: } if (mmov_x || mmov_y || (monster->confused() && one_chance_in(6))) - return do_move_monster(monster, mmov_x, mmov_y); - - return ret; + do_move_monster(monster, mmov_x, mmov_y); } // end monster_move() static void setup_plant_spit(monsters *monster, bolt &pbolt) @@ -5786,6 +5349,7 @@ static void mons_in_cloud(monsters *monster) hurted -= random2(1 + monster->ac); break; // to damage routine at end {dlb} + // what of armour of poison resistance here? {dlb} case CLOUD_POISON: simple_monster_message(monster, " is engulfed in a cloud of poison!"); @@ -5880,8 +5444,6 @@ dungeon_feature_type monster_habitat(int which_class) { switch (which_class) { - case MONS_MERFOLK: - case MONS_MERMAID: case MONS_BIG_FISH: case MONS_GIANT_GOLDFISH: case MONS_ELECTRICAL_EEL: @@ -5897,9 +5459,6 @@ dungeon_feature_type monster_habitat(int which_class) case MONS_SALAMANDER: return (DNGN_LAVA); - case MONS_ROCK_WORM: - return (DNGN_ROCK_WALL); - default: return (DNGN_FLOOR); // closest match to terra firma {dlb} } @@ -5971,17 +5530,6 @@ bool monster_descriptor(int which_class, unsigned char which_descriptor) bool message_current_target() { - - if (crawl_state.is_replaying_keys()) - { - if (you.prev_targ == MHITNOT || you.prev_targ == MHITYOU) - return false; - - const monsters *montarget = &menv[you.prev_targ]; - return (you.prev_targ != MHITNOT && you.prev_targ != MHITYOU - && mons_near(montarget) && player_monster_visible(montarget)); - } - if (you.prev_targ != MHITNOT && you.prev_targ != MHITYOU) { const monsters *montarget = &menv[you.prev_targ]; |