git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@2811 c06c8d41-db1a-0410-9941-cceddc491573
PM65H4V4GNPVIJFUQW57DC3VDB7TRUUNXKVZONQKEFZSK3AXX5GQC 3V52MSSK7QX7FWLLUW63DTWCBAJEK674EFZLKP45FLZ5KZKVARHAC SJDOBXECX7F3ZPPVR7FPURE53D47PP2TFIF4SB6XPS456PZV3DQAC NNG27Y5ZQAZX6UD7F7M4F6KEZBEDFXPEEC3LFUSX4ESKT7K6UJQAC K2CS6TCX2NDVL2ASEHGP4J4K4IJ6FP3ANNKTSIWVG43HPYSBX6ZQC T2AYVN57EFJQLFUFLAZDXKDAFDGTDLQIEQWQZNYFWJZBYSTYH4QQC OSGS3PH2L5CBTDVZCZS6OCFQNA4A7RMEXBYJQB7DDZBYYJW7QSSAC FSD7GIK3YLZXWLEH37BU6KV3IUCFGXPQL6IZ7H65YWNRBEKDBX5AC WUWTYSQ2Z7HI637WNO2J55LW6WLPBDF2ILH622T47ICW3AN7OWMQC RPOZZWKG5GLPHVZZ7ZKMKS64ZMV2LDCQSARBJFJ6FZOTOKCQO7FAC AUXVWXWIFSTWFA6VZXN2FMG7FQEKRZVV6MD32VQQ7J2RKCXHAVGAC B62ICMDTN5V7R7RBL4JALFVKEMVOOVLRSJASRNYS6CGFWBEEF5JQC Y3RBMQ7B6PFQRC6TH7PCIHHGA652AN3FTWTTYAOQHBSWOYDJ7XGQC ZCNA74GZB3323BWZO3UTFG2BNYNQRZOKZDKCCMXIUAO5UKOU3NCQC static bool is_trap_safe(const monsters *monster, const trap_struct &trap)
// 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 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 x = monster->x;const int y = monster->y;// test for corridor-like environment (simple hack)if (!(grd[x-1][y] < DNGN_MINMOVE && grd[x+1][y] < DNGN_MINMOVE|| grd[x][y-1] < DNGN_MINMOVE && grd[x][y+1] < DNGN_MINMOVE))
if (just_check)return false; // square is blockedelse
return (monster->hit_points == monster->max_hit_points);
// test for corridor-like environmentconst int x = trap_x - monster->x;const int y = trap_y - monster->y;// The question is whether the monster (m) can easily reach its// presumable destination (x) without stepping on the trap. Traps// in corridors do not allow this. See e.g// #x# ##// #^# or m^x// m ##//// The same problem occurs if paths are blocked by monsters,// hostile terrain or other traps rather than walls.// What we do is check whether the squares with the relative// positions (-1,0)/(+1,0) or (0,-1)/(0,+1) form a "corridor"// (relative to the _current_ monster position rather than the// trap one) form a corridor-like environment. If they don't// the trap square is marked as "unsafe", otherwise the decision// will be made according to later tests (monster hp, trap type, ...)// If a monster still gets stuck in a corridor it will usually be// because it has less than half its maximum hpif ((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))){return (false);}
}// 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){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;dungeon_feature_type target_grid = grd[targ_x][targ_y];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: 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 (monster->type == MONS_BORING_BEETLE&& (target_grid == DNGN_ROCK_WALL|| target_grid == DNGN_CLEAR_ROCK_WALL)){// don't burrow out of boundsif (targ_x <= 7 || targ_x >= (GXM - 8)|| targ_y <= 7 || targ_y >= (GYM - 8)){return false;}// 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)){return false;}else if (!habitat_okay( monster, target_grid )){return false;}if (monster->type == MONS_WANDERING_MUSHROOM&& see_grid(targ_x, targ_y)){return false;}// Water elementals avoid fire and heatif (monster->type == MONS_WATER_ELEMENTAL&& (target_grid == DNGN_LAVA|| targ_cloud_type == CLOUD_FIRE|| targ_cloud_type == CLOUD_STEAM)){return false;}// Fire elementals avoid water and coldif (monster->type == MONS_FIRE_ELEMENTAL&& (target_grid == DNGN_DEEP_WATER|| target_grid == DNGN_SHALLOW_WATER|| target_grid == DNGN_BLUE_FOUNTAIN|| targ_cloud_type == CLOUD_COLD)){return false;}// 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&& monster->hit_points < (monster->max_hit_points * 3) / 4){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// so it's okay as well// smacking another monster is good, if the monsters// are aligned differentlyif (mgrd[targ_x][targ_y] != NON_MONSTER){if (just_check){if (targ_x == monster->x && targ_y == monster->y)return true;return false; // blocks square}const int thismonster = monster_index(monster),targmonster = mgrd[targ_x][targ_y];if (mons_aligned(thismonster, targmonster)&& targmonster != MHITNOT&& targmonster != MHITYOU&& !mons_can_displace(monster, &menv[targmonster])){return false;}}// wandering through a trap is OK if we're pretty healthy,// really stupid, or immune to the trapconst int which_trap = trap_at_xy(targ_x,targ_y);if (which_trap >= 0 && !is_trap_safe(monster, targ_x, targ_y, just_check)){return false;}if (targ_cloud_num != EMPTY_CLOUD){if (curr_cloud_num != EMPTY_CLOUD&& targ_cloud_type == curr_cloud_type){return true;}switch (targ_cloud_type){case CLOUD_FIRE:if (mons_res_fire(monster) > 0)return true;if (monster->hit_points >= 15 + random2avg(46, 5))return true;break;case CLOUD_STINK:if (mons_res_poison(monster) > 0)return true;if (1 + random2(5) < monster->hit_dice)return true;if (monster->hit_points >= random2avg(19, 2))return true;break;case CLOUD_COLD:if (mons_res_cold(monster) > 0)return true;if (monster->hit_points >= 15 + random2avg(46, 5))return true;break;case CLOUD_POISON:if (mons_res_poison(monster) > 0)return true;if (monster->hit_points >= random2avg(37, 4))return true;break;// this isn't harmful, but dumb critters might think so.case CLOUD_GREY_SMOKE:if (mons_intel(monster->type) > I_ANIMAL || coinflip())return true;if (mons_res_fire(monster) > 0)return true;if (monster->hit_points >= random2avg(19, 2))return true;break;default:return true; // harmless clouds}// if we get here, the cloud is potentially harmful.// exceedingly dumb creatures will still wander in.if (mons_intel(monster->type) != I_PLANT)return false;}// if we end up here the monster can safely movereturn true;
// 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;
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;// [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];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;if (monster->type == MONS_BORING_BEETLE&& (target_grid == DNGN_ROCK_WALL|| target_grid == DNGN_CLEAR_ROCK_WALL)){// don't burrow out of boundsif (targ_x <= 7 || targ_x >= (GXM - 8)|| targ_y <= 7 || targ_y >= (GYM - 8)){good_move[count_x][count_y] = false;continue;}// don't burrow at an angle (legacy behaviour)if (count_x != 1 && count_y != 1){good_move[count_x][count_y] = false;continue;}}else if (!monster->can_pass_through(target_grid)|| (no_water && target_grid >= DNGN_DEEP_WATER&& target_grid <= DNGN_WATER_STUCK)){good_move[count_x][count_y] = false;continue;}else if (!habitat_okay( monster, target_grid )){good_move[count_x][count_y] = false;continue;}if (monster->type == MONS_WANDERING_MUSHROOM&& see_grid(targ_x, targ_y)){good_move[count_x][count_y] = false;continue;}// Water elementals avoid fire and heatif (monster->type == MONS_WATER_ELEMENTAL&& (target_grid == DNGN_LAVA|| targ_cloud_type == CLOUD_FIRE|| targ_cloud_type == CLOUD_STEAM)){good_move[count_x][count_y] = false;continue;}// Fire elementals avoid water and coldif (monster->type == MONS_FIRE_ELEMENTAL&& (target_grid == DNGN_DEEP_WATER|| target_grid == DNGN_SHALLOW_WATER|| target_grid == DNGN_BLUE_FOUNTAIN|| targ_cloud_type == CLOUD_COLD)){good_move[count_x][count_y] = false;continue;}// 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&& monster->hit_points < (monster->max_hit_points * 3) / 4){good_move[count_x][count_y] = false;continue;}// smacking the player is always a good move if// we're hostile (even if we're heading somewhere// else)// smacking another monster is good, if the monsters// are aligned differentlyif (mgrd[targ_x][targ_y] != NON_MONSTER){const int thismonster = monster_index(monster),targmonster = mgrd[targ_x][targ_y];if (mons_aligned(thismonster, targmonster)&& targmonster != MHITNOT&& targmonster != MHITYOU&& !mons_can_displace(monster, &menv[targmonster])){good_move[count_x][count_y] = false;continue;}}// wandering through a trap is OK if we're pretty healthy,// really stupid, or immune to the trapconst int which_trap = trap_at_xy(targ_x,targ_y);if (which_trap >= 0 &&!is_trap_safe(monster, env.trap[which_trap])){good_move[count_x][count_y] = false;continue;}if (targ_cloud_num != EMPTY_CLOUD){if (curr_cloud_num != EMPTY_CLOUD&& targ_cloud_type == curr_cloud_type){continue;}switch (targ_cloud_type){case CLOUD_FIRE:if (mons_res_fire(monster) > 0)continue;if (monster->hit_points >= 15 + random2avg(46, 5))continue;break;case CLOUD_STINK:if (mons_res_poison(monster) > 0)continue;if (1 + random2(5) < monster->hit_dice)continue;if (monster->hit_points >= random2avg(19, 2))continue;break;case CLOUD_COLD:if (mons_res_cold(monster) > 0)continue;if (monster->hit_points >= 15 + random2avg(46, 5))continue;break;case CLOUD_POISON:if (mons_res_poison(monster) > 0)continue;if (monster->hit_points >= random2avg(37, 4))continue;break;// this isn't harmful, but dumb critters might think so.case CLOUD_GREY_SMOKE:if (mons_intel(monster->type) > I_ANIMAL || coinflip())continue;
const int targ_x = monster->x + count_x - 1;const int targ_y = monster->y + count_y - 1;
if (monster->hit_points >= random2avg(19, 2))continue;break;
// 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];
// if we get here, the cloud is potentially harmful.// exceedingly dumb creatures will still wander in.if (mons_intel(monster->type) != I_PLANT)good_move[count_x][count_y] = false;}
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);