From ffe366a5e2fcd7bdbae1e0fb7848ae3799b4a6b4 Mon Sep 17 00:00:00 2001 From: j-p-e-g Date: Sat, 4 Oct 2008 18:18:15 +0000 Subject: Fix 2063470: =f inscription preventing wielding of stones Improve exclusion los behaviour. * now takes into account what the player knows of the map * don't autoremove exclusions if you don't know the monster died * the los gets updated as the player explores the area For some reason this doesn't work when you dig into an excluded area. FR 2006559: Sort monsters in description menu (?\) using the same measure as the monster list does. git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@7132 c06c8d41-db1a-0410-9941-cceddc491573 --- crawl-ref/source/beam.cc | 7 ++++ crawl-ref/source/command.cc | 15 +++------ crawl-ref/source/dat/lua/wield.lua | 6 ++-- crawl-ref/source/debug.cc | 4 +-- crawl-ref/source/effects.cc | 4 +-- crawl-ref/source/mon-data.h | 2 +- crawl-ref/source/mon-util.cc | 9 +++++ crawl-ref/source/mon-util.h | 1 + crawl-ref/source/monstuff.cc | 21 ++++++------ crawl-ref/source/monstuff.h | 2 +- crawl-ref/source/output.cc | 7 ++-- crawl-ref/source/terrain.cc | 7 +++- crawl-ref/source/terrain.h | 1 + crawl-ref/source/travel.cc | 51 +++++++++++++++++++++++++++-- crawl-ref/source/travel.h | 10 +++--- crawl-ref/source/view.cc | 67 +++++++++++++++++++++++++------------- crawl-ref/source/view.h | 3 +- 17 files changed, 151 insertions(+), 66 deletions(-) diff --git a/crawl-ref/source/beam.cc b/crawl-ref/source/beam.cc index 8968e408e6..0d577edc56 100644 --- a/crawl-ref/source/beam.cc +++ b/crawl-ref/source/beam.cc @@ -3049,6 +3049,11 @@ static int _affect_wall(bolt &beam, const coord_def& p) if (grd(p) == DNGN_ROCK_WALL || grd(p) == DNGN_CLEAR_ROCK_WALL) { grd(p) = DNGN_FLOOR; + // Mark terrain as changed so travel excludes can be updated + // as necessary. + // XXX: This doesn't work for some reason: after digging + // the wrong grids are marked excluded. + set_terrain_changed(p); // Blood does not transfer onto floor. if (is_bloodcovered(p)) @@ -3082,8 +3087,10 @@ static int _affect_wall(bolt &beam, const coord_def& p) if (beam.flavour != BEAM_HELLFIRE) { if (see_grid(p)) + { _beam_mpr(MSGCH_PLAIN, "The wax appears to soften slightly."); + } else if (player_can_smell()) _beam_mpr(MSGCH_PLAIN, "You smell warm wax."); } diff --git a/crawl-ref/source/command.cc b/crawl-ref/source/command.cc index 7dd58662ba..35b03c0ade 100644 --- a/crawl-ref/source/command.cc +++ b/crawl-ref/source/command.cc @@ -862,14 +862,8 @@ static bool _compare_mon_toughness(MenuEntry *entry_a, MenuEntry* entry_b) if (*a == *b) return (false); - int a_toughness = mons_global_level(*a); - int b_toughness = mons_global_level(*b); - - if (a_toughness == b_toughness) - { - a_toughness = mons_type_hit_dice(*a); - b_toughness = mons_type_hit_dice(*b); - } + int a_toughness = mons_difficulty(*a); + int b_toughness = mons_difficulty(*b); if (a_toughness == b_toughness) { @@ -877,8 +871,7 @@ static bool _compare_mon_toughness(MenuEntry *entry_a, MenuEntry* entry_b) std::string b_name = mons_type_name(*b, DESC_PLAIN); return (lowercase(a_name) < lowercase(b_name)); } - - return (a_toughness < b_toughness); + return (a_toughness > b_toughness); } class DescMenu : public Menu @@ -2195,7 +2188,7 @@ int list_wizard_commands(bool do_redraw_screen) cols.add_formatted(0, "Player stats\n" "A : set all skills to level\n" - "g : add a skill\n" + "g : exercise a skill\n" "r : change character's species\n" "s : gain 20000 skill points\n" "S : set skill to level\n" diff --git a/crawl-ref/source/dat/lua/wield.lua b/crawl-ref/source/dat/lua/wield.lua index e4fe9951e3..b068b543de 100644 --- a/crawl-ref/source/dat/lua/wield.lua +++ b/crawl-ref/source/dat/lua/wield.lua @@ -32,13 +32,15 @@ function ch_item_wieldable(it) end if spells["Sandblast"] - and string.find( item.name(it, "a"), " stones?$" ) + and item.class(it, true) == "missile" + and string.find( item.name(it, "a"), " stones?" ) then return true end if spells["Sticks to Snakes"] - and string.find( item.name(it, "a"), " arrows?$" ) + and item.class(it, true) == "missile" + and string.find( item.name(it, "a"), " arrows?" ) then return true end diff --git a/crawl-ref/source/debug.cc b/crawl-ref/source/debug.cc index 950c21ef1e..e38d6233d9 100644 --- a/crawl-ref/source/debug.cc +++ b/crawl-ref/source/debug.cc @@ -3824,7 +3824,7 @@ void wizard_dismiss_all_monsters(bool force_all) monsters *monster = &menv[mon]; if (monster->alive()) - monster_die(monster, KILL_DISMISSED, NON_MONSTER); + monster_die(monster, KILL_DISMISSED, NON_MONSTER, false, true); } return; } @@ -3836,7 +3836,7 @@ void wizard_dismiss_all_monsters(bool force_all) monsters *monster = &menv[mon]; if (monster->alive() && tpat.matches(monster->name(DESC_PLAIN))) - monster_die(monster, KILL_DISMISSED, NON_MONSTER); + monster_die(monster, KILL_DISMISSED, NON_MONSTER, false, true); } } diff --git a/crawl-ref/source/effects.cc b/crawl-ref/source/effects.cc index a785592378..07538c1c81 100644 --- a/crawl-ref/source/effects.cc +++ b/crawl-ref/source/effects.cc @@ -2082,12 +2082,10 @@ bool vitrify_area(int radius) { grd(*ri) = static_cast(grid + clear_plus); + set_terrain_changed(ri->x, ri->y); something_happened = true; } } - if (something_happened) - init_exclusion_los(); - return (something_happened); } diff --git a/crawl-ref/source/mon-data.h b/crawl-ref/source/mon-data.h index 53751a0fff..3b75da5afc 100644 --- a/crawl-ref/source/mon-data.h +++ b/crawl-ref/source/mon-data.h @@ -1910,7 +1910,7 @@ static monsterentry mondata[] = { { MONS_SKELETAL_DRAGON, 'D', LIGHTGREY, "skeletal dragon", - M_SENSE_INVIS | M_EVIL, + M_SENSE_INVIS | M_EVIL | M_FLIES, MR_RES_POISON | MR_RES_FIRE | MR_RES_COLD | MR_RES_ELEC, 0, 12, MONS_DRAGON, MONS_SKELETAL_DRAGON, MH_UNDEAD, -4, { {AT_BITE, AF_PLAIN, 30}, {AT_CLAW, AF_PLAIN, 20}, diff --git a/crawl-ref/source/mon-util.cc b/crawl-ref/source/mon-util.cc index 123d8a5511..f4fe83941e 100644 --- a/crawl-ref/source/mon-util.cc +++ b/crawl-ref/source/mon-util.cc @@ -1323,6 +1323,15 @@ int mons_type_hit_dice( int type ) return (0); } +int mons_difficulty(int mtype) +{ + // Currently, difficulty is defined as "average hp". Leaks too much info? + const monsterentry* me = get_monster_data(mtype); + + // [ds] XXX: Use monster experience value as a better indicator of diff.? + return (me->hpdice[0] * (me->hpdice[1] + (me->hpdice[2]/2)) + + me->hpdice[3]); +} int exper_value( const struct monsters *monster ) { diff --git a/crawl-ref/source/mon-util.h b/crawl-ref/source/mon-util.h index f0ccd48226..07c83658e5 100644 --- a/crawl-ref/source/mon-util.h +++ b/crawl-ref/source/mon-util.h @@ -477,6 +477,7 @@ bool mons_is_unique(int mclass); * called from: describe - fight * *********************************************************************** */ // int exper_value(int mclass, int mHD, int maxhp); +int mons_difficulty(int mtype); int exper_value( const monsters *monster ); diff --git a/crawl-ref/source/monstuff.cc b/crawl-ref/source/monstuff.cc index caa77f743d..53c2c9dd5c 100644 --- a/crawl-ref/source/monstuff.cc +++ b/crawl-ref/source/monstuff.cc @@ -762,7 +762,7 @@ static void _mummy_curse(monsters* monster, killer_type killer, int index) } void monster_die(monsters *monster, killer_type killer, - int killer_index, bool silent) + int killer_index, bool silent, bool wizard) { if (invalid_monster(monster)) return; @@ -775,8 +775,9 @@ void monster_die(monsters *monster, killer_type killer, // Update list of monsters beholding player. update_beholders(monster, true); - // Clear auto exclusion now the monster is killed. - remove_auto_exclude(monster); + // Clear auto exclusion now the monster is killed -- if we know about it. + if (mons_near(monster) || wizard) + remove_auto_exclude(monster); const int monster_killed = monster_index(monster); const bool hard_reset = testbits(monster->flags, MF_HARD_RESET); @@ -6398,8 +6399,8 @@ void mons_check_pool(monsters *mons, killer_type killer, int killnum) if (grid == DNGN_LAVA && mons_res_fire(mons) >= 2) grid = DNGN_DEEP_WATER; - // Even fire resistant monsters perish in lava, but undead can survive - // deep water. + // Even fire resistant monsters perish in lava, but inanimate monsters + // can survive deep water. if (grid == DNGN_LAVA || mons->can_drown()) { if (message) @@ -7592,17 +7593,17 @@ static spell_type _map_wand_to_mspell(int wand_type) void seen_monster(monsters *monster) { + // If the monster is in the auto_exclude list, automatically + // set an exclusion. + if (need_auto_exclude(monster) && !is_exclude_root(monster->pos())) + toggle_exclude(monster->pos()); + if (monster->flags & MF_SEEN) return; // First time we've seen this particular monster. monster->flags |= MF_SEEN; - // If the monster is in the auto_exclude list, automatically - // set an exclusion. - if (need_auto_exclude(monster) && !is_exclude_root(monster->pos())) - toggle_exclude(monster->pos()); - if (!mons_is_mimic(monster->type) && MONST_INTERESTING(monster) && monster->type != MONS_PANDEMONIUM_DEMON diff --git a/crawl-ref/source/monstuff.h b/crawl-ref/source/monstuff.h index 21b58c7126..cce7636b59 100644 --- a/crawl-ref/source/monstuff.h +++ b/crawl-ref/source/monstuff.h @@ -85,7 +85,7 @@ bool monster_polymorph(monsters *monster, monster_type targetc, * spells1 - spells2 - spells3 - spells4 * *********************************************************************** */ void monster_die(monsters *monster, killer_type killer, - int killer_index, bool silent = false); + int killer_index, bool silent = false, bool wizard = false); void mons_check_pool(monsters *monster, killer_type killer = KILL_NONE, int killnum = -1); diff --git a/crawl-ref/source/output.cc b/crawl-ref/source/output.cc index 242f64f329..27c83fefda 100644 --- a/crawl-ref/source/output.cc +++ b/crawl-ref/source/output.cc @@ -1132,11 +1132,8 @@ monster_pane_info::monster_pane_info(const monsters *m) if (mtype == MONS_RAKSHASA_FAKE) mtype = MONS_RAKSHASA; - // Currently, difficulty is defined as "average hp". Leaks too much info? - const monsterentry* me = get_monster_data(mtype); - // [ds] XXX: Use monster experience value as a better indicator of diff.? - m_difficulty = me->hpdice[0] * (me->hpdice[1] + (me->hpdice[2]/2)) - + me->hpdice[3]; + // Currently, difficulty is defined as "average hp". + m_difficulty = mons_difficulty(mtype); // [ds] XXX: Kill the magic numbers. if (mons_looks_stabbable(m)) m_brands |= 1; diff --git a/crawl-ref/source/terrain.cc b/crawl-ref/source/terrain.cc index ae538be8fb..621403ff36 100644 --- a/crawl-ref/source/terrain.cc +++ b/crawl-ref/source/terrain.cc @@ -311,7 +311,12 @@ unsigned int show_appearance(const coord_def &ep) dungeon_feature_type grid_appearance(const coord_def &gc) { - dungeon_feature_type grid = grd(gc); + return grid_appearance(grd, gc); +} + +dungeon_feature_type grid_appearance(feature_grid &gr, const coord_def &gc) +{ + dungeon_feature_type grid = gr(gc); if (grid == DNGN_SECRET_DOOR) grid = grid_secret_door_appearance(gc); diff --git a/crawl-ref/source/terrain.h b/crawl-ref/source/terrain.h index 2c32be9af7..4e3df832c8 100644 --- a/crawl-ref/source/terrain.h +++ b/crawl-ref/source/terrain.h @@ -48,6 +48,7 @@ void find_connected_range(coord_def d, dungeon_feature_type ft_min, void get_door_description(int door_size, const char** adjective, const char** noun); dungeon_feature_type grid_secret_door_appearance(const coord_def &where); dungeon_feature_type grid_appearance(const coord_def &gc); +dungeon_feature_type grid_appearance(feature_grid &gr, const coord_def &gc); unsigned int show_appearance(const coord_def &ep); bool grid_destroys_items(dungeon_feature_type grid); diff --git a/crawl-ref/source/travel.cc b/crawl-ref/source/travel.cc index 66b2ebe0f3..421365c9e4 100644 --- a/crawl-ref/source/travel.cc +++ b/crawl-ref/source/travel.cc @@ -274,9 +274,45 @@ bool is_traversable(dungeon_feature_type grid) return (traversable_terrain[grid] == TRAVERSABLE); } +static feature_grid _map_to_grid(coord_def &pos) +{ + feature_grid fgrid = env.grid; + + for (int x = pos.x - LOS_RADIUS; x < pos.x + LOS_RADIUS; x++) + for (int y = pos.y - LOS_RADIUS; y < pos.y + LOS_RADIUS; y++) + { + if (!in_bounds(x,y)) + continue; + + // For unseen terrain, assume transparency. + if (!is_terrain_seen(x,y)) + { + fgrid[x][y] = DNGN_FLOOR; + continue; + } + + if (!is_terrain_changed(x,y)) + continue; + + if (env.map[x][y].object < NUM_REAL_FEATURES) + fgrid[x][y] = (dungeon_feature_type) env.map[x][y].object; + else + { + // If you have seen monsters, items or clouds there, + // it must have been passable. + fgrid[x][y] = DNGN_FLOOR; + } + } + + return fgrid; +} + void travel_exclude::set_exclude_show() { - losight(show, grd, pos); + // ignores clouds + feature_grid fgrid = _map_to_grid(pos); + losight(show, fgrid, pos, false, true); + uptodate = true; } void init_exclusion_los() @@ -285,11 +321,20 @@ void init_exclusion_los() curr_excludes[i].set_exclude_show(); } -void update_exclusion_los(coord_def &p) +void update_exclusion_los(const coord_def &p) { for (unsigned int i = 0; i < curr_excludes.size(); i++) - if ((curr_excludes[i].pos - p).abs() <= LOS_RADIUS) + if (!curr_excludes[i].uptodate + && (curr_excludes[i].pos - p).abs() <= LOS_RADIUS * LOS_RADIUS) + { curr_excludes[i].set_exclude_show(); + } +} + +void mark_all_excludes_non_updated() +{ + for (unsigned int i = 0; i < curr_excludes.size(); i++) + curr_excludes[i].uptodate = false; } static bool _is_excluded(const coord_def &p, diff --git a/crawl-ref/source/travel.h b/crawl-ref/source/travel.h index 77368c23be..700d8635db 100644 --- a/crawl-ref/source/travel.h +++ b/crawl-ref/source/travel.h @@ -436,13 +436,15 @@ public: }; void init_exclusion_los(); -void update_exclusion_los(coord_def &p); +void update_exclusion_los(const coord_def &p); +void mark_all_excludes_non_updated(); struct travel_exclude { - coord_def pos; - int radius; - env_show_grid show; + coord_def pos; // exclusion centre + int radius; // exclusion radisu + env_show_grid show; // los from exclusion centre + bool uptodate; // Is show up to date? void set_exclude_show(); diff --git a/crawl-ref/source/view.cc b/crawl-ref/source/view.cc index 9239c33266..fe4c69b8c3 100644 --- a/crawl-ref/source/view.cc +++ b/crawl-ref/source/view.cc @@ -413,8 +413,13 @@ static void _get_symbol( const coord_def& where, { const int colmask = *colour & COLFLAG_MASK; + bool excluded_stairs = (object >= DNGN_STONE_STAIRS_DOWN_I + && object <= DNGN_ESCAPE_HATCH_UP + && is_exclude_root(where)); + bool blocked_movement = false; - if (object < NUM_FEATURES && object >= DNGN_MINMOVE + if (!excluded_stairs + && object < NUM_FEATURES && object >= DNGN_MINMOVE && you.duration[DUR_BEHELD]) { // Colour grids that cannot be reached due to beholders @@ -433,7 +438,11 @@ static void _get_symbol( const coord_def& where, } } - if (blocked_movement) + if (excluded_stairs) + { + *colour = Options.tc_excluded | colmask; + } + else if (blocked_movement) { *colour = DARKGREY | colmask; } @@ -746,8 +755,6 @@ void clear_map(bool clear_detected_items, bool clear_detected_monsters) // This reasoning doesn't make sense when it comes to *clearing* // the map! (jpeg) -// if (is_terrain_changed(x, y)) -// continue; unsigned envc = get_envmap_char(x, y); if (!envc) @@ -2505,16 +2512,16 @@ bool find_ray( const coord_def& source, const coord_def& target, slope_diff, ray_slope_diff))) { // Success! - ray = fullrays[fullray]; + ray = fullrays[fullray]; ray.fullray_idx = fullray; shortest = real_length; imbalance = cimbalance; slope_diff = ray_slope_diff; - if ( sourcex > targetx ) + if (sourcex > targetx) ray.accx = 1.0 - ray.accx; - if ( sourcey > targety ) + if (sourcey > targety) ray.accy = 1.0 - ray.accy; ray.accx += sourcex; @@ -2642,7 +2649,7 @@ int num_feats_between(const coord_def& source, const coord_def& target, // done by updating with a second array. void losight(env_show_grid &sh, feature_grid &gr, const coord_def& center, - bool clear_walls_block) + bool clear_walls_block, bool ignore_clouds) { raycast(); const int x_p = center.x; @@ -2657,7 +2664,7 @@ void losight(env_show_grid &sh, const unsigned int num_cellrays = compressed_ray_x.size(); const unsigned int num_words = (num_cellrays + LONGSIZE - 1) / LONGSIZE; - for ( int quadrant = 0; quadrant < 4; ++quadrant ) + for (int quadrant = 0; quadrant < 4; ++quadrant) { const int xmult = quadrant_x[quadrant]; const int ymult = quadrant_y[quadrant]; @@ -2668,9 +2675,9 @@ void losight(env_show_grid &sh, // kill all blocked rays const unsigned long* inptr = los_blockrays; - for ( int xdiff = 0; xdiff <= LOS_MAX_RANGE_X; ++xdiff ) + for (int xdiff = 0; xdiff <= LOS_MAX_RANGE_X; ++xdiff) for (int ydiff = 0; ydiff <= LOS_MAX_RANGE_Y; - ++ydiff, inptr += num_words ) + ++ydiff, inptr += num_words) { const int realx = x_p + xdiff * xmult; @@ -2680,20 +2687,21 @@ void losight(env_show_grid &sh, continue; coord_def real(realx, realy); - dungeon_feature_type dfeat = grid_appearance(real); + dungeon_feature_type dfeat = grid_appearance(gr, real); // if this cell is opaque... - if ( grid_is_opaque(dfeat) - || (clear_walls_block && grid_is_wall(dfeat))) + if (grid_is_opaque(dfeat) + || clear_walls_block && grid_is_wall(dfeat)) { // then block the appropriate rays - for ( unsigned int i = 0; i < num_words; ++i ) + for (unsigned int i = 0; i < num_words; ++i) dead_rays[i] |= inptr[i]; } - else if ( is_opaque_cloud(env.cgrid[realx][realy]) ) + else if (!ignore_clouds + && is_opaque_cloud(env.cgrid[realx][realy])) { // block rays which have already seen a cloud - for ( unsigned int i = 0; i < num_words; ++i ) + for (unsigned int i = 0; i < num_words; ++i) { dead_rays[i] |= (smoke_rays[i] & inptr[i]); smoke_rays[i] |= inptr[i]; @@ -2704,11 +2712,11 @@ void losight(env_show_grid &sh, // ray calculation done, now work out which cells in this // quadrant are visible unsigned int rayidx = 0; - for ( unsigned int wordloc = 0; wordloc < num_words; ++wordloc ) + for (unsigned int wordloc = 0; wordloc < num_words; ++wordloc) { const unsigned long curword = dead_rays[wordloc]; // Note: the last word may be incomplete - for ( unsigned int bitloc = 0; bitloc < LONGSIZE; ++bitloc) + for (unsigned int bitloc = 0; bitloc < LONGSIZE; ++bitloc) { // make the cells seen by this ray at this point visible if ( ((curword >> bitloc) & 1UL) == 0 ) @@ -2719,13 +2727,13 @@ void losight(env_show_grid &sh, // update shadow map if (x_p + realx >= 0 && x_p + realx < 80 && y_p + realy >= 0 && y_p + realy < 70 - && realx * realx + realy * realy <= los_radius_squared ) + && realx * realx + realy * realy <= los_radius_squared) { sh[sh_xo+realx][sh_yo+realy] = gr[x_p+realx][y_p+realy]; } } ++rayidx; - if ( rayidx == num_cellrays ) + if (rayidx == num_cellrays) break; } } @@ -3716,7 +3724,7 @@ bool magic_mapping(int map_radius, int proportion, bool suppress_msg, // to detect exits magically. if (wizard_map || player_mutation_level(MUT_PANDEMONIUM) > 1 - && grd(*ri) == DNGN_EXIT_PANDEMONIUM) + && grd(*ri) == DNGN_EXIT_PANDEMONIUM) { set_terrain_seen( *ri ); } @@ -4920,6 +4928,7 @@ void viewwindow(bool draw_it, bool do_updates) if (flash_colour == BLACK) flash_colour = _viewmap_flash_colour(); + std::vector update_excludes; for (count_y = crawl_view.viewp.y; count_y < crawl_view.viewp.y + crawl_view.viewsz.y; count_y++) { @@ -5006,6 +5015,9 @@ void viewwindow(bool draw_it, bool do_updates) if (map) { set_envmap_glyph( gc.x, gc.y, object, colour ); + if (is_terrain_changed(gc) || !is_terrain_seen(gc)) + update_excludes.push_back(gc); + set_terrain_seen( gc.x, gc.y ); set_envmap_detected_mons(gc.x, gc.y, false); set_envmap_detected_item(gc.x, gc.y, false); @@ -5061,6 +5073,9 @@ void viewwindow(bool draw_it, bool do_updates) if (buffy[bufcount] != 0) { // ... map that we've seen this + if (is_terrain_changed(gc) || !is_terrain_seen(gc)) + update_excludes.push_back(gc); + set_terrain_seen( gc.x, gc.y ); set_envmap_glyph( gc.x, gc.y, object, colour ); set_envmap_detected_mons(gc.x, gc.y, false); @@ -5160,6 +5175,14 @@ void viewwindow(bool draw_it, bool do_updates) } } + if (!update_excludes.empty()) + { + mark_all_excludes_non_updated(); + + for (unsigned int k = 0; k < update_excludes.size(); k++) + update_exclusion_los(update_excludes[k]); + } + // Leaving it this way because short flashes can occur in long ones, // and this simply works without requiring a stack. you.flash_colour = BLACK; diff --git a/crawl-ref/source/view.h b/crawl-ref/source/view.h index f0f21cf266..1e0c6e47fc 100644 --- a/crawl-ref/source/view.h +++ b/crawl-ref/source/view.h @@ -88,7 +88,8 @@ void find_features(const std::vector& features, * called from: direct - monstufff - view * *********************************************************************** */ void losight(env_show_grid &sh, feature_grid &gr, - const coord_def& center, bool clear_walls_block = false); + const coord_def& center, bool clear_walls_block = false, + bool ignore_clouds = false); bool magic_mapping(int map_radius, int proportion, bool suppress_msg, -- cgit v1.2.3-54-g00ecf