shithub: sce

Download patch

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