shithub: asif

Download patch

ref: 8e0e384527daa1b1b4ef59b5413d074617a62dd4
parent: 71250575dc797b28a5e9a9e8fd612c1253be9bc1
author: qwx <qwx@sciops.net>
date: Wed Mar 23 18:31:17 EDT 2022

add 4-directional pathfinding functions

--- a/path/a∗.c
+++ b/path/a∗.c
@@ -21,7 +21,7 @@
 }
 
 static Node **
-successors(Node *n)
+successors8(Node *n)
 {
 	static Node *suc[8+1];
 	static dtab[2*(nelem(suc)-1)]={
@@ -44,11 +44,40 @@
 		assert(s >= map && s < map + mapwidth * mapheight);
 		if(isblocked(s))
 			continue;
+		s->Δg = 1;
 		*np++ = s;
 	}
 	return suc;
 }
 
+static Node **
+successors4(Node *n)
+{
+	static Node *suc[4+1];
+	static dtab[2*(nelem(suc)-1)]={
+		0,-1, -1,0, 1,0, 0,1,
+	};
+	int i;
+	Node *s, **np;
+	Point p;
+	Rectangle r;
+
+	memset(suc, 0, sizeof suc);
+	p = n2p(n);
+	r = Rect(0, 0, mapwidth, mapheight);
+	for(i=0, np=suc; i<nelem(dtab); i+=2){
+		if(!ptinrect(addpt(p, Pt(dtab[i], dtab[i+1])), r))
+			continue;
+		s = n + dtab[i+1] * mapwidth + dtab[i];
+		assert(s >= map && s < map + mapwidth * mapheight);
+		if(isblocked(s))
+			continue;
+		s->Δg = 1;
+		*np++ = s;
+	}
+	return suc;
+}
+
 static Node *
 a∗(Node *a, Node *b)
 {
@@ -67,13 +96,13 @@
 		if(x == b)
 			break;
 		x->closed = 1;
-		if((sl = successors(x)) == nil)
+		if((sl = successors8(x)) == nil)
 			sysfatal("a∗: %r");
 		for(s=*sl++; s!=nil; s=*sl++){
 			if(s->closed)
 				continue;
 			assert(!isblocked(s));
-			g = x->g + 1;
+			g = x->g + s->Δg;
 			Δg = s->g - g;
 			if(!s->open){
 				s->from = x;
--- a/path/dijkstra.c
+++ b/path/dijkstra.c
@@ -21,7 +21,7 @@
 }
 
 static Node **
-successors(Node *n)
+successors8(Node *n)
 {
 	static Node *suc[8+1];
 	static dtab[2*(nelem(suc)-1)]={
@@ -50,6 +50,34 @@
 	return suc;
 }
 
+static Node **
+successors4(Node *n)
+{
+	static Node *suc[4+1];
+	static dtab[2*(nelem(suc)-1)]={
+		0,-1, -1,0, 1,0, 0,1,
+	};
+	int i;
+	Node *s, **np;
+	Point p;
+	Rectangle r;
+
+	memset(suc, 0, sizeof suc);
+	p = n2p(n);
+	r = Rect(0, 0, mapwidth, mapheight);
+	for(i=0, np=suc; i<nelem(dtab); i+=2){
+		if(!ptinrect(addpt(p, Pt(dtab[i], dtab[i+1])), r))
+			continue;
+		s = n + dtab[i+1] * mapwidth + dtab[i];
+		assert(s >= map && s < map + mapwidth * mapheight);
+		if(isblocked(s))
+			continue;
+		s->Δg = 1;
+		*np++ = s;
+	}
+	return suc;
+}
+
 static Node *
 dijkstra(Node *a, Node *b)
 {
@@ -68,7 +96,7 @@
 		if(x == b)
 			break;
 		x->closed = 1;
-		if((sl = successors(x)) == nil)
+		if((sl = successors8(x)) == nil)
 			sysfatal("a∗: %r");
 		for(s=*sl++; s!=nil; s=*sl++){
 			if(s->closed)
--- a/path/fns.h
+++ b/path/fns.h
@@ -8,6 +8,7 @@
 void	resetdrw(void);
 double	eucdist(Node*, Node*);
 double	octdist(Node*, Node*);
+double	manhdist(Node*, Node*);
 Vertex	n2p(Node*);
 Node*	p2n(Vertex);
 int	isblocked(Node*);
--- a/path/map.c
+++ b/path/map.c
@@ -45,6 +45,19 @@
 	return 1 * (dx + dy) + MIN(dx, dy) * (SQRT2 - 2 * 1);
 }
 
+double
+manhdist(Node *a, Node *b)
+{
+	int dx, dy;
+	Vertex p, q;
+
+	p = n2p(a);
+	q = n2p(b);
+	dx = abs(p.x - q.x);
+	dy = abs(p.y - q.y);
+	return dx + dy;
+}
+
 int
 isblocked(Node *n)
 {