From 12de33d2d95164e30a8a2ac960ad28b2a69383e3 Mon Sep 17 00:00:00 2001 From: j-p-e-g Date: Thu, 17 Apr 2008 21:28:56 +0000 Subject: Another modification of autotargetting submerged monsters, based off BR 1935715. * Targeting a square with a known submerged monster ("strange disturbance" description) always enforces '!' rather than '.' * Submerged monsters only get targetted if there are no other more viable targets (dangerous monsters, really) in sight. The latter uses a heavily modified i_feel_safe() that now draws on get_playervisible_monsters(), which got numerous new parameters to cover all possibilities. :p git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@4314 c06c8d41-db1a-0410-9941-cceddc491573 --- crawl-ref/source/direct.cc | 78 +++++++++++++++-------- crawl-ref/source/fight.cc | 10 +-- crawl-ref/source/invent.cc | 1 + crawl-ref/source/misc.cc | 150 ++++++++++++++++++++------------------------ crawl-ref/source/misc.h | 9 ++- crawl-ref/source/skills2.cc | 10 +-- 6 files changed, 135 insertions(+), 123 deletions(-) diff --git a/crawl-ref/source/direct.cc b/crawl-ref/source/direct.cc index 31bf2c580d..c822c03304 100644 --- a/crawl-ref/source/direct.cc +++ b/crawl-ref/source/direct.cc @@ -247,6 +247,19 @@ static void draw_ray_glyph(const coord_def &pos, int colour, #endif } +// Unseen monsters in shallow water show a "strange disturbance". +// (Unless flying!) +static bool _mon_submerged_in_water(const monsters *mon) +{ + if (!mon) + return false; + + return (grd[mon->x][mon->y] == DNGN_SHALLOW_WATER + && see_grid(mon->x, mon->y) + && !player_monster_visible(mon) + && !mons_flies(mon)); +} + static bool _is_target_in_range(int x, int y, int range) { // range doesn't matter @@ -564,11 +577,11 @@ void direction(dist& moves, targeting_type restricts, key_command = shift_direction(key_command); } - if (target_unshifted && - (key_command == CMD_TARGET_CYCLE_FORWARD - || key_command == CMD_TARGET_CYCLE_BACK - || key_command == CMD_TARGET_OBJ_CYCLE_FORWARD - || key_command == CMD_TARGET_OBJ_CYCLE_BACK)) + if (target_unshifted + && (key_command == CMD_TARGET_CYCLE_FORWARD + || key_command == CMD_TARGET_CYCLE_BACK + || key_command == CMD_TARGET_OBJ_CYCLE_FORWARD + || key_command == CMD_TARGET_OBJ_CYCLE_BACK)) { target_unshifted = false; } @@ -710,8 +723,8 @@ void direction(dist& moves, targeting_type restricts, mode = static_cast((mode + 1) % TARG_NUM_MODES); mprf( "Targeting mode is now: %s", (mode == TARG_ANY) ? "any" : - (mode == TARG_ENEMY) ? "enemies" : - "friends" ); + (mode == TARG_ENEMY) ? "enemies" + : "friends" ); break; case CMD_TARGET_PREV_TARGET: @@ -758,7 +771,13 @@ void direction(dist& moves, targeting_type restricts, moves.isEndpoint = true; // intentional fall-through case CMD_TARGET_SELECT: // finalize current choice - moves.isValid = true; + if (!moves.isEndpoint + && mgrd[moves.tx][moves.ty] != NON_MONSTER + && _mon_submerged_in_water(&menv[mgrd[moves.tx][moves.ty]])) + { + moves.isEndpoint = true; + } + moves.isValid = true; moves.isTarget = true; loop_done = true; @@ -919,8 +938,8 @@ void direction(dist& moves, targeting_type restricts, MSGCH_EXAMINE_FILTER); } // Ask for confirmation if we're quitting for some odd reason - else if ( moves.isValid || moves.isCancel || - yesno("Are you sure you want to fizzle?", false, 'n') ) + else if ( moves.isValid || moves.isCancel + || yesno("Are you sure you want to fizzle?", false, 'n') ) { // Finalize whatever is inside the loop // (moves-internal finalizations can be done later) @@ -966,17 +985,18 @@ void direction(dist& moves, targeting_type restricts, #ifdef USE_TILE // tiles always need a beam redraw if show_beam is true (and if valid...) - if (show_beam && find_ray(you.x_pos, you.y_pos, moves.tx, moves.ty, - true, ray, 0, true) || need_beam_redraw ) + if ( need_beam_redraw + || show_beam && find_ray(you.x_pos, you.y_pos, moves.tx, moves.ty, + true, ray, 0, true) ) { #else if ( need_beam_redraw ) { viewwindow(true, false); #endif - if ( show_beam && - in_vlos(grid2viewX(moves.tx), grid2viewY(moves.ty)) && - moves.target() != you.pos() ) + if ( show_beam + && in_vlos(grid2viewX(moves.tx), grid2viewY(moves.ty)) + && moves.target() != you.pos() ) { // Draw the new ray with magenta '*'s, not including // your square or the target square. @@ -996,7 +1016,7 @@ void direction(dist& moves, targeting_type restricts, textcolor(LIGHTGREY); #ifdef USE_TILE draw_ray_glyph(moves.target(), MAGENTA, '*', - MAGENTA | COLFLAG_REVERSE); + MAGENTA | COLFLAG_REVERSE); } viewwindow(true, false); #else @@ -1131,23 +1151,27 @@ static bool find_monster( int x, int y, int mode, int range = -1) if (targ_mon == NON_MONSTER || !in_los(x,y)) return (false); - // Unseen monsters in shallow water show a "strange disturbance" - // (unless flying!) - if (!player_monster_visible(&menv[targ_mon])) - { - // since you can't see the monster, assume it's not a friend - return (mode != TARG_FRIEND - && grd[x][y] == DNGN_SHALLOW_WATER - && !mons_flies(&menv[targ_mon])); - } + monsters *mon = &menv[targ_mon]; // Unknown mimics don't count as monsters, either. - if (mons_is_mimic(menv[targ_mon].type) - && !(menv[targ_mon].flags & MF_KNOWN_MIMIC)) + if (mons_is_mimic(mon->type) + && !(mon->flags & MF_KNOWN_MIMIC)) { return (false); } + // Don't usually target unseen monsters... + if (!player_monster_visible(mon)) + { + // ... unless it creates a "disturbance in the water". + // Since you can't see the monster, assume it's not a friend. + // Also don't target submerged monsters if there are other targets + // in sight. (This might be too restrictive.) + return (mode != TARG_FRIEND + && _mon_submerged_in_water(mon) + && i_feel_safe(false, false, true, range)); + } + // Now compare target modes. if (mode == TARG_ANY) return true; diff --git a/crawl-ref/source/fight.cc b/crawl-ref/source/fight.cc index 80e10471de..ddbaad4aa2 100644 --- a/crawl-ref/source/fight.cc +++ b/crawl-ref/source/fight.cc @@ -348,13 +348,13 @@ void melee_attack::init_attack() if (defender) defender_shield = defender->shield(); - water_attack = is_water_attack(attacker, defender); - attacker_visible = attacker->visible(); + water_attack = is_water_attack(attacker, defender); + attacker_visible = attacker->visible(); attacker_invisible = !attacker_visible && see_grid(attacker->pos()); - defender_visible = defender && defender->visible(); + defender_visible = defender && defender->visible(); defender_invisible = !defender_visible && defender - && see_grid(defender->pos()); - needs_message = attacker_visible || defender_visible; + && see_grid(defender->pos()); + needs_message = attacker_visible || defender_visible; if (defender && defender->submerged()) unarmed_ok = false; diff --git a/crawl-ref/source/invent.cc b/crawl-ref/source/invent.cc index 01e5bd5543..f232e5374c 100644 --- a/crawl-ref/source/invent.cc +++ b/crawl-ref/source/invent.cc @@ -537,6 +537,7 @@ const menu_sort_condition *InvMenu::find_menu_sort_condition() const for (int i = 0, size = Options.sort_menus.size(); i < size; ++i) if (Options.sort_menus[i].matches(type)) return &Options.sort_menus[i]; + return (NULL); } diff --git a/crawl-ref/source/misc.cc b/crawl-ref/source/misc.cc index bb1cba82f7..5f210c6ca7 100644 --- a/crawl-ref/source/misc.cc +++ b/crawl-ref/source/misc.cc @@ -2537,10 +2537,10 @@ bool mons_is_safe(const struct monsters *mon, bool want_move) || mons_class_flag(mon->type, M_NO_EXP_GAIN); #ifdef CLUA_BINDINGS - bool moving = ((!you.delay_queue.empty() && - is_run_delay(you.delay_queue.front().type) && - you.delay_queue.front().type != DELAY_REST) || - you.running < RMODE_NOT_RUNNING || want_move); + bool moving = ((!you.delay_queue.empty() + && is_run_delay(you.delay_queue.front().type) + && you.delay_queue.front().type != DELAY_REST) + || you.running < RMODE_NOT_RUNNING || want_move); int dist = grid_distance(you.x_pos, you.y_pos, mon->x, mon->y); @@ -2559,113 +2559,97 @@ bool mons_is_safe(const struct monsters *mon, bool want_move) // Return all monsters in LOS that the player is able to see // and recognize as being a monster. -void get_playervisible_monsters(std::vector& mons) +void get_playervisible_monsters(std::vector &mons, bool want_move, + bool just_check, bool dangerous, int range) { - const int ystart = MAX(0, you.y_pos - LOS_RADIUS); - const int yend = MIN(GYM, you.y_pos + LOS_RADIUS); - const int xstart = MAX(0, you.x_pos - LOS_RADIUS); - const int xend = MIN(GXM, you.x_pos + LOS_RADIUS); + if (range == -1) + range = LOS_RADIUS; + + const int ystart = MAX(0, you.y_pos - range); + const int yend = MIN(GYM, you.y_pos + range); + const int xstart = MAX(0, you.x_pos - range); + const int xend = MIN(GXM, you.x_pos + range); // monster check for ( int y = ystart; y < yend; ++y ) - for ( int x = xstart; x < xend; ++x ) - { - const unsigned short targ_monst = env.mgrid[x][y]; - if ( targ_monst != NON_MONSTER ) + for ( int x = xstart; x < xend; ++x ) { - if ( see_grid(x,y) ) + const unsigned short targ_monst = env.mgrid[x][y]; + if ( targ_monst != NON_MONSTER ) { - monsters *mon = &env.mons[targ_monst]; - if ( player_monster_visible(mon) && - !mons_is_submerged(mon) && - (!mons_is_mimic(mon->type) || mons_is_known_mimic(mon)) - ) + if ( see_grid(x,y) ) { - mons.push_back(mon); + monsters *mon = &env.mons[targ_monst]; + if ( player_monster_visible(mon) + && !mons_is_submerged(mon) + && (!mons_is_mimic(mon->type) + || mons_is_known_mimic(mon)) + && (!dangerous || !mons_is_safe(mon, want_move))) + { + mons.push_back(mon); + if (just_check) + { + // one monster found, that's enough + return; + } + } } } } - } } -bool i_feel_safe(bool announce, bool want_move) +bool i_feel_safe(bool announce, bool want_move, bool just_monsters, int range) { - int ystart = you.y_pos - 9, xstart = you.x_pos - 9; - int yend = you.y_pos + 9, xend = you.x_pos + 9; - if ( xstart < 0 ) xstart = 0; - if ( ystart < 0 ) ystart = 0; - if ( xend >= GXM ) xend = GXM; - if ( yend >= GYM ) yend = GYM; - - if (in_bounds(you.x_pos, you.y_pos) - && env.cgrid[you.x_pos][you.y_pos] != EMPTY_CLOUD) - { - const cloud_type type = - env.cloud[ env.cgrid[you.x_pos][you.y_pos] ].type; - if (is_damaging_cloud(type, false)) - { - if (announce) - mprf(MSGCH_WARN, "You're standing in a cloud of %s!", - cloud_name(type).c_str()); - return (false); - } - } - - // no monster will attack you inside a sanctuary, - // so presence of monsters won't matter - if (is_sanctuary(you.x_pos, you.y_pos)) - return (true); - - std::vector mons; - - // monster check - // XXX: refactor this to make use of get_playervisible_monsters() - for ( int y = ystart; y < yend; ++y ) + if (!just_monsters) { - for ( int x = xstart; x < xend; ++x ) + if (in_bounds(you.x_pos, you.y_pos) + && env.cgrid[you.x_pos][you.y_pos] != EMPTY_CLOUD) { - // if you can see an unfriendly monster, then you feel unsafe - if ( see_grid(x,y) ) + const cloud_type type = + env.cloud[ env.cgrid[you.x_pos][you.y_pos] ].type; + if (is_damaging_cloud(type, false)) { - const unsigned short targ_monst = mgrd[x][y]; - if ( targ_monst != NON_MONSTER ) + if (announce) { - const monsters *mon = &menv[targ_monst]; - if ( player_monster_visible(mon) && - !mons_is_submerged(mon) && - !mons_is_mimic(mon->type) && - !mons_is_safe(mon, want_move)) - { - if (announce) - mons.push_back(mon); - else - { - tutorial_first_monster(*mon); - return false; - } - } + mprf(MSGCH_WARN, "You're standing in a cloud of %s!", + cloud_name(type).c_str()); } + return (false); } } + + // no monster will attack you inside a sanctuary, + // so presence of monsters won't matter + if (is_sanctuary(you.x_pos, you.y_pos)) + return (true); } - if (announce) + // monster check + std::vector visible; + get_playervisible_monsters(visible, !announce, want_move, true, range); + + // No monsters found. + if (visible.empty()) + return true; + + // Announce the presence of monsters (Eidolos). + if (visible.size() == 1) { - // Announce the presence of monsters (Eidolos). - if (mons.size() == 1) + const monsters &m = *visible[0]; + if (announce) { - const monsters &m = *mons[0]; mprf(MSGCH_WARN, "Not with %s in view!", - m.name(DESC_NOCAP_A).c_str()); - } - else if (mons.size() > 1) - { - mprf(MSGCH_WARN, "Not with these monsters around!"); + m.name(DESC_NOCAP_A).c_str()); } - return (mons.empty()); + else + tutorial_first_monster(m); + } + else if (announce && visible.size() > 1) + { + mprf(MSGCH_WARN, "Not with these monsters around!"); } - return true; + return (false); } static const char *shop_types[] = { diff --git a/crawl-ref/source/misc.h b/crawl-ref/source/misc.h index 9e71adead8..2223757511 100644 --- a/crawl-ref/source/misc.h +++ b/crawl-ref/source/misc.h @@ -113,7 +113,12 @@ void curare_hits_player(int agent, int degree); bool mons_is_safe(const monsters *mon, bool want_move = false); -bool i_feel_safe(bool announce = false, bool want_move = false); +void get_playervisible_monsters(std::vector& mons, + bool just_check = false, bool want_move = false, + bool dangerous = false, int range = -1); + +bool i_feel_safe(bool announce = false, bool want_move = false, + bool just_monsters = false, int range = -1); void setup_environment_effects(); @@ -137,6 +142,4 @@ bool interrupt_cmd_repeat( activity_interrupt_type ai, void reveal_secret_door(int x, int y); -void get_playervisible_monsters(std::vector& mons); - #endif diff --git a/crawl-ref/source/skills2.cc b/crawl-ref/source/skills2.cc index 01a120a906..550164c3ee 100644 --- a/crawl-ref/source/skills2.cc +++ b/crawl-ref/source/skills2.cc @@ -1698,13 +1698,13 @@ static const skill_type skill_display_order[] = static const int ndisplayed_skills = sizeof(skill_display_order) / sizeof(*skill_display_order); -static bool player_knows_aptitudes() +static bool _player_knows_aptitudes() { return !player_genus(GENPC_DRACONIAN) || you.max_level >= 7; } -static void display_skill_table(bool show_aptitudes) +static void _display_skill_table(bool show_aptitudes) { menu_letter lcount = 'a'; const int num_lines = get_number_of_lines(); @@ -1847,7 +1847,7 @@ static void display_skill_table(bool show_aptitudes) textcolor(LIGHTGREY); cprintf("Press the letter of a skill to choose " "whether you want to practise it."); - if (player_knows_aptitudes()) + if (_player_knows_aptitudes()) { cgotoxy(1, bottom_line); formatted_string::parse_string("Press '!' to toggle between " @@ -1864,10 +1864,10 @@ void show_skills() clrscr(); while (true) { - display_skill_table(show_aptitudes); + _display_skill_table(show_aptitudes); const int keyin = getch(); - if (keyin == '!' && player_knows_aptitudes()) + if (keyin == '!' && _player_knows_aptitudes()) { show_aptitudes = !show_aptitudes; continue; -- cgit v1.2.3-54-g00ecf