ref: a23fca93dd914bf618a72579ff644f16cf6f81fd
parent: 0891f6208a02a6b22decb65358e78ca0b61d39ec
author: qwx <[email protected]>
date: Sun Nov 28 18:44:21 EST 2021
sim: add return command and gather-return loop - build a list of drop points when spawning main buildings - implement loop by pushing new commands, simplest and cleanest option - ignore immutable objects like resources from sim state loop - decrement resource amount on successful gather
--- a/com.c
+++ b/com.c
@@ -77,12 +77,10 @@
reqgather(uchar *p, uchar *e)
{
int n;
- Point click;
Mobj reqm, reqt, *mo, *tgt;
- if((n = unpack(p, e, "dldd dd dldd",
+ if((n = unpack(p, e, "dldd dldd",
&reqm.idx, &reqm.uuid, &reqm.x, &reqm.y,
- &click.x, &click.y,
&reqt.idx, &reqt.uuid, &reqt.x, &reqt.y)) < 0)
return -1;
if((mo = mobjfromreq(&reqm)) == nil)
@@ -101,12 +99,8 @@
werrstr("reqgather: target %M not a resource", tgt);
return -1;
}
- if(click.x >= nodemapwidth || click.y >= nodemapheight){
- werrstr("reqgather: invalid location %d,%d", click.x, click.y);
+ if(pushgathercommand(mo, tgt) < 0)
return -1;
- }
- if(pushgathercommand(click, mo, tgt) < 0)
- return -1;
return n;
}
@@ -304,14 +298,13 @@
}
int
-sendgather(Mobj *mo, Point click, Mobj *tgt)
+sendgather(Mobj *mo, Mobj *tgt)
{
Msg *m;
m = getclbuf();
- if(packmsg(m, "h dldd dd dldd", CTgather,
+ if(packmsg(m, "h dldd dldd", CTgather,
mo->idx, mo->uuid, mo->x, mo->y,
- click.x, click.y,
tgt->idx, tgt->uuid, tgt->x, tgt->y) < 0){
fprint(2, "sendgather: %r\n");
return -1;
--- a/dat.h
+++ b/dat.h
@@ -234,6 +234,9 @@
extern Map *map;
extern int mapwidth, mapheight;
+enum{
+ Ngatheramount = 8,
+};
struct Resource{
char *name;
int init;
@@ -251,6 +254,9 @@
Mobj **mo;
int sz;
int firstempty;
+ Mobj **drop;
+ int dropsz;
+ int ndrop;
};
extern Team teams[Nteam];
extern int nteam;
--- a/drw.c
+++ b/drw.c
@@ -95,7 +95,7 @@
sendstop(it);
if(mo != nil){
if((mo->o->f & Fresource) && (it->o->f & Fgather))
- sendgather(it, p, mo);
+ sendgather(it, mo);
else
sendmovenear(it, p, mo);
}else
--- a/fns.h
+++ b/fns.h
@@ -3,7 +3,7 @@
void initnet(char*);
int parsemsg(Msg*);
void endmsg(Msg*);
-int sendgather(Mobj*, Point, Mobj*);
+int sendgather(Mobj*, Mobj*);
int sendmovenear(Mobj*, Point, Mobj*);
int sendstop(Mobj*);
int sendmove(Mobj*, Point);
@@ -11,10 +11,12 @@
void stepsnd(void);
void initsnd(void);
void linktomap(Mobj*);
-int pushgathercommand(Point, Mobj*, Mobj*);
+int pushreturncommand(Mobj*, Mobj*);
+int pushgathercommand(Mobj*, Mobj*);
int pushmove(Mobj*);
int pushmovecommand(Point, Mobj*, Mobj*);
void resourcestate(Mobj*);
+void depleteresource(Mobj*, int);
void freezefrm(Mobj*, int);
void idlestate(Mobj*);
Mobj* derefmobj(int, long);
@@ -21,7 +23,6 @@
void nextstate(Mobj*);
void clearcommands(Mobj*);
void abortcommands(Mobj*);
-void popcommand(Mobj*);
Command* pushcommand(Mobj*);
Mobjl* linkmobj(Mobjl*, Mobj*, Mobjl*);
void unlinkmobj(Mobjl*);
@@ -42,6 +43,7 @@
void drawfb(void);
void initimg(void);
void initfs(void);
+double octdist(Node*, Node*);
void setgoal(Point*, Mobj*, Mobj*);
Mobj* unitat(int, int);
int isblocked(int, int, Obj*);
--- a/mkfile
+++ b/mkfile
@@ -16,6 +16,7 @@
sim.idle.$O\
sim.move.$O\
sim.resource.$O\
+ sim.return.$O\
sim.spawn.$O\
snd.$O\
sv.$O\
--- a/path.c
+++ b/path.c
@@ -130,7 +130,7 @@
return sqrt(dx * dx + dy * dy);
}
-static double
+double
octdist(Node *a, Node *b)
{
int dx, dy;
--- a/sim.c
+++ b/sim.c
@@ -62,25 +62,17 @@
if(t->mo[i] == nil)
break;
t->firstempty = i;
+ if(mo->o->nspawn > 0){
+ assert(mo->o->spawn != nil);
+ if(t->ndrop == t->dropsz){
+ t->drop = erealloc(t->drop, (t->dropsz + 32) * sizeof *t->drop, t->dropsz * sizeof *t->drop);
+ t->dropsz += 32;
+ }
+ t->drop[t->ndrop++] = mo;
+ }
}
void
-nextstate(Mobj *mo)
-{
- Command *c;
-
- c = mo->cmds;
- if(c->cleanupfn != nil)
- c->cleanupfn(mo);
- if(c->nextfn != nil){
- c->initfn = c->nextfn;
- freezefrm(mo, mo->state);
- mo->state = OSskymaybe; /* FIXME: kind of overloading this just for drw.c */
- }else
- popcommand(mo);
-}
-
-void
clearcommands(Mobj *mo)
{
Command *c;
@@ -96,11 +88,11 @@
void
abortcommands(Mobj *mo)
{
- dprint("%M abortcommand: %s\n", mo, mo->cmds[0].name);
+ dprint("%M abortcommand: %s: %r\n", mo, mo->cmds[0].name);
clearcommands(mo);
}
-void
+static void
popcommand(Mobj *mo)
{
dprint("%M popcommand: %s\n", mo, mo->cmds[0].name);
@@ -128,6 +120,22 @@
return c;
}
+void
+nextstate(Mobj *mo)
+{
+ Command *c;
+
+ c = mo->cmds;
+ if(c->cleanupfn != nil)
+ c->cleanupfn(mo);
+ if(c->nextfn != nil){
+ c->initfn = c->nextfn;
+ freezefrm(mo, mo->state);
+ mo->state = OSskymaybe; /* FIXME: kind of overloading this just for drw.c */
+ }else
+ popcommand(mo);
+}
+
static void
updatemobj(void)
{
@@ -137,7 +145,7 @@
for(ml=mobjl->l, next=ml->l; ml!=mobjl; ml=next, next=next->l){
mo = ml->mo;
- if(mo->state == OSidle)
+ if(mo->state == OSidle || mo->o->f & Fimmutable)
continue;
c = mo->cmds;
if(mo->state == OSskymaybe && c->initfn(mo) < 0){
--- a/sim.gather.c
+++ b/sim.gather.c
@@ -10,7 +10,6 @@
enum{
Twait = 8,
Tgather = 75, /* FIXME: 37 for gas, define in db? */
- Namount = 8,
};
static void
@@ -19,18 +18,6 @@
}
static void
-returncargo(Mobj *mo)
-{
- Resource *r;
- Command *c;
-
- c = mo->cmds;
- r = c->target1->o->res;
- assert(r != nil);
- teams[mo->team].r[r-resources] += Namount;
-}
-
-static void
waitstep(Mobj *mo)
{
Command *c;
@@ -38,11 +25,13 @@
c = mo->cmds;
if(--c->tc > 0)
return;
+ depleteresource(c->target1, Ngatheramount);
+ pushreturncommand(mo, c->target1);
nextstate(mo);
}
static void
-step(Mobj *mo)
+gatherstep(Mobj *mo)
{
Command *c;
@@ -49,7 +38,6 @@
c = mo->cmds;
if(++c->tc < Tgather)
return;
- returncargo(mo);
mo->state = OSwait;
c->stepfn = waitstep;
c->tc = nrand(Twait+1);
@@ -63,8 +51,9 @@
c = mo->cmds;
/* FIXME: check if resource still exists? (and amount >0) (needs despawning/death) */
c->cleanupfn = cleanup;
- c->stepfn = step;
- c->nextfn = pushgather;
+ c->stepfn = gatherstep;
+ c->nextfn = nil;
+ c->goal = c->target1->Point;
c->tc = 0;
mo->state = OSgather;
return 0;
@@ -71,10 +60,14 @@
}
int
-pushgathercommand(Point goal, Mobj *mo, Mobj *target)
+pushgathercommand(Mobj *mo, Mobj *tgt)
{
Command *c;
+ if(tgt == nil){
+ dprint("pushgathercommand: no target\n");
+ return -1;
+ }
if((c = pushcommand(mo)) == nil){
fprint(2, "pushmovecommand: %r\n");
return -1;
@@ -81,8 +74,8 @@
}
c->name = "gather";
c->initfn = pushmove;
- c->goal = goal;
- c->target1 = target;
+ c->target1 = tgt;
+ c->goal = tgt->Point;
c->nextfn = pushgather;
return 0;
}
--- a/sim.resource.c
+++ b/sim.resource.c
@@ -16,3 +16,11 @@
break;
mo->state = os;
}
+
+void
+depleteresource(Mobj *mo, int n)
+{
+ /* FIXME: despawn when getting to 0 */
+ mo->amount -= n;
+ resourcestate(mo);
+}
--- /dev/null
+++ b/sim.return.c
@@ -1,0 +1,95 @@
+#include <u.h>
+#include <libc.h>
+#include <draw.h>
+#include "dat.h"
+#include "fns.h"
+
+enum{
+ Twait = 8,
+};
+
+static void
+cleanup(Mobj *)
+{
+}
+
+static void
+waitstep(Mobj *mo)
+{
+ Resource *r;
+ Command *c;
+
+ c = mo->cmds;
+ if(--c->tc > 0)
+ return;
+ r = c->target2->o->res;
+ assert(r != nil);
+ teams[mo->team].r[r-resources] += Ngatheramount;
+ pushgathercommand(mo, c->target2);
+ nextstate(mo);
+}
+
+static int
+pushdrop(Mobj *mo)
+{
+ Command *c;
+
+ c = mo->cmds;
+ c->cleanupfn = cleanup;
+ c->nextfn = nil;
+ c->stepfn = waitstep;
+ c->tc = nrand(Twait+1);
+ mo->state = OSwait;
+ return 0;
+}
+
+static Mobj *
+finddrop(Mobj *mo)
+{
+ double d, d´;
+ Team *t;
+ Mobj *wo, *w, **wp;
+ Node *a, *b;
+
+ t = teams + mo->team;
+ if(t->ndrop <= 0){
+ werrstr("no drops");
+ return nil;
+ }
+ assert(t->drop != nil);
+ a = nodemap + mo->y * nodemapwidth + mo->x;
+ a->x = mo->x;
+ a->y = mo->y;
+ d = nodemapwidth * nodemapheight;
+ for(wp=t->drop, wo=nil; wp<t->drop+t->ndrop; t++){
+ w = *wp;
+ b = nodemap + w->y * nodemapwidth + w->x;
+ b->x = w->x;
+ b->y = w->y;
+ d´ = octdist(a, b);
+ if(d´ < d){
+ wo = w;
+ d = d´;
+ }
+ }
+ return wo;
+}
+
+int
+pushreturncommand(Mobj *mo, Mobj *ro)
+{
+ Command *c;
+
+ if((c = pushcommand(mo)) == nil){
+ fprint(2, "pushmovecommand: %r\n");
+ return -1;
+ }
+ if((c->target1 = finddrop(mo)) == nil)
+ return -1;
+ c->name = "return";
+ c->initfn = pushmove;
+ c->goal = c->target1->Point;
+ c->target2 = ro;
+ c->nextfn = pushdrop;
+ return 0;
+}