shithub: asif

Download patch

ref: 672e6e2a22e2b3c94aabd4f591fcc20a7634b93f
parent: dd04e30867a84320194bf9f9f7724c55060e016f
author: qwx <qwx@sciops.net>
date: Sat Jul 16 12:16:17 EDT 2022

path(1): parse gppc pathfinding maps/scenarios for benchmarking

--- a/app/path/client.c
+++ b/app/path/client.c
@@ -52,12 +52,13 @@
 }
 
 void
-init(int w, int h)
+init(char *scen, Vertex v, int m, int a, int d)
 {
 	fmtinstall('P', Pfmt);
 	fmtinstall('R', Rfmt);
 	initfs();
-	initmap(w, h);
+	if(initmap(scen, v, m, a, d) < 0)
+		sysfatal("init: %r");
 	initdrw();
 	if((kc = initkeyboard(nil)) == nil)
 		sysfatal("initkeyboard: %r");
--- a/app/path/fns.h
+++ b/app/path/fns.h
@@ -1,9 +1,10 @@
-void	init(int, int);
+void	init(char*, Vertex, int, int, int);
 Node*	scrselect(Point);
 void	updatedrw(void);
 void	evloop(void);
+int	readscen(char*, Vertex*, int*, int*, int*);
 void	initfs(void);
-void	initmap(int, int);
+int	initmap(char*, Vertex, int, int, int);
 void	initdrw(void);
 void	resetdrw(void);
 Vertex	n2s(Node*);
--- a/app/path/fs.c
+++ b/app/path/fs.c
@@ -1,9 +1,160 @@
 #include <u.h>
 #include <libc.h>
+#include <bio.h>
 #include "asif.h"
 #include "path.h"
 #include "dat.h"
 #include "fns.h"
+
+/* https://bitbucket.org/dharabor/pathfinding/src/gppc/gppc-2014/scenarios/ */
+typedef struct Sim Sim;
+struct Sim{
+	Vertex start;
+	Vertex goal;
+	double dist;
+};
+static VArray *sims;
+
+static int
+readscenmaphdr(Biobuf *bf, Vertex *v)
+{
+	int done;
+	char *s, *t;
+
+	done = 0;
+	while((s = Brdstr(bf, '\n', 1)) != nil){
+		t = strtok(s, " ");
+		if(strcmp(t, "type") == 0){
+			;
+		}else if(strcmp(t, "height") == 0){
+			if((t = strtok(nil, " ")) == nil)
+				return -1;
+			v->y = atoi(t);
+		}else if(strcmp(t, "width") == 0){
+			if((t = strtok(nil, " ")) == nil)
+				return -1;
+			v->x = atoi(t);
+		}else if(strcmp(t, "map") == 0)
+			done = 1;
+		else{
+			werrstr("unknown verb %s", t);
+			return -1;
+		}
+		free(s);
+		if(done)
+			return 0;
+	}
+	return -1;
+}
+
+static int
+readscenmap(char *path, Vertex *v)
+{
+	char c, *s, *t;
+	Vertex u;
+	Biobuf *bf;
+
+	if((bf = Bopen(path, OREAD)) == nil)
+		sysfatal("readscenmap: %r");
+	if(readscenmaphdr(bf, v) < 0)
+		return -1;
+	initgrid(v->x, v->y);
+	for(u.y=0; u.y<gridheight; u.y++){
+		if((s = Brdstr(bf, '\n', 1)) == nil)
+			return -1;
+		for(t=s, u.x=0; (c=*t)!=0; t++, u.x++){
+			switch(c){
+			case 'S':
+			case 'W': 
+			case 'T':
+			case '@':
+			case 'O':
+				toggleblocked(p2n(u));
+				break;
+			}
+		}
+		if(u.x != gridwidth){
+			werrstr("line %d: invalid length %d not %d", u.y+1, u.x, gridwidth);
+			return -1;
+		}
+		free(s);
+	}
+	Bterm(bf);
+	return 0;
+}
+
+static int
+readscenhdr(Biobuf *bf, Vertex *v)
+{
+	int done;
+	char *s, *t;
+
+	done = 0;
+	while((s = Brdstr(bf, '\n', 1)) != nil){
+		t = strtok(s, " ");
+		if(strcmp(t, "type") == 0){
+			;
+		}else if(strcmp(t, "height") == 0){
+			if((t = strtok(nil, " ")) == nil)
+				return -1;
+			v->y = atoi(t);
+		}else if(strcmp(t, "width") == 0){
+			if((t = strtok(nil, " ")) == nil)
+				return -1;
+			v->x = atoi(t);
+		}else if(strcmp(t, "map") == 0)
+			done = 1;
+		else{
+			werrstr("unknown verb %s", t);
+			return -1;
+		}
+		free(s);
+		if(done)
+			return 0;
+	}
+	return -1;
+}
+
+int
+readscen(char *path, Vertex *v, int *m, int *a, int *d)
+{
+	int n;
+	char *s, *arg[32];
+	Biobuf *bf;
+	Sim sim;
+
+	/* only supported benchmarking configuration so far */
+	*d = Doctile;
+	*a = Pa∗;
+	*m = Move8;
+	if((s = strrchr(path, '.')) == nil){
+		werrstr("invalid path name");
+		return -1;
+	}
+	*s = 0;
+	if(readscenmap(path, v) < 0)
+		return -1;
+	*s = '.';
+	if((bf = Bopen(path, OREAD)) == nil)
+		sysfatal("readscen: %r");
+	sims = valloc(4100, sizeof(Sim));
+	free(Brdstr(bf, '\n', 1));	/* "version 1\n" */
+	while((s = Brdstr(bf, '\n', 1)) != nil){
+		if((n = getfields(s, arg, nelem(arg), 1, " \t")) != 9){
+			werrstr("invalid record length %d not 9", n);
+			return -1;
+		}
+		sim.start.x = atoi(arg[4]);
+		sim.start.y =  atoi(arg[5]);
+		sim.goal.x = atoi(arg[6]);
+		sim.goal.y = atoi(arg[7]);
+		sim.dist = strtod(arg[8], nil);
+		vinsert(sims, (char*)&sim);
+		free(s);
+	}
+	Bterm(bf);
+	return 0;
+}
 
 void
 initfs(void)
--- a/app/path/map.c
+++ b/app/path/map.c
@@ -8,6 +8,8 @@
 int movemode;
 int	(*pathfn)(Node*, Node*);
 
+static int gotscen;
+
 Vertex
 n2s(Node *n)
 {
@@ -46,14 +48,29 @@
 void
 clearmap(void)
 {
-	if(grid == nil)
+	start = goal = nil;
+	if(grid == nil || gotscen)
 		return;
 	cleargrid();
-	start = goal = nil;
 }
 
-void
-initmap(int w, int h)
+static void
+defaults(Vertex v)
 {
-	initgrid(w, h);
+	initgrid(v.x, v.y);
+	setparm(Move8, Pa∗, Doctile);
+}
+
+int
+initmap(char *scen, Vertex v, int m, int a, int d)
+{
+	if(scen == nil){
+		defaults(v);
+		return 0;
+	}
+	if(readscen(scen, &v, &m, &a, &d) < 0)
+		sysfatal("readscen: %r");
+	gotscen = 1;
+	setparm(m, a, d);
+	return 0;
 }
--- a/app/path/mkfile
+++ b/app/path/mkfile
@@ -11,6 +11,7 @@
 	../../emalloc.$O\
 	../../pheap.$O\
 	../../vec.$O\
+	../../varray.$O\
 	../../zalloc.$O\
 	client.$O\
 	drw.$O\
--- a/app/path/path.c
+++ b/app/path/path.c
@@ -66,7 +66,7 @@
 static void
 usage(void)
 {
-	fprint(2, "usage: %s [-D4] [-a algo] [-d dist] [-s width[,height]]\n", argv0);
+	fprint(2, "usage: %s [-D4] [-a algo] [-d dist] [-s width[,height]] [-m scen]\n", argv0);
 	threadexits("usage");
 }
 
@@ -74,7 +74,7 @@
 threadmain(int argc, char **argv)
 {
 	int w, h, a, d, m;
-	char *s;
+	char *s, *scen;
 
 	w = 64;
 	h = 64;
@@ -81,6 +81,7 @@
 	a = -1;
 	d = -1;
 	m = Move8;
+	scen = nil;
 	ARGBEGIN{
 	case 'D':
 		if(++debuglevel >= Logparanoid)
@@ -116,6 +117,9 @@
 			usage();
 		}
 		break;
+	case 'm':
+		scen = EARGF(usage());
+		break;
 	case 's':
 		w = strtol(EARGF(usage()), &s, 0);
 		if(w <= 0)
@@ -133,13 +137,12 @@
 	if(w <= 0 || w > 512
 	|| h <= 0 || h > 512)
 		sysfatal("invalid map size, must be in ]0,512]");
-	keyfn = grkey;
-	mousefn = grmouse;
 	if(d < 0)
 		d = m == Move8 ? Doctile : Dmanhattan;
 	if(a < 0)
 		a = Pa∗;
-	setparm(m, a, d);
-	init(w, h);
+	keyfn = grkey;
+	mousefn = grmouse;
+	init(scen, (Vertex){w,h}, m, a, d);
 	evloop();
 }