diff options
-rw-r--r-- | crawl-ref/source/fight.cc | 21 | ||||
-rw-r--r-- | crawl-ref/source/mon-util.cc | 101 | ||||
-rw-r--r-- | crawl-ref/source/mon-util.h | 8 | ||||
-rw-r--r-- | crawl-ref/source/monplace.cc | 183 | ||||
-rw-r--r-- | crawl-ref/source/monplace.h | 7 | ||||
-rw-r--r-- | crawl-ref/source/monstuff.cc | 123 | ||||
-rw-r--r-- | crawl-ref/source/mstuff2.cc | 9 | ||||
-rw-r--r-- | crawl-ref/source/spells3.cc | 2 | ||||
-rw-r--r-- | crawl-ref/source/stuff.cc | 3 |
9 files changed, 285 insertions, 172 deletions
diff --git a/crawl-ref/source/fight.cc b/crawl-ref/source/fight.cc index 0eaafa19a5..b694f09412 100644 --- a/crawl-ref/source/fight.cc +++ b/crawl-ref/source/fight.cc @@ -280,14 +280,8 @@ bool you_attack(int monster_attacked, bool unarmed_attacks) // wet merfolk if (player_is_swimming() - // monster not a water creature - && monster_habitat( defender->type ) != DNGN_DEEP_WATER - && !mons_class_flag( defender->type, M_AMPHIBIOUS ) - // monster in water - && (grd[defender->x][defender->y] == DNGN_SHALLOW_WATER - || grd[defender->x][defender->y] == DNGN_DEEP_WATER) - // monster not flying - && !mons_flies( defender )) + // monster not a water creature, but is in water + && monster_floundering(defender)) { water_attack = true; } @@ -2957,19 +2951,14 @@ bool monsters_fight(int monster_attacking, int monster_attacked) return false; } - if (grd[attacker->x][attacker->y] == DNGN_SHALLOW_WATER - && !mons_flies( attacker ) - && !mons_class_flag( attacker->type, M_AMPHIBIOUS ) - && habitat == DNGN_FLOOR - && one_chance_in(4)) + if (monster_floundering(attacker) && one_chance_in(4)) { mpr("You hear a splashing noise."); return true; } - if (grd[defender->x][defender->y] == DNGN_SHALLOW_WATER - && !mons_flies(defender) - && habitat == DNGN_DEEP_WATER) + // habitat is the favoured habitat of the attacker + if (monster_floundering(defender) && habitat == DNGN_DEEP_WATER) { water_attack = true; } diff --git a/crawl-ref/source/mon-util.cc b/crawl-ref/source/mon-util.cc index 641662f184..1d229c02c9 100644 --- a/crawl-ref/source/mon-util.cc +++ b/crawl-ref/source/mon-util.cc @@ -31,6 +31,7 @@ #include "debug.h" #include "itemname.h" #include "itemprop.h" +#include "monplace.h" #include "mstuff2.h" #include "player.h" #include "randart.h" @@ -43,6 +44,20 @@ static FixedVector < int, NUM_MONSTERS > mon_entry; // really important extern -- screen redraws suck w/o it {dlb} FixedVector < unsigned short, 1000 > mcolour; +enum habitat_type +{ + // Flying monsters will appear in all categories + HT_NORMAL, // Normal critters + HT_SHALLOW_WATER, // Union of normal + water + HT_DEEP_WATER, // Water critters + HT_LAVA, // Lava critters + + NUM_HABITATS +}; + +static bool initialized_randmons = false; +static std::vector<int> monsters_by_habitat[NUM_HABITATS]; + static struct monsterentry mondata[] = { #include "mon-data.h" }; @@ -118,6 +133,72 @@ static monsterentry *seekmonster(int p_monsterid); #define smc seekmonster(mc) /* ******************** BEGIN PUBLIC FUNCTIONS ******************** */ + +habitat_type grid2habitat(int grid) +{ + switch (grid) + { + case DNGN_DEEP_WATER: + return (HT_DEEP_WATER); + case DNGN_SHALLOW_WATER: + return (HT_SHALLOW_WATER); + case DNGN_LAVA: + return (HT_LAVA); + default: + return (HT_NORMAL); + } +} + +int habitat2grid(habitat_type ht) +{ + switch (ht) + { + case HT_DEEP_WATER: + return (DNGN_DEEP_WATER); + case HT_SHALLOW_WATER: + return (DNGN_SHALLOW_WATER); + case HT_LAVA: + return (DNGN_LAVA); + case HT_NORMAL: + default: + return (DNGN_FLOOR); + } +} + +static void initialize_randmons() +{ + for (int i = 0; i < NUM_HABITATS; ++i) + { + int grid = habitat2grid( habitat_type(i) ); + + for (int m = 0; m < NUM_MONSTERS; ++m) + { + if (invalid_monster_class(m)) + continue; + if (monster_habitable_grid(m, grid)) + monsters_by_habitat[i].push_back(m); + } + } + initialized_randmons = true; +} + +monster_type random_monster_at_grid(int x, int y) +{ + return (random_monster_at_grid(grd[x][y])); +} + +monster_type random_monster_at_grid(int grid) +{ + if (!initialized_randmons) + initialize_randmons(); + + const habitat_type ht = grid2habitat(grid); + const std::vector<int> &valid_mons = monsters_by_habitat[ht]; + ASSERT(!valid_mons.empty()); + return valid_mons.empty()? MONS_PROGRAM_BUG + : monster_type(valid_mons[ random2(valid_mons.size()) ]); +} + void init_monsters(FixedVector < unsigned short, 1000 > &colour) { unsigned int x; // must be unsigned to match size_t {dlb} @@ -159,7 +240,7 @@ bool mons_class_flag(int mc, int bf) return ((smc->bitfields & bf) != 0); } // end mons_class_flag() -static int scan_mon_inv_randarts( struct monsters *mon, int ra_prop ) +static int scan_mon_inv_randarts( const monsters *mon, int ra_prop ) { int ret = 0; @@ -216,6 +297,14 @@ bool invalid_monster(const monsters *mons) return (!mons || mons->type == -1); } +bool invalid_monster_class(int mclass) +{ + return (mclass < 0 + || mclass >= NUM_MONSTERS + || mon_entry[mclass] == -1 + || mon_entry[mclass] == MONS_PROGRAM_BUG); +} + bool mons_is_mimic( int mc ) { return (mons_species( mc ) == MONS_GOLD_MIMIC); @@ -285,7 +374,8 @@ corpse_effect_type mons_corpse_effect(int mc) monster_type mons_species( int mc ) { - return (smc->species); + const monsterentry *me = seekmonster(mc); + return (me? me->species : MONS_PROGRAM_BUG); } // end mons_species() monster_type mons_genus( int mc ) @@ -698,7 +788,7 @@ int mons_skeleton(int mc) return (1); } // end mons_skeleton() -char mons_class_flies(int mc) +int mons_class_flies(int mc) { if (mc == MONS_PANDEMONIUM_DEMON) return (ghost.values[ GVAL_DEMONLORD_FLY ]); @@ -714,10 +804,9 @@ char mons_class_flies(int mc) return (0); } -char mons_flies( struct monsters *mon ) +int mons_flies( const monsters *mon ) { - char ret = mons_class_flies( mon->type ); - + int ret = mons_class_flies( mon->type ); return (ret ? ret : (scan_mon_inv_randarts(mon, RAP_LEVITATE) > 0) ? 2 : 0); } // end mons_flies() diff --git a/crawl-ref/source/mon-util.h b/crawl-ref/source/mon-util.h index e6f97da0e6..55695d203b 100644 --- a/crawl-ref/source/mon-util.h +++ b/crawl-ref/source/mon-util.h @@ -140,8 +140,8 @@ const char *ptr_monam( struct monsters *mon, char desc ); /* *********************************************************************** * called from: beam - direct - fight - monstuff - mstuff2 - spells4 - view * *********************************************************************** */ -char mons_class_flies( int mc ); -char mons_flies( struct monsters *mon ); +int mons_class_flies( int mc ); +int mons_flies( const monsters *mon ); // last updated XXmay2000 {dlb} @@ -430,6 +430,7 @@ bool check_mons_resist_magic( struct monsters *monster, int pow ); bool mons_is_stationary(const monsters *mons); bool invalid_monster(const monsters *mons); +bool invalid_monster_class(int mclass); bool monster_shover(const monsters *m); bool mons_is_paralysed(const monsters *m); @@ -437,4 +438,7 @@ bool mons_is_paralysed(const monsters *m); bool monster_senior(const monsters *first, const monsters *second); monster_type draco_subspecies( const monsters *mon ); +monster_type random_monster_at_grid(int x, int y); +monster_type random_monster_at_grid(int grid); + #endif diff --git a/crawl-ref/source/monplace.cc b/crawl-ref/source/monplace.cc index beef83df3c..355afb7d8d 100644 --- a/crawl-ref/source/monplace.cc +++ b/crawl-ref/source/monplace.cc @@ -41,6 +41,101 @@ static int place_monster_aux(int mon_type, char behaviour, int target, int px, int py, int power, int extra, bool first_band_member, int dur = 0); +// Returns whether actual_grid is compatible with grid_wanted for monster +// movement (or for monster generation, if generation is true). +bool grid_compatible(int grid_wanted, int actual_grid, bool generation) +{ + // XXX What in Xom's name is DNGN_WATER_STUCK? It looks like an artificial + // device to slow down fiery monsters flying over water. + if (grid_wanted == DNGN_FLOOR) + return actual_grid >= DNGN_FLOOR + || (!generation + && actual_grid == DNGN_SHALLOW_WATER); + + return (grid_wanted == actual_grid + || (grid_wanted == DNGN_DEEP_WATER + && (actual_grid == DNGN_SHALLOW_WATER + || actual_grid == DNGN_BLUE_FOUNTAIN))); +} + +// Can this monster happily on actual_grid? +// +// If you have an actual monster, use this instead of the overloaded function +// that uses only the monster class to make decisions. +bool monster_habitable_grid(const monsters *m, int actual_grid) +{ + return (monster_habitable_grid(m->type, actual_grid, mons_flies(m))); +} + +// Can monsters of class monster_class live happily on actual_grid? Use flies +// == true to pretend the monster can fly. +// +// [dshaligram] We're trying to harmonise the checks from various places into +// one check, so we no longer care if a water elemental springs into existence +// on dry land, because they're supposed to be able to move onto dry land +// anyway. +bool monster_habitable_grid(int monster_class, int actual_grid, bool flies) +{ + const int preferred_habitat = monster_habitat(monster_class); + return (grid_compatible(preferred_habitat, actual_grid) + // [dshaligram] Flying creatures are all DNGN_FLOOR, so we + // only have to check for the additional valid grids of deep + // water and lava. + || ((flies || mons_class_flies(monster_class)) + && (actual_grid == DNGN_LAVA + || actual_grid == DNGN_DEEP_WATER)) + + // Amphibious critters are happy in the water. + || (mons_class_flag(monster_class, M_AMPHIBIOUS) + && grid_compatible(DNGN_DEEP_WATER, actual_grid)) + + // And water elementals are native to the water but happy on land + // as well. + || (monster_class == MONS_WATER_ELEMENTAL + && grid_compatible(DNGN_FLOOR, actual_grid))); +} + +// Returns true if the monster is floundering in water and susceptible to +// extra damage from water-natives. +bool monster_floundering(const monsters *m) +{ + const int grid = grd[m->x][m->y]; + return ((grid == DNGN_DEEP_WATER || grid == DNGN_SHALLOW_WATER) + // Can't use monster_habitable_grid because that'll return true + // for non-water monsters in shallow water. + && monster_habitat(m->type) != DNGN_DEEP_WATER + && !mons_class_flag(m->type, M_AMPHIBIOUS) + && !mons_flies(m)); +} + +// Returns the grid type that a monster can submerge in, or -1 if the monster +// is incapable of submerging. +int monster_submersible_grid(int monster_class) +{ + switch (monster_class) + { + case MONS_BIG_FISH: + case MONS_GIANT_GOLDFISH: + case MONS_ELECTRICAL_EEL: + case MONS_JELLYFISH: + case MONS_WATER_ELEMENTAL: + case MONS_SWAMP_WORM: + return (DNGN_DEEP_WATER); + + case MONS_LAVA_WORM: + case MONS_LAVA_FISH: + case MONS_LAVA_SNAKE: + case MONS_SALAMANDER: + return (DNGN_LAVA); + + default: + // [dshaligram] Not exactly a safe sentinel with all the int -> char + // -> unsigned char mayhem going around, but it should be sufficient + // for now. + return (-1); + } +} + bool place_monster(int &id, int mon_type, int power, char behaviour, int target, bool summoned, int px, int py, bool allow_bands, int proximity, int extra, int dur) @@ -224,18 +319,10 @@ bool place_monster(int &id, int mon_type, int power, char behaviour, continue; } - // compatible - floor? - if (grid_wanted == DNGN_FLOOR && grd[px][py] < DNGN_FLOOR) + // Is the monster happy where we want to put it? + if (!grid_compatible(grid_wanted, grd[px][py], true)) continue; - // compatible - others (must match, except for deep water monsters - // generated in shallow water) - if ((grid_wanted != DNGN_FLOOR && grd[px][py] != grid_wanted) - && (grid_wanted != DNGN_DEEP_WATER || grd[px][py] != DNGN_SHALLOW_WATER)) - { - continue; - } - // don't generate monsters on top of teleport traps // (how did they get there?) int trap = trap_at_xy(px, py); @@ -366,7 +453,7 @@ static int place_monster_aux( int mon_type, char behaviour, int target, bool first_band_member, int dur ) { int id, i; - char grid_wanted; + unsigned char grid_wanted; int fx=0, fy=0; // final x,y // gotta be able to pick an ID @@ -407,14 +494,7 @@ static int place_monster_aux( int mon_type, char behaviour, int target, if (mgrd[fx][fy] != NON_MONSTER) continue; - // compatible - floor? - if (grid_wanted == DNGN_FLOOR && grd[fx][fy] < DNGN_FLOOR) - continue; - - // compatible - others (must match, except for deep water monsters - // generated in shallow water) - if ((grid_wanted != DNGN_FLOOR && grd[fx][fy] != grid_wanted) - && (grid_wanted != DNGN_DEEP_WATER || grd[fx][fy] != DNGN_SHALLOW_WATER)) + if (!grid_compatible(grid_wanted, grd[fx][fy], true)) continue; // don't generate monsters on top of teleport traps @@ -486,28 +566,10 @@ static int place_monster_aux( int mon_type, char behaviour, int target, menv[id].flags |= MF_BATTY; } - if ((mon_type == MONS_BIG_FISH - || mon_type == MONS_GIANT_GOLDFISH - || mon_type == MONS_ELECTRICAL_EEL - || mon_type == MONS_JELLYFISH - || mon_type == MONS_WATER_ELEMENTAL - || mon_type == MONS_SWAMP_WORM) - && grd[fx][fy] == DNGN_DEEP_WATER - && !one_chance_in(5)) - { + if (monster_submersible_grid(mon_type) == grd[fx][fy] + && !one_chance_in(5)) mons_add_ench( &menv[id], ENCH_SUBMERGED ); - } - - if ((mon_type == MONS_LAVA_WORM - || mon_type == MONS_LAVA_FISH - || mon_type == MONS_LAVA_SNAKE - || mon_type == MONS_SALAMANDER) - && grd[fx][fy] == DNGN_LAVA - && !one_chance_in(5)) - { - mons_add_ench( &menv[id], ENCH_SUBMERGED ); - } - + menv[id].flags |= MF_JUST_SUMMONED; if (mon_type == MONS_DANCING_WEAPON && extra != 1) // ie not from spell @@ -1241,25 +1303,41 @@ int mons_place( int mon_type, char behaviour, int target, bool summoned, return (mid); } // end mons_place() - -int create_monster( int cls, int dur, int beha, int cr_x, int cr_y, - int hitting, int zsec, bool permit_bands ) +coord_def find_newmons_square(int mons_class, int x, int y) { - int summd = -1; FixedVector < char, 2 > empty; - - unsigned char spcw = ((cls == RANDOM_MONSTER) ? DNGN_FLOOR - : monster_habitat( cls )); + coord_def pos = { -1, -1 }; empty[0] = 0; empty[1] = 0; + if (mons_class == WANDERING_MONSTER) + mons_class = RANDOM_MONSTER; + + int spcw = ((mons_class == RANDOM_MONSTER)? DNGN_FLOOR + : monster_habitat( mons_class )); + // Might be better if we chose a space and tried to match the monster // to it in the case of RANDOM_MONSTER, that way if the target square // is surrounded by water of lava this function would work. -- bwr - if (empty_surrounds( cr_x, cr_y, spcw, true, empty )) + if (empty_surrounds( x, y, spcw, true, empty )) + { + pos.x = empty[0]; + pos.y = empty[1]; + } + + return (pos); +} + +int create_monster( int cls, int dur, int beha, int cr_x, int cr_y, + int hitting, int zsec, bool permit_bands ) +{ + int summd = -1; + coord_def pos = find_newmons_square(cls, cr_x, cr_y); + + if (pos.x != -1 && pos.y != -1) { - summd = mons_place( cls, beha, hitting, true, empty[0], empty[1], + summd = mons_place( cls, beha, hitting, true, pos.x, pos.y, you.level_type, 0, zsec, dur, permit_bands ); } @@ -1350,12 +1428,7 @@ bool empty_surrounds(int emx, int emy, unsigned char spc_wanted, if (grd[tx][ty] == spc_wanted) success = true; - // those seeking ground can stand in shallow water or better - if (spc_wanted == DNGN_FLOOR && grd[tx][ty] >= DNGN_SHALLOW_WATER) - success = true; - - // water monsters can be created in shallow as well as deep water - if (spc_wanted == DNGN_DEEP_WATER && grd[tx][ty] == DNGN_SHALLOW_WATER) + if (grid_compatible(spc_wanted, grd[tx][ty])) success = true; if (success) diff --git a/crawl-ref/source/monplace.h b/crawl-ref/source/monplace.h index a3c2aa7a2c..7e3f2c8733 100644 --- a/crawl-ref/source/monplace.h +++ b/crawl-ref/source/monplace.h @@ -87,4 +87,11 @@ monster_type rand_dragon( dragon_class_type type ); void mark_interesting_monst(struct monsters* monster, char behaviour = BEH_SLEEP); +bool grid_compatible(int grid_wanted, int actual_grid, bool generation = false); +bool monster_habitable_grid(int monster_class, int actual_grid, + bool flies = false); +bool monster_habitable_grid(const monsters *m, int actual_grid); +bool monster_floundering(const monsters *m); +int monster_submersible_grid(int monster_class); + #endif // MONPLACE_H diff --git a/crawl-ref/source/monstuff.cc b/crawl-ref/source/monstuff.cc index 92bf884a85..d306f3a745 100644 --- a/crawl-ref/source/monstuff.cc +++ b/crawl-ref/source/monstuff.cc @@ -909,30 +909,8 @@ static bool valid_morph( struct monsters *monster, int new_mclass ) return (false); } - /* Not fair to instakill a monster like this -- - order of evaluation of inner conditional important */ - if (current_tile == DNGN_LAVA || current_tile == DNGN_DEEP_WATER) - { - if (!mons_class_flies(new_mclass) - || monster_habitat(new_mclass) != current_tile) - { - return (false); - } - } - - // not fair to strand a water monster on dry land, either. :) - if (monster_habitat(new_mclass) == DNGN_DEEP_WATER - && current_tile != DNGN_DEEP_WATER - && current_tile != DNGN_SHALLOW_WATER) - { - return (false); - } - - // and putting lava monsters on non-lava sqaures is a no-no, too - if (monster_habitat(new_mclass) == DNGN_LAVA && current_tile != DNGN_LAVA) - return (false); - - return (true); + // Determine if the monster is happy on current tile + return (monster_habitable_grid(new_mclass, current_tile)); } // end valid_morph() // note that power is (as of yet) unused within this function - @@ -958,9 +936,11 @@ bool monster_polymorph( struct monsters *monster, int targetc, int power ) { do { - targetc = random2( NUM_MONSTERS ); + // Pick a monster that's guaranteed happy at this grid + targetc = random_monster_at_grid(monster->x, monster->y); - // valid targets are always base classes + // valid targets are always base classes ([ds] which is unfortunate + // in that well-populated monster classes will dominate polymorphs) targetc = mons_species( targetc ); target_power = mons_power( targetc ); @@ -1119,45 +1099,7 @@ bool random_near_space(int ox, int oy, int &tx, int &ty, bool allow_adjacent, static bool habitat_okay( struct monsters *monster, int targ ) { - bool ret = false; - const int habitat = monster_habitat( monster->type ); - - if (mons_flies( monster )) - { - // flying monsters don't care - ret = true; - } - else if (mons_class_flag( monster->type, M_AMPHIBIOUS ) - && (targ == DNGN_DEEP_WATER || targ == DNGN_SHALLOW_WATER)) - { - // Amphibious creatures are "land" by default in mon-data, - // we allow them to swim here. -- bwr - ret = true; - } - else if (monster->type == MONS_WATER_ELEMENTAL && targ >= DNGN_DEEP_WATER) - { - // water elementals can crawl out over the land - ret = true; - } - else if (habitat == DNGN_FLOOR - && (targ >= DNGN_FLOOR || targ == DNGN_SHALLOW_WATER)) - { - // FLOOR habitat monster going to a non-bad place - ret = true; - } - else if (habitat == DNGN_DEEP_WATER - && (targ == DNGN_DEEP_WATER || targ == DNGN_SHALLOW_WATER)) - { - // Water monster to water - ret = true; - } - else if (habitat == DNGN_LAVA && targ == DNGN_LAVA) - { - // Lava monster to lava - ret = true; - } - - return (ret); + return (monster_habitable_grid(monster, targ)); } // This doesn't really swap places, it just sets the monster's @@ -4387,12 +4329,11 @@ static void monster_move(struct monsters *monster) for (count_y = 0; count_y < 3; count_y++) { good_move[count_x][count_y] = true; + const int targ_x = monster->x + count_x - 1; const int targ_y = monster->y + count_y - 1; - int target_grid = grd[targ_x][targ_y]; - - const int targ_cloud = env.cgrid[ targ_x ][ targ_y ]; - const int curr_cloud = env.cgrid[ monster->x ][ monster->y ]; + // [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) @@ -4401,6 +4342,18 @@ static void monster_move(struct monsters *monster) continue; } + int target_grid = grd[targ_x][targ_y]; + + const int targ_cloud_num = env.cgrid[ targ_x ][ targ_y ]; + const int targ_cloud_type = + targ_cloud_num == EMPTY_CLOUD? CLOUD_NONE + : env.cloud[targ_cloud_num].type; + + const int curr_cloud_num = env.cgrid[ monster->x ][ monster->y ]; + const int curr_cloud_type = + curr_cloud_num == EMPTY_CLOUD? CLOUD_NONE + : env.cloud[curr_cloud_num].type; + if (target_grid == DNGN_DEEP_WATER) deep_water_available = true; @@ -4443,10 +4396,10 @@ static void monster_move(struct monsters *monster) // Water elementals avoid fire and heat if (monster->type == MONS_WATER_ELEMENTAL && (target_grid == DNGN_LAVA - || targ_cloud == CLOUD_FIRE - || targ_cloud == CLOUD_FIRE_MON - || targ_cloud == CLOUD_STEAM - || targ_cloud == CLOUD_STEAM_MON)) + || targ_cloud_type == CLOUD_FIRE + || targ_cloud_type == CLOUD_FIRE_MON + || targ_cloud_type == CLOUD_STEAM + || targ_cloud_type == CLOUD_STEAM_MON)) { good_move[count_x][count_y] = false; continue; @@ -4457,8 +4410,8 @@ static void monster_move(struct monsters *monster) && (target_grid == DNGN_DEEP_WATER || target_grid == DNGN_SHALLOW_WATER || target_grid == DNGN_BLUE_FOUNTAIN - || targ_cloud == CLOUD_COLD - || targ_cloud == CLOUD_COLD_MON)) + || targ_cloud_type == CLOUD_COLD + || targ_cloud_type == CLOUD_COLD_MON)) { good_move[count_x][count_y] = false; continue; @@ -4466,12 +4419,14 @@ static void monster_move(struct monsters *monster) // Submerged water creatures avoid the shallows where // they would be forced to surface. -- bwr + // [dshaligram] Monsters now prefer to head for deep water only if + // they're low on hitpoints. No point in hiding if they want a + // fight. if (habitat == DNGN_DEEP_WATER && (targ_x != you.x_pos || targ_y != you.y_pos) && target_grid != DNGN_DEEP_WATER && grd[monster->x][monster->y] == DNGN_DEEP_WATER - && (mons_has_ench( monster, ENCH_SUBMERGED ) - || monster->hit_points < (monster->max_hit_points * 3) / 4)) + && monster->hit_points < (monster->max_hit_points * 3) / 4) { good_move[count_x][count_y] = false; continue; @@ -4509,15 +4464,15 @@ static void monster_move(struct monsters *monster) } } - if (targ_cloud != EMPTY_CLOUD) + if (targ_cloud_num != EMPTY_CLOUD) { - if (curr_cloud != EMPTY_CLOUD - && env.cloud[targ_cloud].type == env.cloud[curr_cloud].type) + if (curr_cloud_num != EMPTY_CLOUD + && targ_cloud_type == curr_cloud_type) { continue; } - switch (env.cloud[ targ_cloud ].type) + switch (targ_cloud_type) { case CLOUD_FIRE: case CLOUD_FIRE_MON: @@ -4621,14 +4576,16 @@ static void monster_move(struct monsters *monster) } // done door-eating jellies - // water creatures have a preferance for water they can hide in -- bwr + // water creatures have a preference for water they can hide in -- bwr + // [ds] Weakened the powerful attraction to deep water if the monster + // is in good health. if (habitat == DNGN_DEEP_WATER && deep_water_available && grd[monster->x][monster->y] != DNGN_DEEP_WATER && grd[monster->x + mmov_x][monster->y + mmov_y] != DNGN_DEEP_WATER && (monster->x + mmov_x != you.x_pos || monster->y + mmov_y != you.y_pos) - && (coinflip() + && (one_chance_in(3) || monster->hit_points <= (monster->max_hit_points * 3) / 4)) { count = 0; diff --git a/crawl-ref/source/mstuff2.cc b/crawl-ref/source/mstuff2.cc index 87b0269166..e5abcd061a 100644 --- a/crawl-ref/source/mstuff2.cc +++ b/crawl-ref/source/mstuff2.cc @@ -736,8 +736,6 @@ void monster_teleport(struct monsters *monster, bool instan) // pick the monster up mgrd[monster->x][monster->y] = NON_MONSTER; - char ogrid = monster_habitat(monster->type); - int newx, newy; while(true) { @@ -748,12 +746,7 @@ void monster_teleport(struct monsters *monster, bool instan) if (mgrd[newx][newy] != NON_MONSTER) continue; - // monsters going to the same habitat - if (ogrid == grd[newx][newy]) - break; - - // DEEP_WATER monsters can be teleported to SHALLOW_WATER - if (ogrid == DNGN_DEEP_WATER && grd[newx][newy] == DNGN_SHALLOW_WATER) + if (monster_habitable_grid(monster, grd[newx][newy])) break; } diff --git a/crawl-ref/source/spells3.cc b/crawl-ref/source/spells3.cc index 30c4957f9a..157547eb5f 100644 --- a/crawl-ref/source/spells3.cc +++ b/crawl-ref/source/spells3.cc @@ -927,7 +927,7 @@ bool recall(char type_recalled) if (!mons_friendly(monster)) continue; - if (monster_habitat(monster->type) != DNGN_FLOOR) + if (!monster_habitable_grid(monster, DNGN_FLOOR)) continue; if (type_recalled == 1) diff --git a/crawl-ref/source/stuff.cc b/crawl-ref/source/stuff.cc index 69ea936eee..7384bbc902 100644 --- a/crawl-ref/source/stuff.cc +++ b/crawl-ref/source/stuff.cc @@ -15,6 +15,7 @@ #include "AppHdr.h" #include "direct.h" +#include "monplace.h" #include "stuff.h" #include "view.h" @@ -136,7 +137,7 @@ void tag_followers( void ) continue; } - if (monster_habitat(fmenv->type) != DNGN_FLOOR) + if (!monster_habitable_grid(fmenv, DNGN_FLOOR)) continue; if (fmenv->speed_increment < 50) |