diff options
Diffstat (limited to 'crawl-ref/source/abyss.cc')
-rw-r--r-- | crawl-ref/source/abyss.cc | 161 |
1 files changed, 149 insertions, 12 deletions
diff --git a/crawl-ref/source/abyss.cc b/crawl-ref/source/abyss.cc index 06fa718286..a3ca3b9a77 100644 --- a/crawl-ref/source/abyss.cc +++ b/crawl-ref/source/abyss.cc @@ -33,6 +33,7 @@ #include "terrain.h" #include "traps.h" #include "view.h" +#include "xom.h" static bool place_feature_near( const coord_def ¢re, int radius, @@ -69,6 +70,10 @@ void generate_abyss(void) int i, j; // loop variables int temp_rand; // probability determination {dlb} +#if DEBUG_ABYSS + mpr("generate_abyss().", MSGCH_DIAGNOSTICS); +#endif + for (i = 5; i < (GXM - 5); i++) { for (j = 5; j < (GYM - 5); j++) @@ -91,6 +96,10 @@ void generate_abyss(void) static void generate_area(int gx1, int gy1, int gx2, int gy2) { +#if DEBUG_ABYSS + mpr("generate_area().", MSGCH_DIAGNOSTICS); +#endif + int items_placed = 0; const int thickness = random2(70) + 30; int thing_created; @@ -156,6 +165,9 @@ static void generate_area(int gx1, int gy1, int gx2, int gy2) { thing_created = items(1, OBJ_MISCELLANY, MISC_RUNE_OF_ZOT, true, 51, 51); +#if DEBUG_ABYSS + mpr("Placing an Abyssal rune.", MSGCH_DIAGNOSTICS); +#endif } else { @@ -172,6 +184,9 @@ static void generate_area(int gx1, int gy1, int gx2, int gy2) } } + int exits_wanted = 0; + int altars_wanted = 0; + for (int i = gx1; i <= gx2; i++) { for (int j = gy1; j <= gy2; j++) @@ -180,9 +195,23 @@ static void generate_area(int gx1, int gy1, int gx2, int gy2) grd[i][j] = replaced[random2(5)]; if (one_chance_in(7500)) // place an exit + exits_wanted++; + + // Don't place exit under items + if (exits_wanted > 0 && igrd[i][j] == NON_ITEM) + { grd[i][j] = DNGN_EXIT_ABYSS; + exits_wanted--; +#if DEBUG_ABYSS + mpr("Placing Abyss exit.", MSGCH_DIAGNOSTICS); +#endif + } if (one_chance_in(10000)) // place an altar + altars_wanted++; + + // Don't place altars under items. + if (altars_wanted > 0 && igrd[i][j] == NON_ITEM) { do { @@ -197,11 +226,109 @@ static void generate_area(int gx1, int gy1, int gx2, int gy2) // Lugonu has a flat 50% chance of corrupting the altar if ( coinflip() ) grd[i][j] = DNGN_ALTAR_LUGONU; + + altars_wanted--; +#if DEBUG_ABYSS + mpr("Placing altar.", MSGCH_DIAGNOSTICS); +#endif } } } } +static int abyss_exit_nearness() +{ + int nearness = INFINITE_DISTANCE; + + for (int x = you.x_pos - LOS_RADIUS; x < you.x_pos + LOS_RADIUS; x++) + for (int y = you.y_pos - LOS_RADIUS; y < you.y_pos + LOS_RADIUS; y++) + { + if (!in_bounds(x, y)) + continue; + + // HACK: Why doesn't is_terrain_known() work here? + if (grd[x][y] == DNGN_EXIT_ABYSS + && get_screen_glyph(x, y) != ' ') + { + nearness = MIN(nearness, + grid_distance(you.x_pos, you.y_pos, + x, y)); + } + } + + return (nearness); +} + +static int abyss_rune_nearness() +{ + int nearness = INFINITE_DISTANCE; + + for (int x = you.x_pos - LOS_RADIUS; x < you.x_pos + LOS_RADIUS; x++) + for (int y = you.y_pos - LOS_RADIUS; y < you.y_pos + LOS_RADIUS; y++) + { + if (!in_bounds(x, y)) + continue; + + // HACK: Why doesn't is_terrain_known() work here? + if (get_screen_glyph(x, y) != ' ') + { + int i = igrd[x][y]; + + while (i != NON_ITEM) + { + item_def& item(mitm[i]); + if (is_rune(item) && item.plus == RUNE_ABYSSAL) + nearness = MIN(nearness, + grid_distance(you.x_pos, you.y_pos, + x, y)); + i = item.link; + } + } + } + + return (nearness); +} + +static int exit_was_near; +static int rune_was_near; + +static void xom_check_nearness_setup() +{ + exit_was_near = abyss_exit_nearness(); + rune_was_near = abyss_rune_nearness(); +} + +// If the player was almost to the exit when it disppeared, Xom is +// extremely amused. He's also extremely amused if the player winds +// up right next to an exit when there wasn't one there before. The +// same applies to Abyssal runes. +static void xom_check_nearness() +{ + // Update known terrain + viewwindow(true, false); + + int exit_is_near = abyss_exit_nearness(); + int rune_is_near = abyss_rune_nearness(); + + if ((exit_was_near < INFINITE_DISTANCE + && exit_is_near == INFINITE_DISTANCE) + || (rune_was_near < INFINITE_DISTANCE + && rune_is_near == INFINITE_DISTANCE + && you.attribute[ATTR_ABYSSAL_RUNES] == 0)) + { + xom_is_stimulated(255, "Xom snickers loudly.", true); + } + + if ((rune_was_near == INFINITE_DISTANCE + && rune_is_near < INFINITE_DISTANCE + && you.attribute[ATTR_ABYSSAL_RUNES] == 0) + || (exit_was_near == INFINITE_DISTANCE && + exit_is_near < INFINITE_DISTANCE)) + { + xom_is_stimulated(255); + } +} + static void abyss_lose_monster(monsters &mons) { if (mons.needs_transit()) @@ -213,6 +340,12 @@ static void abyss_lose_monster(monsters &mons) void area_shift(void) /*******************/ { +#if DEBUG_ABYSS + mpr("area_shift().", MSGCH_DIAGNOSTICS); +#endif + + xom_check_nearness_setup(); + for (unsigned int i = 0; i < MAX_MONSTERS; i++) { monsters &m = menv[i]; @@ -237,7 +370,7 @@ void area_shift(void) grd[i][j] = DNGN_UNSEEN; // nuke items - destroy_item_stack( i, j ); + lose_item_stack( i, j ); if (mgrd[i][j] != NON_MONSTER) abyss_lose_monster( menv[ mgrd[i][j] ] ); @@ -296,6 +429,8 @@ void area_shift(void) generate_area(5, 5, (GXM - 5), (GYM - 5)); + xom_check_nearness(); + for (unsigned int mcount = 0; mcount < 15; mcount++) { mons_place( RANDOM_MONSTER, BEH_HOSTILE, MHITNOT, false, 1, 1, @@ -319,6 +454,8 @@ void save_abyss_uniques() void abyss_teleport( bool new_area ) /**********************************/ { + xom_check_nearness_setup(); + int x, y, i, j, k; if (!new_area) @@ -340,11 +477,19 @@ void abyss_teleport( bool new_area ) if (i < 100) { +#if DEBUG_ABYSS + mpr("Non-new area Abyss teleport.", MSGCH_DIAGNOSTICS); +#endif you.moveto(x, y); + xom_check_nearness(); return; } } +#if DEBUG_ABYSS + mpr("New area Abyss teleport.", MSGCH_DIAGNOSTICS); +#endif + // teleport to a new area of the abyss: init_pandemonium(); // get new monsters @@ -361,17 +506,7 @@ void abyss_teleport( bool new_area ) { if (is_valid_item( mitm[k] )) { - if (mitm[k].base_type == OBJ_ORBS) - { - set_unique_item_status( OBJ_ORBS, mitm[k].sub_type, - UNIQ_LOST_IN_ABYSS ); - } - else if (is_fixed_artefact( mitm[k] )) - { - set_unique_item_status( OBJ_WEAPONS, mitm[k].special, - UNIQ_LOST_IN_ABYSS ); - } - + item_was_lost( mitm[k] ); destroy_item( k ); } } @@ -396,6 +531,8 @@ void abyss_teleport( bool new_area ) generate_area( 10, 10, (GXM - 10), (GYM - 10) ); + xom_check_nearness(); + grd[you.x_pos][you.y_pos] = DNGN_FLOOR; if ( one_chance_in(5) ) place_feature_near( you.pos(), LOS_RADIUS, |