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