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();
}