shithub: sce

Download patch

ref: c0f37dd92b13f2463a38b17e51f5cf26a4a041c0
parent: 47b5c8421d974ddc96a6e38187913d5a53699800
author: qwx <qwx@sciops.net>
date: Fri Nov 19 19:41:18 EST 2021

sim: refactor state machine implementation

- state transitions imply a move, true with any action
- simple move commands just transition back to idle state
- no longer defining action seqs, instead each new state
will set where to transition next to

--- a/dat.h
+++ b/dat.h
@@ -5,7 +5,6 @@
 typedef struct Pics Pics;
 typedef struct Obj Obj;
 typedef struct Path Path;
-typedef struct Action Action;
 typedef struct Command Command;
 typedef struct Munit Munit;
 typedef struct Mresource Mresource;
@@ -189,17 +188,14 @@
 	Mobjl *mapl;
 };
 struct Command{
-	int os;
 	char *name;
-	int (*initfn)(Mobj*);
 	Point goal;
-	vlong arg[4];
-};
-struct Action{
-	int os;
-	char *name;
+	Mobj *target1;
+	Mobj *target2;
+	int (*initfn)(Mobj*);
 	void (*stepfn)(Mobj*);
 	void (*cleanupfn)(Mobj*);
+	void (*nextfn)(Mobj*);
 };
 struct Mobj{
 	Obj *o;
@@ -206,7 +202,6 @@
 	int idx;
 	long uuid;
 	int state;
-	Action *actp;
 	Command cmds[Ncmd];
 	int ctail;
 	Point;
@@ -222,6 +217,7 @@
 	Mobjl *l;
 	Mobjl *lp;
 };
+extern char *statename[OSend];
 
 struct Tile{
 	Pic *p;
--- a/drw.c
+++ b/drw.c
@@ -113,7 +113,7 @@
 		snprint(s, sizeof s, "%s %d/%d", mo->o->name, mo->hp, mo->o->hp);
 	string(screen, p0, display->white, ZP, font, s);
 	if((mo->o->f & Fresource) == 0){
-		snprint(s, sizeof s, "%s", mo->actp!=nil ? mo->actp->name : "idle");
+		snprint(s, sizeof s, "%s", mo->state < OSend ? statename[mo->state] : "");
 		string(screen, addpt(p0, Pt(0,font->height)), display->white, ZP, font, s);
 	}
 }
--- a/fns.h
+++ b/fns.h
@@ -13,8 +13,7 @@
 void	resourcestate(Mobj*);
 void	idlestate(Mobj*);
 Mobj*	derefmobj(int, long);
-void	nextaction(Mobj*);
-int	pushactions(Mobj*, Action*);
+void	nextstate(Mobj*);
 void	clearcommands(Mobj*);
 void	abortcommands(Mobj*);
 void	popcommand(Mobj*);
--- a/sim.c
+++ b/sim.c
@@ -8,6 +8,11 @@
 int nteam;
 int initres[Nresource], foodcap;
 
+char *statename[OSend] = {
+	[OSidle] "idle",
+	[OSmove] "moving",
+};
+
 static Mobjl mobjl0 = {.l = &mobjl0, .lp = &mobjl0}, *mobjl = &mobjl0;
 
 Mobjl *
@@ -59,36 +64,27 @@
 }
 
 void
-nextaction(Mobj *mo)
+nextstate(Mobj *mo)
 {
-	assert(mo->actp != nil);
-	if(mo->actp->cleanupfn != nil)
-		mo->actp->cleanupfn(mo);
-	mo->actp++;
-	if((mo->state = mo->actp->os) == OSskymaybe){
-		dprint("%M nextaction: done\n", mo);
-		mo->actp = nil;
+	Command *c;
+
+	c = mo->cmds;
+	if(c->cleanupfn != nil)
+		c->cleanupfn(mo);
+	if(c->nextfn != nil)
+		c->nextfn(mo);
+	else
 		popcommand(mo);
-		return;
-	}
-	dprint("%M nextaction: %s\n", mo, mo->actp->name);
 }
 
-int
-pushactions(Mobj *mo, Action *a)
-{
-	mo->actp = a;
-	mo->state = a->os;
-	dprint("%M pushaction: %s\n", mo, a->name);
-	return 0;
-}
-
 void
 clearcommands(Mobj *mo)
 {
-	if(mo->actp != nil && mo->actp->cleanupfn != nil)
-		mo->actp->cleanupfn(mo);
-	mo->actp = nil;
+	Command *c;
+
+	c = mo->cmds;
+	if(c->cleanupfn != nil)
+		c->cleanupfn(mo);
 	memset(mo->cmds, 0, sizeof mo->cmds);
 	mo->ctail = 0;
 	idlestate(mo);
@@ -125,6 +121,7 @@
 	c = mo->cmds + mo->ctail++;
 	if(mo->state == OSidle)
 		mo->state = OSskymaybe;
+	memset(c, 0, sizeof *c);
 	return c;
 }
 
@@ -133,13 +130,14 @@
 {
 	Mobjl *ml, *next;
 	Mobj *mo;
+	Command *c;
 
 	for(ml=mobjl->l, next=ml->l; ml!=mobjl; ml=next, next=next->l){
 		mo = ml->mo;
 		if(mo->state == OSidle)
 			continue;
-		if(mo->actp == nil
-		&& (mo->cmds[0].initfn(mo) < 0 || mo->actp == nil || mo->state == OSskymaybe)){
+		c = mo->cmds;
+		if(mo->state == OSskymaybe && c->initfn(mo) < 0){
 			abortcommands(mo);
 			continue;
 		}
@@ -146,7 +144,7 @@
 		if(mo->state == OSskymaybe)
 			sysfatal("updatemobj: %s cmd %s impossible/stale state %d",
 				mo->o->name, mo->cmds[0].name, mo->state);
-		mo->actp->stepfn(mo);
+		c->stepfn(mo);
 	}
 }
 
--- a/sim.move.c
+++ b/sim.move.c
@@ -82,7 +82,7 @@
 movedone(Mobj *mo)
 {
 	dprint("%M successfully reached goal\n", mo);
-	nextaction(mo);
+	nextstate(mo);
 }
 
 static void
@@ -285,40 +285,25 @@
 	}
 }
 
-static Action acts[] = {
-	{
-		.os = OSmove,
-		.name = "moving",
-		.stepfn = step,
-		.cleanupfn = cleanup,
-	},
-	{
-		.os = OSskymaybe,
-	}
-};
-
 int
 newmove(Mobj *mo)
 {
 	Point goal;
-	Mobj *block;
 	Command *c;
 
 	c = mo->cmds;
+	c->cleanupfn = cleanup;
 	goal = c->goal;
-	block = nil;
-	if(c->arg[0] >= 0 && (block = derefmobj(c->arg[0], c->arg[1])) == nil)
-		return -1;
-	setgoal(&goal, mo, block);
+	setgoal(&goal, mo, c->target1);	/* FIXME: target[12] might be a problem for returns */
 	if(repath(goal, mo) < 0)
 		return -1;
-	if(pushactions(mo, acts) < 0)
-		return -1;
+	c->stepfn = step;
+	mo->state = OSmove;
 	return 0;
 }
 
 int
-pushmovecommand(Point goal, Mobj *mo, Mobj *block)
+pushmovecommand(Point goal, Mobj *mo, Mobj *target)
 {
 	Command *c;
 
@@ -326,14 +311,10 @@
 		fprint(2, "pushmovecommand: %r\n");
 		return -1;
 	}
-	c->os = OSmove;
 	c->name = "move";
 	c->initfn = newmove;
 	c->goal = goal;
-	if(block != nil){
-		c->arg[0] = block->idx;
-		c->arg[1] = block->uuid;
-	}else
-		c->arg[0] = -1;
+	c->target1 = target;
+	c->nextfn = nil;
 	return 0;
 }