point on the target level that is connected to at least one stone stair.
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@1893 c06c8d41-db1a-0410-9941-cceddc491573
2WRXQTGYDBLV46WRNVIUKGNA5QS563XZNNW3N2L6PVOCHIP2YGHQC FMKQARDH6JZ7DUTPPQ6I3LLNQAFGXS36XJCSROUJMEIYQYJDVITQC F5PJ6H7W2SS5LTUJ7N6JW4SSWTGTDJRXX7L4JBM2NSD2QC26FFLQC 2YSMM7QMFZOPD5NXAD2OAMDJEY5LOZO4NCYBC7UCQVANKINJRNBAC SDLKLUNFGVKDS55DDJZCBAVIB7NL3RRYPTACAY65SCUQKV6APFSAC RPOZZWKG5GLPHVZZ7ZKMKS64ZMV2LDCQSARBJFJ6FZOTOKCQO7FAC OYTCBRC7LE44EUVRZVYTOOVKQWJ6P6YE3FXTOGUTNKEMLNWPHKSQC RC6L3CIBLJEH4GWRFD7UQNGI6PZT74FRUVOYHSAN2XCC74NZUASQC ILOED4VB4I6VPAUTR75ZWX6MXDYXB5DO2EDK2UH67O3HNKWV23RQC MSQI3TH6T62JAXQGLL52QZCWAMC372TGB6ZNNRDGUGMJKBNNV2VAC K2CS6TCX2NDVL2ASEHGP4J4K4IJ6FP3ANNKTSIWVG43HPYSBX6ZQC SW3RLYFNRT3IJBK6LYKHKP2J2YDU7SXQWAJZX7U6S7ICYW43OMNQC W5VEC2PBIM5DMU5233HOWAZUEPTGWJRZZIA3H35YYQQW6BTP6XUAC EOMCPVNQLX3IMLC46EAO67DPBH5KEG2FQTPBLGU62HIRWA3UQ7XQC C22455VGUQOSUX2OORA32LROFQ7NNYDMD2ZDTTUZSAQLXK4AD6QAC IVVTHLTTLOP5TSULXJWUSSXHOKYWVU3OWKYVK45A7RIB6V34MYQAC // If the player has overridden deep water already, we'll respect that.set_pass_feature(DNGN_DEEP_WATER, water);
// If the player has overridden deep water already, we'll respect that.set_pass_feature(DNGN_DEEP_WATER, water);
// Permanently levitating players can cross most hostile terrain.signed char trav = player_is_permalevitating()?TRAVERSABLE : IMPASSABLE;
// Permanently levitating players can cross most hostile terrain.signed char trav = player_is_permalevitating()?TRAVERSABLE : IMPASSABLE;
if (water != TRAVERSABLE)set_pass_feature(DNGN_DEEP_WATER, trav);set_pass_feature(DNGN_LAVA, trav);set_pass_feature(DNGN_TRAP_MECHANICAL, trav);
if (water != TRAVERSABLE)set_pass_feature(DNGN_DEEP_WATER, trav);set_pass_feature(DNGN_LAVA, trav);set_pass_feature(DNGN_TRAP_MECHANICAL, trav);}else{set_pass_feature(DNGN_DEEP_WATER, IMPASSABLE);set_pass_feature(DNGN_LAVA, IMPASSABLE);set_pass_feature(DNGN_TRAP_MECHANICAL, IMPASSABLE);}
}bool grid_is_stone_stair(dungeon_feature_type grid){switch (grid){case DNGN_STONE_STAIRS_UP_I:case DNGN_STONE_STAIRS_UP_II:case DNGN_STONE_STAIRS_UP_III:case DNGN_STONE_STAIRS_DOWN_I:case DNGN_STONE_STAIRS_DOWN_II:case DNGN_STONE_STAIRS_DOWN_III:return (true);default:return (false);}
static coord_def find_nearby_stair(int stair_to_find, bool find_closest){// scan around the player's position firstint basex = you.x_pos;int basey = you.y_pos;// check for illegal starting pointif ( !in_bounds(basex, basey) ){basex = 0;basey = 0;}coord_def result;int found = 0;int best_dist = 1 + GXM*GXM + GYM*GYM;// XXX These passes should be rewritten to use an iterator of STL// algorithm of some kind.// First pass: look for an exact matchfor (int xcode = 0; xcode < GXM; ++xcode ){const int xsign = ((xcode % 2) ? 1 : -1);const int xdiff = xsign * (xcode + 1)/2;const int xpos = (basex + xdiff + GXM) % GXM;for (int ycode = 0; ycode < GYM; ++ycode){const int ysign = ((ycode % 2) ? 1 : -1);const int ydiff = ysign * (ycode + 1)/2;const int ypos = (basey + ydiff + GYM) % GYM;// note that due to the wrapping above, we can't just use// xdiff*xdiff + ydiff*ydiffconst int dist = (xpos-basex)*(xpos-basex) +(ypos-basey)*(ypos-basey);if (grd[xpos][ypos] == stair_to_find){found++;if (find_closest){if (dist < best_dist){best_dist = dist;result.x = xpos;result.y = ypos;}}else if (one_chance_in( found )){result.x = xpos;result.y = ypos;}}}}if ( found )return result;best_dist = 1 + GXM*GXM + GYM*GYM;// Second pass: find a staircase in the proper directionfor (int xcode = 0; xcode < GXM; ++xcode ){const int xsign = ((xcode % 2) ? 1 : -1);const int xdiff = xsign * (xcode + 1)/2;const int xpos = (basex + xdiff + GXM) % GXM;for (int ycode = 0; ycode < GYM; ++ycode){const int ysign = ((ycode % 2) ? 1 : -1);const int ydiff = ysign * (ycode + 1)/2;const int ypos = (basey + ydiff + GYM) % GYM;bool good_stair;const int looking_at = grd[xpos][ypos];
if (stair_to_find <= DNGN_ROCK_STAIRS_DOWN )good_stair =(looking_at >= DNGN_STONE_STAIRS_DOWN_I) &&(looking_at <= DNGN_ROCK_STAIRS_DOWN);elsegood_stair =(looking_at >= DNGN_STONE_STAIRS_UP_I) &&(looking_at <= DNGN_ROCK_STAIRS_UP);const int dist = (xpos-basex)*(xpos-basex) +(ypos-basey)*(ypos-basey);if ( good_stair ){found++;if (find_closest && dist < best_dist){best_dist = dist;result.x = xpos;result.y = ypos;}else if (one_chance_in( found )){result.x = xpos;result.y = ypos;}}}}if ( found )return result;// Third pass: look for any clear terrain (shouldn't happen).// We abandon the idea of looking nearby now.for (int xpos = 0; xpos < GXM; xpos++){for (int ypos = 0; ypos < GYM; ypos++){if (grd[xpos][ypos] >= DNGN_FLOOR){found++;if (one_chance_in( found )){result.x = xpos;result.y = ypos;}}}}ASSERT( found );return result;}
static void fixup_pandemonium_stairs(){for (int i = 0; i < GXM; i++){for (int j = 0; j < GYM; j++){if (grd[i][j] >= DNGN_STONE_STAIRS_UP_I&& grd[i][j] <= DNGN_ROCK_STAIRS_UP){if (one_chance_in( you.mutation[MUT_PANDEMONIUM] ? 5 : 50 ))grd[i][j] = DNGN_EXIT_PANDEMONIUM;elsegrd[i][j] = DNGN_FLOOR;}if (grd[i][j] >= DNGN_ENTER_LABYRINTH&& grd[i][j] <= DNGN_ROCK_STAIRS_DOWN){grd[i][j] = DNGN_TRANSIT_PANDEMONIUM;}}}}
return (grid == DNGN_ROCK_WALL|| (grid_is_solid(grid) && grid != DNGN_CLOSED_DOOR&& grid != DNGN_SECRET_DOOR));
return !(grid == DNGN_ROCK_WALL|| (grid_is_solid(grid) && grid != DNGN_CLOSED_DOOR&& grid != DNGN_SECRET_DOOR));}static inline void dgn_point_record_stub(const coord_def &) { }template <class point_record>static void dgn_fill_zone(const coord_def &c, int zone, point_record &prec,bool (*passable)(dungeon_feature_type) = dgn_grid_is_passable){// No bounds checks, assuming the level has at least one layer of// rock border.travel_point_distance[c.x][c.y] = zone;for (int yi = -1; yi <= 1; ++yi){for (int xi = -1; xi <= 1; ++xi){if (!xi && !yi)continue;const coord_def cp(c.x + xi, c.y + yi);if (travel_point_distance[cp.x][cp.y]|| dgn_map_mask(cp)|| !passable(grd(cp))){continue;}prec(cp);dgn_fill_zone(cp, zone, prec);}}
struct nearest_point{coord_def target;coord_def nearest;int distance;nearest_point(const coord_def &t) : target(t), nearest(), distance(-1){}void operator () (const coord_def &c){if (grd(c) == DNGN_FLOOR){const int ndist = (c - target).abs();if (distance == -1 || ndist < distance){distance = ndist;nearest = c;}}}};
// Fill travel_point_distance out from all stone stairs on the level.static coord_def dgn_find_closest_to_stone_stairs(){memset(travel_point_distance, 0, sizeof(travel_distance_grid_t));init_travel_terrain_check(false);nearest_point np(you.pos());for (int y = 0; y < GYM; ++y)for (int x = 0; x < GXM; ++x)if (!travel_point_distance[x][y] && grid_is_stone_stair(grd[x][y]))dgn_fill_zone(coord_def(x, y), 1, np, is_traversable);return (np.nearest);}
coord_def dgn_find_nearby_stair(int stair_to_find, bool find_closest){if (stair_to_find == DNGN_ROCK_STAIRS_UP|| stair_to_find == DNGN_ROCK_STAIRS_DOWN){const coord_def pos(dgn_find_closest_to_stone_stairs());if (in_bounds(pos))return (pos);}// scan around the player's position firstint basex = you.x_pos;int basey = you.y_pos;// check for illegal starting pointif ( !in_bounds(basex, basey) ){basex = 0;basey = 0;}coord_def result;int found = 0;int best_dist = 1 + GXM*GXM + GYM*GYM;// XXX These passes should be rewritten to use an iterator of STL// algorithm of some kind.// First pass: look for an exact matchfor (int xcode = 0; xcode < GXM; ++xcode ){const int xsign = ((xcode % 2) ? 1 : -1);const int xdiff = xsign * (xcode + 1)/2;const int xpos = (basex + xdiff + GXM) % GXM;for (int ycode = 0; ycode < GYM; ++ycode){const int ysign = ((ycode % 2) ? 1 : -1);const int ydiff = ysign * (ycode + 1)/2;const int ypos = (basey + ydiff + GYM) % GYM;// note that due to the wrapping above, we can't just use// xdiff*xdiff + ydiff*ydiffconst int dist = (xpos-basex)*(xpos-basex) +(ypos-basey)*(ypos-basey);if (grd[xpos][ypos] == stair_to_find){found++;if (find_closest){if (dist < best_dist){best_dist = dist;result.x = xpos;result.y = ypos;}}else if (one_chance_in( found )){result.x = xpos;result.y = ypos;}}}}if ( found )return result;best_dist = 1 + GXM*GXM + GYM*GYM;// Second pass: find a staircase in the proper directionfor (int xcode = 0; xcode < GXM; ++xcode ){const int xsign = ((xcode % 2) ? 1 : -1);const int xdiff = xsign * (xcode + 1)/2;const int xpos = (basex + xdiff + GXM) % GXM;for (int ycode = 0; ycode < GYM; ++ycode){const int ysign = ((ycode % 2) ? 1 : -1);const int ydiff = ysign * (ycode + 1)/2;const int ypos = (basey + ydiff + GYM) % GYM;bool good_stair;const int looking_at = grd[xpos][ypos];if (stair_to_find <= DNGN_ROCK_STAIRS_DOWN )good_stair =(looking_at >= DNGN_STONE_STAIRS_DOWN_I) &&(looking_at <= DNGN_ROCK_STAIRS_DOWN);elsegood_stair =(looking_at >= DNGN_STONE_STAIRS_UP_I) &&(looking_at <= DNGN_ROCK_STAIRS_UP);const int dist = (xpos-basex)*(xpos-basex) +(ypos-basey)*(ypos-basey);if ( good_stair ){found++;if (find_closest && dist < best_dist){best_dist = dist;result.x = xpos;result.y = ypos;}else if (one_chance_in( found )){result.x = xpos;result.y = ypos;}}}}if ( found )return result;// Third pass: look for any clear terrain and abandon the idea of// looking nearby now. This is used when taking transit Pandemonium gates,// or landing in Labyrinths. Never land the PC inside a Pan or Lab vault.// We can't check vaults for other levels because vault information is// not saved, and the player can re-enter other levels.for (int xpos = 0; xpos < GXM; xpos++){for (int ypos = 0; ypos < GYM; ypos++){if (grd[xpos][ypos] >= DNGN_FLOOR&& (you.level_type == LEVEL_DUNGEON|| unforbidden(coord_def(xpos, ypos), MMT_VAULT))){found++;if (one_chance_in( found )){result.x = xpos;result.y = ypos;}}}}ASSERT( found );return result;}