v2.1.1: enemies now go for targets they can reach over ones they can't

This commit is contained in:
Evan Debenham
2023-06-08 13:46:44 -04:00
parent ca0d8bbda7
commit a49215ccc7
2 changed files with 18 additions and 40 deletions
@@ -957,8 +957,7 @@ public class Dungeon {
BArray.setFalse(passable); BArray.setFalse(passable);
} }
public static PathFinder.Path findPath(Char ch, int to, boolean[] pass, boolean[] vis, boolean chars) { public static boolean[] findPassable(Char ch, boolean[] pass, boolean[] vis, boolean chars){
setupPassable(); setupPassable();
if (ch.flying || ch.buff( Amok.class ) != null) { if (ch.flying || ch.buff( Amok.class ) != null) {
BArray.or( pass, Dungeon.level.avoid, passable ); BArray.or( pass, Dungeon.level.avoid, passable );
@@ -978,7 +977,12 @@ public class Dungeon {
} }
} }
return PathFinder.find( ch.pos, to, passable ); return passable;
}
public static PathFinder.Path findPath(Char ch, int to, boolean[] pass, boolean[] vis, boolean chars) {
return PathFinder.find( ch.pos, to, findPassable(ch, pass, vis, chars) );
} }
@@ -988,47 +992,17 @@ public class Dungeon {
return Actor.findChar( to ) == null && (pass[to] || Dungeon.level.avoid[to]) ? to : -1; return Actor.findChar( to ) == null && (pass[to] || Dungeon.level.avoid[to]) ? to : -1;
} }
setupPassable(); return PathFinder.getStep( ch.pos, to, findPassable(ch, pass, visible, chars) );
if (ch.flying || ch.buff( Amok.class ) != null) {
BArray.or( pass, Dungeon.level.avoid, passable );
} else {
System.arraycopy( pass, 0, passable, 0, Dungeon.level.length() );
}
if (Char.hasProp(ch, Char.Property.LARGE)){
BArray.and( passable, Dungeon.level.openSpace, passable );
}
if (chars){
for (Char c : Actor.chars()) {
if (visible[c.pos]) {
passable[c.pos] = false;
}
}
}
return PathFinder.getStep( ch.pos, to, passable );
} }
public static int flee( Char ch, int from, boolean[] pass, boolean[] visible, boolean chars ) { public static int flee( Char ch, int from, boolean[] pass, boolean[] visible, boolean chars ) {
//only consider chars impassable if our retreat path runs into them
setupPassable(); boolean[] passable = findPassable(ch, pass, visible, false);
if (ch.flying) {
BArray.or( pass, Dungeon.level.avoid, passable );
} else {
System.arraycopy( pass, 0, passable, 0, Dungeon.level.length() );
}
if (Char.hasProp(ch, Char.Property.LARGE)){
BArray.and( passable, Dungeon.level.openSpace, passable );
}
passable[ch.pos] = true; passable[ch.pos] = true;
//only consider chars impassable if our retreat path runs into them
int step = PathFinder.getStepBack( ch.pos, from, passable ); int step = PathFinder.getStepBack( ch.pos, from, passable );
while (step != -1 && Actor.findChar(step) != null){ while (step != -1 && Actor.findChar(step) != null && chars){
passable[step] = false; passable[step] = false;
step = PathFinder.getStepBack( ch.pos, from, passable ); step = PathFinder.getStepBack( ch.pos, from, passable );
} }
@@ -375,16 +375,20 @@ public abstract class Mob extends Char {
if (enemies.isEmpty()){ if (enemies.isEmpty()){
return null; return null;
} else { } else {
//go after the closest potential enemy, preferring enemies that can be attacked, and the hero if two are equidistant //go after the closest potential enemy, preferring enemies that can be reached/attacked, and the hero if two are equidistant
PathFinder.buildDistanceMap(pos, Dungeon.findPassable(this, Dungeon.level.passable, fieldOfView, true));
Char closest = null; Char closest = null;
for (Char curr : enemies){ for (Char curr : enemies){
if (closest == null){ if (closest == null){
closest = curr; closest = curr;
} else if (canAttack(closest) && !canAttack(curr)){ } else if (canAttack(closest) && !canAttack(curr)){
continue; continue;
} else if ((canAttack(curr) && !canAttack(closest)) } else if ((canAttack(curr) && !canAttack(closest))
|| (Dungeon.level.distance(pos, curr.pos) < Dungeon.level.distance(pos, closest.pos)) || (PathFinder.distance[curr.pos] < PathFinder.distance[closest.pos])){
|| (Dungeon.level.distance(pos, curr.pos) == Dungeon.level.distance(pos, closest.pos) && curr == Dungeon.hero)){ closest = curr;
} else if ( curr == Dungeon.hero &&
(PathFinder.distance[curr.pos] == PathFinder.distance[closest.pos]) || (canAttack(curr) && canAttack(closest))){
closest = curr; closest = curr;
} }
} }