Explorar el Código

improve path finding (added build4Dirs + keep same direction in getPath)

ncannasse hace 11 años
padre
commit
250f472946
Se han modificado 2 ficheros con 87 adiciones y 9 borrados
  1. 8 4
      hxd/impl/FastIO.hx
  2. 79 5
      hxd/impl/PathFind.hx

+ 8 - 4
hxd/impl/FastIO.hx

@@ -40,6 +40,10 @@ class FastIO<T> {
 		}
 	}
 
+	public inline function flushMax( writesPerRead ) {
+		flush((write < read ? write : (write - read)) * writesPerRead);
+	}
+
 }
 
 class FastIntIO extends FastIO<Int> {
@@ -54,7 +58,7 @@ class FastIntIO extends FastIO<Int> {
 
 	public inline function loop(callb) {
 		while( true ) {
-			flush((write < read ? write : (write - read)) * 4);
+			flushMax(4);
 			if( !hasNext() )
 				break;
 			for( id in this )
@@ -65,7 +69,7 @@ class FastIntIO extends FastIO<Int> {
 	public inline function rec2d( x, y, bits, callb ) {
 		add2d(x, y, bits);
 		while( true ) {
-			flush((write < read ? write : (write - read)) * 4);
+			flushMax(4);
 			if( !hasNext() )
 				break;
 			for( id in this ) {
@@ -84,7 +88,7 @@ class FastIntIO extends FastIO<Int> {
 	public inline function rec2di( x, y, d, bits, callb ) {
 		add2di(x, y, d, bits);
 		while( true ) {
-			flush((write < read ? write : (write - read)) * 4);
+			flushMax(4);
 			if( !hasNext() )
 				break;
 			for( id in this ) {
@@ -106,7 +110,7 @@ class FastIntIO extends FastIO<Int> {
 		var k = 0;
 		add2d(x, y, bits);
 		while( true ) {
-			flush((write < read ? write : (write - read)) * 4);
+			flushMax(4);
 			if( !hasNext() )
 				break;
 			for( id in this ) {

+ 79 - 5
hxd/impl/PathFind.hx

@@ -33,7 +33,7 @@ class PathFind {
 			k++;
 			var a = x + y * width;
 			var p = t[a];
-			if( p != 0 && Math.iabs(p) <= k ) return false;
+			if( p != 0 ) return false;
 			if( collide(x, y) ) {
 				t[a] = -k;
 				return k == 1;
@@ -43,34 +43,107 @@ class PathFind {
 		});
 	}
 
-	public function getPath( x : Int, y : Int ) {
+	/**
+		The collide function will return the allowed movements for a given position as a set of bits 1|2|4|8 for Up|Down|Left|Right
+	**/
+	public inline function build4Dirs( x : Int, y : Int, collide : Int -> Int -> Int ) {
+		var tmp = new FastIO.FastIntIO();
+		var k = 0;
+		tmp.add2d(x, y, bits);
+		while( true ) {
+			tmp.flushMax(4);
+			if( !tmp.hasNext() )
+				break;
+			for( id in tmp ) {
+				var x = id & ((1 << bits) - 1);
+				var y = id >>> bits;
+				var col = collide(x, y);
+
+				var a = x + y * width;
+				var p = t[a];
+				if( p != 0 ) continue;
+
+				var k = k + 1;
+				var col = collide(x, y);
+
+				if( y > 0 ) {
+					if( col & 1 != 0 )
+						tmp.add2d(x, y - 1, bits);
+					else if( t[a - width] == 0 )
+						t[a - width] = -k;
+				}
+
+				if( y < height - 1 ) {
+					if( col & 2 != 0 )
+						tmp.add2d(x, y + 1, bits);
+					else if( t[a + width] == 0 )
+						t[a + width] = -k;
+				}
+
+				if( x > 0 ) {
+					if( col & 4 != 0 )
+						tmp.add2d(x - 1, y, bits);
+					else if( t[a - 1] == 0 )
+						t[a - 1] = -k;
+				}
+
+				if( x < width - 1 ) {
+					if( col & 8 != 0 )
+						tmp.add2d(x + 1, y, bits);
+					else if( t[a + 1] == 0 )
+						t[a + 1] = -k;
+				}
+
+				t[a] = k;
+			}
+			k++;
+		}
+	}
+
+	public function getPath( x : Int, y : Int, ?prefDir : hxd.Direction ) {
 		var a = x + y * width;
 		var k = Math.iabs(t[a]);
 		if( k == 0 ) return null;
 		var path = [];
+		var dir : hxd.Direction = prefDir == null ? Direction.Down : prefDir;
 		while( k > 1 ) {
 			k--;
+
+			// check with previous dir
+			var tx = x + dir.x, ty = y + dir.y, ta = a + dir.x + dir.y * width;
+			if( tx > 0 && tx < width && ty > 0 && ty < height && t[ta] == k ) {
+				x += dir.x;
+				y += dir.y;
+				a = ta;
+				path.push( { x:x, y:y } );
+				continue;
+			}
+
 			if( x > 0 && t[a - 1] == k ) {
 				x--;
 				a--;
+				dir = Left;
 				path.push( { x:x, y:y } );
 				continue;
 			}
 			if( y > 0 && t[a - width] == k ) {
 				y--;
-				a-=width;
+				a -= width;
+				dir = Up;
 				path.push( { x:x, y:y } );
 				continue;
 			}
 			if( x < width-1 && t[a + 1] == k ) {
 				x++;
 				a++;
+				dir = Right;
 				path.push( { x:x, y:y } );
 				continue;
 			}
 			if( y < height - 1 && t[a + width] == k ) {
 				y++;
-				a+=width;
+				a += width;
+				dir = Down;
 				path.push( { x:x, y:y } );
 				continue;
 			}
@@ -97,7 +170,8 @@ class PathFind {
 			}
 			if( y < height - 1 && t[a + width] == k ) {
 				y++;
-				a+=width;				path.push( { x:x, y:y } );
+				a += width;
+				path.push( { x:x, y:y } );
 				continue;
 			}
 			throw "assert";