From 01aad4196cdce515028b839ab7d9d06b31b4351f Mon Sep 17 00:00:00 2001 From: Evan Debenham Date: Tue, 30 Aug 2016 18:33:16 -0400 Subject: [PATCH] v0.4.2: implemented path storage for better pathfinder performance --- .../shatteredpixeldungeon/actors/Char.java | 3 +- .../actors/hero/Hero.java | 45 +++++++++--- .../actors/mobs/Mob.java | 71 +++++++++++++++++-- 3 files changed, 104 insertions(+), 15 deletions(-) diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/Char.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/Char.java index 7662a9599..2989f7628 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/Char.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/Char.java @@ -67,7 +67,8 @@ public abstract class Char extends Actor { public int SHLD; protected float baseSpeed = 1; - + protected PathFinder.Path path; + public int paralysed = 0; public boolean rooted = false; public boolean flying = false; diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/Hero.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/Hero.java index 8dcdf0036..3ae9c9159 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/Hero.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/Hero.java @@ -1013,6 +1013,9 @@ public class Hero extends Char { private boolean getCloser( final int target ) { + if (target == pos) + return false; + if (rooted) { Camera.main.shake( 1, 1f ); return false; @@ -1022,6 +1025,8 @@ public class Hero extends Char { if (Dungeon.level.adjacent( pos, target )) { + path = null; + if (Actor.findChar( target ) == null) { if (Level.pit[target] && !flying && !Level.solid[target]) { if (!Chasm.jumpConfirmed){ @@ -1039,16 +1044,40 @@ public class Hero extends Char { } else { - int len = Dungeon.level.length(); - boolean[] p = Level.passable; - boolean[] v = Dungeon.level.visited; - boolean[] m = Dungeon.level.mapped; - boolean[] passable = new boolean[len]; - for (int i=0; i < len; i++) { - passable[i] = p[i] && (v[i] || m[i]); + boolean newPath = false; + if (path == null || path.isEmpty()) + newPath = true; + else if (path.getLast() != target) + newPath = true; + else { + //checks 2 cells ahead for validity. + //Note that this is shorter than for mobs, so that mobs usually yield to the hero + for (int i = 0; i < Math.min(path.size(), 2); i++){ + int cell = path.get(i); + if (!Level.passable[cell] || ((i != path.size()-1) && Dungeon.visible[cell] && Actor.findChar(cell) != null)) { + newPath = true; + break; + } + } } - step = Dungeon.findStep( this, pos, target, passable, Level.fieldOfView ); + if (newPath) { + + int len = Dungeon.level.length(); + boolean[] p = Level.passable; + boolean[] v = Dungeon.level.visited; + boolean[] m = Dungeon.level.mapped; + boolean[] passable = new boolean[len]; + for (int i = 0; i < len; i++) { + passable[i] = p[i] && (v[i] || m[i]); + } + + path = Dungeon.findPath(this, pos, target, passable, Level.fieldOfView); + } + + if (path == null) return false; + step = path.removeFirst(); + } if (step != -1) { diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Mob.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Mob.java index fd6839420..1716568ba 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Mob.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Mob.java @@ -290,13 +290,72 @@ public abstract class Mob extends Char { protected boolean getCloser( int target ) { - if (rooted) { + if (rooted || target == pos) { return false; } - - int step = Dungeon.findStep( this, pos, target, - Level.passable, - Level.fieldOfView ); + + boolean newPath = false; + if (path == null || path.isEmpty()) + newPath = true; + else if (path.getLast() != target) { + //if the new target is adjacent to the end of the path, adjust for that + //rather than scrapping the whole path + if (Dungeon.level.adjacent(target, path.getLast())){ + int last = path.removeLast(); + + if (path.isEmpty()) { + + //shorten for a closer one + if (Dungeon.level.adjacent(target, pos)) { + path.add(target); + //extend the path for a further target + } else { + path.add(last); + path.add(target); + } + + } else if (!path.isEmpty()){ + //if the new target is simply 1 earlier in the path shorten the path + if (path.getLast() == target) { + + //if the new target is closer/same, need to modify end of path + } else if (Dungeon.level.adjacent(target, path.getLast())){ + path.add(target); + + //if the new target is further away, need to extend the path + } else { + path.add(last); + path.add(target); + } + } + + } else { + newPath = true; + } + + } + + if (!newPath){ + //checks the next 4 cells in the path for validity + for (int i = 0; i < Math.min(path.size(), 4); i++){ + int cell = path.get(i); + if (!Level.passable[cell] || ((i != path.size()-1) && Dungeon.visible[cell] && Actor.findChar(cell) != null)) { + newPath = true; + break; + } + } + } + + if (newPath) { + path = Dungeon.findPath(this, pos, target, + Level.passable, + Level.fieldOfView); + } + + if (path == null) + return false; + + int step = path.removeFirst(); if (step != -1) { move( step ); return true; @@ -467,7 +526,7 @@ public abstract class Mob extends Char { float lootChance = this.lootChance; int bonus = RingOfWealth.getBonus(Dungeon.hero, RingOfWealth.Wealth.class); - lootChance *= Math.pow(1.1, bonus); + lootChance *= Math.pow(1.15, bonus); if (Random.Float() < lootChance && Dungeon.hero.lvl <= maxLvl + 2) { Item loot = createLoot();