Check whether there's an unobstructed path to our foe, either by using an existing travel_path or calculating a new one. Returns true if no further handling necessary, else false.
| 85 | // either by using an existing travel_path or calculating a new one. |
| 86 | // Returns true if no further handling necessary, else false. |
| 87 | bool try_pathfind(monster* mon) |
| 88 | { |
| 89 | // Just because we can *see* our target, that doesn't mean |
| 90 | // we can actually get there. |
| 91 | // If no path is found (too far away, perhaps) set a |
| 92 | // flag, so we don't directly calculate the whole thing again |
| 93 | // next turn, and even extend that flag to neighbouring |
| 94 | // monsters of similar movement restrictions. |
| 95 | |
| 96 | const actor* foe = (mon->friendly() && mon->foe == MHITYOU ? &you |
| 97 | : mon->get_foe()); |
| 98 | |
| 99 | // Trying to pathfind towards nothing in particular; bail out. |
| 100 | if (!foe) |
| 101 | return false; |
| 102 | |
| 103 | const coord_def targpos = foe->pos(); |
| 104 | |
| 105 | bool need_pathfind = !can_go_straight(mon, mon->pos(), targpos); |
| 106 | |
| 107 | const int threat_range_lof = mon->threat_range(true, false); |
| 108 | const int threat_range_no_lof = mon->threat_range(false, true); |
| 109 | const int dist = grid_distance(mon->pos(), targpos); |
| 110 | |
| 111 | // Monsters that are already in range to do something threatening to their |
| 112 | // target don't need pathfinding. |
| 113 | if (need_pathfind |
| 114 | && !mon->friendly() |
| 115 | && ((dist <= threat_range_lof |
| 116 | && cell_see_cell(mon->pos(), targpos, LOS_SOLID_SEE)) |
| 117 | || (dist <= threat_range_no_lof |
| 118 | && cell_see_cell(mon->pos(), targpos, LOS_NO_TRANS)))) |
| 119 | { |
| 120 | need_pathfind = false; |
| 121 | } |
| 122 | |
| 123 | if (!need_pathfind) |
| 124 | { |
| 125 | // The target is easily reachable (or we're close enough already). |
| 126 | // Clear travel path and target, if necessary. |
| 127 | if (mon->travel_target != MTRAV_PATROL |
| 128 | && mon->travel_target != MTRAV_NONE) |
| 129 | { |
| 130 | if (mon->is_travelling()) |
| 131 | mon->travel_path.clear(); |
| 132 | mon->travel_target = MTRAV_NONE; |
| 133 | } |
| 134 | return false; |
| 135 | } |
| 136 | |
| 137 | // If the target is "unreachable" (the monster already tried, |
| 138 | // and failed, to find a path), there's a chance of trying again. |
| 139 | // Retreating monsters retry every turn. |
| 140 | if (target_is_unreachable(mon) && !one_chance_in(12)) |
| 141 | return false; |
| 142 | |
| 143 | #ifdef DEBUG_PATHFIND |
| 144 | mprf("%s: Target out of reach! What now?", |
no test coverage detected