ref: 10cff16795c01635a868ec5d09beb587df4edb79
parent: 59162f80b7b16674f701d3a9bbdf257761a9f753
author: qwx <qwx@sciops.net>
date: Tue Jul 27 22:26:19 EDT 2021
sim: split moving logic
--- a/fns.h
+++ b/fns.h
@@ -8,8 +8,11 @@
int sendpause(void);
void stepsnd(void);
void initsnd(void);
+void updatemoves(void);
void linktomap(Mobj*);
int moveone(Point, Mobj*, Mobj*);
+Mobjl* linkmobj(Mobjl*, Mobj*, Mobjl*);
+void unlinkmobj(Mobjl*);
void stepsim(void);
void initsim(void);
void initsv(int, char*);
--- a/mkfile
+++ b/mkfile
@@ -12,6 +12,7 @@
pheap.$O\
sce.$O\
sim.$O\
+ sim.move.$O\
snd.$O\
sv.$O\
util.$O\
--- a/sim.c
+++ b/sim.c
@@ -1,6 +1,5 @@
#include <u.h>
#include <libc.h>
-#include <thread.h>
#include <draw.h>
#include "dat.h"
#include "fns.h"
@@ -9,9 +8,7 @@
int nteam;
int initres[Nresource], foodcap;
-static Mobjl moving0 = {.l = &moving0, .lp = &moving0}, *moving = &moving0;
-
-static Mobjl *
+Mobjl *
linkmobj(Mobjl *l, Mobj *mo, Mobjl *p)
{
if(p == nil)
@@ -24,7 +21,7 @@
return p;
}
-static void
+void
unlinkmobj(Mobjl *ml)
{
if(ml == nil || ml->l == nil || ml->lp == nil)
@@ -34,15 +31,6 @@
ml->lp = ml->l = nil;
}
-void
-linktomap(Mobj *mo)
-{
- Map *m;
-
- m = map + mo->y / Node2Tile * mapwidth + mo->x / Node2Tile;
- mo->mobjl = linkmobj(mo->o->f & Fair ? m->ml.lp : &m->ml, mo, mo->mobjl);
-}
-
static void
refmobj(Mobj *mo)
{
@@ -67,92 +55,7 @@
t->firstempty = i;
}
-static void
-resetcoords(Mobj *mo)
-{
- markmobj(mo, 0);
- mo->subpx = mo->px << Subpxshift;
- mo->subpy = mo->py << Subpxshift;
- markmobj(mo, 1);
-}
-
-static double
-facemobj(Point p, Mobj *mo)
-{
- int dx, dy;
- double vx, vy, d, θ, θ256, Δθ;
-
- dx = p.x - mo->px;
- dy = p.y - mo->py;
- d = sqrt(dx * dx + dy * dy);
- vx = dx / d;
- vy = dy / d;
- /* angle in radians [0;2π[ with 0 facing north */
- θ = atan2(vy, vx) + PI / 2;
- if(θ < 0)
- θ += 2 * PI;
- else if(θ >= 2 * PI)
- θ -= 2 * PI;
- /* movement calculations use values in [0;256[, drawing in [0;32[ */
- θ256 = θ * 256.0 / (2 * PI);
- mo->u = vx;
- mo->v = vy;
- Δθ = θ256 - mo->θ;
- if(Δθ <= -256 / 2)
- Δθ += 256;
- else if(Δθ >= 256 / 2)
- Δθ -= 256;
- mo->Δθs = Δθ < 0 ? -1: 1;
- mo->Δθ = fabs(Δθ);
- return θ256;
-}
-
-static void
-freemove(Mobj *mo)
-{
- unlinkmobj(mo->movingp);
- mo->pathp = nil;
- mo->freezefrm = tc % mo->o->pics[mo->state][PTbase].nf;
- mo->state = OSidle;
- resetcoords(mo);
-}
-
-static void
-nextmove(Mobj *mo)
-{
- resetcoords(mo);
- facemobj(*mo->pathp, mo);
-}
-
-static int
-repath(Point p, Mobj *mo)
-{
- freemove(mo);
- mo->target = p;
- if(findpath(p, mo) < 0){
- mo->θ = facemobj(p, mo);
- return -1;
- }
- mo->movingp = linkmobj(moving, mo, mo->movingp);
- mo->pathp = mo->paths;
- mo->state = OSmove;
- nextmove(mo);
- return 0;
-}
-
int
-moveone(Point p, Mobj *mo, Mobj *block)
-{
- setgoal(&p, mo, block);
- if(repath(p, mo) < 0){
- mo->speed = 0.0;
- dprint("move to %d,%d: %r\n", p.x, p.y);
- return -1;
- }
- return 0;
-}
-
-int
spawnunit(int x, int y, Obj *o, int team)
{
Mobj *mo;
@@ -197,194 +100,10 @@
return 0;
}
-static int
-tryturn(Mobj *mo)
-{
- int r;
- double Δθ;
-
- r = 1;
- if(mo->Δθ <= mo->o->turn){
- r = 0;
- Δθ = mo->Δθ;
- }else
- Δθ = mo->o->turn;
- mo->θ += mo->Δθs * Δθ;
- if(mo->θ < 0)
- mo->θ += 256;
- else if(mo->θ >= 256)
- mo->θ -= 256;
- mo->Δθ -= Δθ;
- return r;
-}
-
-static void
-updatespeed(Mobj *mo)
-{
- if(1 + mo->pathlen < (mo->speed / 8) * (mo->speed / 8) / 2 / (mo->o->accel / 8)){
- mo->speed -= mo->o->accel;
- if(mo->speed < 0.0)
- mo->speed = 0.0;
- }else if(mo->speed < mo->o->speed){
- mo->speed += mo->o->accel;
- if(mo->speed > mo->o->speed)
- mo->speed = mo->o->speed;
- }
-}
-
-static int
-trymove(Mobj *mo)
-{
- int x, y, px, py, sx, sy, Δx, Δy, Δu, Δv, Δrx, Δry, Δpx, Δpy;
- double dx, dy;
-
- markmobj(mo, 0);
- px = mo->px;
- py = mo->py;
- sx = mo->subpx;
- sy = mo->subpy;
- Δu = mo->u * (1 << Subpxshift);
- Δv = mo->v * (1 << Subpxshift);
- Δx = abs(Δu);
- Δy = abs(Δv);
- Δrx = fabs(mo->u * mo->speed) * (1 << Subpxshift);
- Δry = fabs(mo->v * mo->speed) * (1 << Subpxshift);
- Δpx = abs((mo->pathp->x << Subpxshift) - sx);
- Δpy = abs((mo->pathp->y << Subpxshift) - sy);
- if(Δpx < Δrx)
- Δrx = Δpx;
- if(Δpy < Δry)
- Δry = Δpy;
- while(Δrx > 0 || Δry > 0){
- x = mo->x;
- y = mo->y;
- if(Δrx > 0){
- sx += Δu;
- Δrx -= Δx;
- if(Δrx < 0)
- sx += mo->u < 0 ? -Δrx : Δrx;
- x = (sx >> Subpxshift) + ((sx & Subpxmask) != 0);
- x /= Nodewidth;
- }
- if(Δry > 0){
- sy += Δv;
- Δry -= Δy;
- if(Δry < 0)
- sy += mo->v < 0 ? -Δry : Δry;
- y = (sy >> Subpxshift) + ((sy & Subpxmask) != 0);
- y /= Nodewidth;
- }
- if(isblocked(x, y, mo->o))
- goto end;
- /* disallow corner coasting */
- if(x != mo->x && y != mo->y
- && (isblocked(x, mo->y, mo->o) || isblocked(mo->x, y, mo->o))){
- dprint("detected corner coasting %d,%d vs %d,%d\n",
- x, y, mo->x, mo->y);
- goto end;
- }
- mo->subpx = sx;
- mo->subpy = sy;
- mo->px = sx >> Subpxshift;
- mo->py = sy >> Subpxshift;
- mo->x = mo->px / Nodewidth;
- mo->y = mo->py / Nodeheight;
- }
- markmobj(mo, 1);
- dx = mo->px - px;
- dx *= dx;
- dy = mo->py - py;
- dy *= dy;
- mo->pathlen -= sqrt(dx + dy) / Nodewidth;
- return 0;
-end:
- werrstr("trymove: can't move to %d,%d", x, y);
- mo->subpx = mo->px << Subpxshift;
- mo->subpy = mo->py << Subpxshift;
- markmobj(mo, 1);
- dx = mo->px - px;
- dx *= dx;
- dy = mo->py - py;
- dy *= dy;
- mo->pathlen -= sqrt(dx + dy) / Nodewidth;
- return -1;
-}
-
-static int
-domove(Mobj *mo)
-{
- int r;
-
- updatespeed(mo);
- unlinkmobj(mo->mobjl);
- r = trymove(mo);
- linktomap(mo);
- return r;
-}
-
-static void
-stepmove(Mobj *mo)
-{
- int n;
-
- n = 0;
-restart:
- n++;
- if(tryturn(mo))
- return;
- if(domove(mo) < 0){
- if(n > 1){
- fprint(2, "stepmove: %s %#p bug inducing infinite loop!\n",
- mo->o->name, mo);
- return;
- }
- dprint("stepmove: failed to move: %r\n");
- if(repath(mo->target, mo) < 0){
- dprint("stepmove: %s %#p moving towards target: %r\n",
- mo->o->name, mo);
- mo->speed = 0.0;
- return;
- }
- goto restart;
- }
- if(mo->px == mo->pathp->x && mo->py == mo->pathp->y){
- mo->pathp++;
- if(mo->pathp < mo->pathe){
- nextmove(mo);
- return;
- }else if(mo->x == mo->target.x && mo->y == mo->target.y){
- mo->npatherr = 0;
- mo->speed = 0.0;
- freemove(mo);
- return;
- }
- dprint("stepmove: %s %#p reached final node, but not target\n",
- mo->o->name, mo);
- if(mo->goalblocked && isblocked(mo->target.x, mo->target.y, mo->o)){
- dprint("stepmove: %s %#p goal still blocked, stopping\n",
- mo->o->name, mo);
- mo->speed = 0.0;
- freemove(mo);
- return;
- }
- if(mo->npatherr++ > 1
- || repath(mo->target, mo) < 0){
- dprint("stepmove: %s %#p trying to find target: %r\n",
- mo->o->name, mo);
- mo->npatherr = 0;
- mo->speed = 0.0;
- freemove(mo);
- }
- }
-}
-
void
stepsim(void)
{
- Mobjl *ml, *oml;
-
- for(oml=moving->l, ml=oml->l; oml!=moving; oml=ml, ml=ml->l)
- stepmove(oml->mo);
+ updatemoves();
}
void
--- /dev/null
+++ b/sim.move.c
@@ -1,0 +1,291 @@
+#include <u.h>
+#include <libc.h>
+#include <draw.h>
+#include "dat.h"
+#include "fns.h"
+
+static Mobjl moving0 = {.l = &moving0, .lp = &moving0}, *moving = &moving0;
+
+void
+linktomap(Mobj *mo)
+{
+ Map *m;
+
+ m = map + mo->y / Node2Tile * mapwidth + mo->x / Node2Tile;
+ mo->mobjl = linkmobj(mo->o->f & Fair ? m->ml.lp : &m->ml, mo, mo->mobjl);
+}
+
+static void
+resetcoords(Mobj *mo)
+{
+ markmobj(mo, 0);
+ mo->subpx = mo->px << Subpxshift;
+ mo->subpy = mo->py << Subpxshift;
+ markmobj(mo, 1);
+}
+
+static double
+facemobj(Point p, Mobj *mo)
+{
+ int dx, dy;
+ double vx, vy, d, θ, θ256, Δθ;
+
+ dx = p.x - mo->px;
+ dy = p.y - mo->py;
+ d = sqrt(dx * dx + dy * dy);
+ vx = dx / d;
+ vy = dy / d;
+ /* angle in radians [0;2π[ with 0 facing north */
+ θ = atan2(vy, vx) + PI / 2;
+ if(θ < 0)
+ θ += 2 * PI;
+ else if(θ >= 2 * PI)
+ θ -= 2 * PI;
+ /* movement calculations use values in [0;256[, drawing in [0;32[ */
+ θ256 = θ * 256.0 / (2 * PI);
+ mo->u = vx;
+ mo->v = vy;
+ Δθ = θ256 - mo->θ;
+ if(Δθ <= -256 / 2)
+ Δθ += 256;
+ else if(Δθ >= 256 / 2)
+ Δθ -= 256;
+ mo->Δθs = Δθ < 0 ? -1: 1;
+ mo->Δθ = fabs(Δθ);
+ return θ256;
+}
+
+static void
+freemove(Mobj *mo)
+{
+ unlinkmobj(mo->movingp);
+ mo->pathp = nil;
+ mo->freezefrm = tc % mo->o->pics[mo->state][PTbase].nf;
+ mo->state = OSidle;
+ resetcoords(mo);
+}
+
+static void
+nextmove(Mobj *mo)
+{
+ resetcoords(mo);
+ facemobj(*mo->pathp, mo);
+}
+
+static int
+repath(Point p, Mobj *mo)
+{
+ freemove(mo);
+ mo->target = p;
+ if(findpath(p, mo) < 0){
+ mo->θ = facemobj(p, mo);
+ return -1;
+ }
+ mo->movingp = linkmobj(moving, mo, mo->movingp);
+ mo->pathp = mo->paths;
+ mo->state = OSmove;
+ nextmove(mo);
+ return 0;
+}
+
+int
+moveone(Point p, Mobj *mo, Mobj *block)
+{
+ setgoal(&p, mo, block);
+ if(repath(p, mo) < 0){
+ mo->speed = 0.0;
+ dprint("move to %d,%d: %r\n", p.x, p.y);
+ return -1;
+ }
+ return 0;
+}
+
+static int
+tryturn(Mobj *mo)
+{
+ int r;
+ double Δθ;
+
+ r = 1;
+ if(mo->Δθ <= mo->o->turn){
+ r = 0;
+ Δθ = mo->Δθ;
+ }else
+ Δθ = mo->o->turn;
+ mo->θ += mo->Δθs * Δθ;
+ if(mo->θ < 0)
+ mo->θ += 256;
+ else if(mo->θ >= 256)
+ mo->θ -= 256;
+ mo->Δθ -= Δθ;
+ return r;
+}
+
+static void
+updatespeed(Mobj *mo)
+{
+ if(1 + mo->pathlen < (mo->speed / 8) * (mo->speed / 8) / 2 / (mo->o->accel / 8)){
+ mo->speed -= mo->o->accel;
+ if(mo->speed < 0.0)
+ mo->speed = 0.0;
+ }else if(mo->speed < mo->o->speed){
+ mo->speed += mo->o->accel;
+ if(mo->speed > mo->o->speed)
+ mo->speed = mo->o->speed;
+ }
+}
+
+static int
+trymove(Mobj *mo)
+{
+ int x, y, px, py, sx, sy, Δx, Δy, Δu, Δv, Δrx, Δry, Δpx, Δpy;
+ double dx, dy;
+
+ markmobj(mo, 0);
+ px = mo->px;
+ py = mo->py;
+ sx = mo->subpx;
+ sy = mo->subpy;
+ Δu = mo->u * (1 << Subpxshift);
+ Δv = mo->v * (1 << Subpxshift);
+ Δx = abs(Δu);
+ Δy = abs(Δv);
+ Δrx = fabs(mo->u * mo->speed) * (1 << Subpxshift);
+ Δry = fabs(mo->v * mo->speed) * (1 << Subpxshift);
+ Δpx = abs((mo->pathp->x << Subpxshift) - sx);
+ Δpy = abs((mo->pathp->y << Subpxshift) - sy);
+ if(Δpx < Δrx)
+ Δrx = Δpx;
+ if(Δpy < Δry)
+ Δry = Δpy;
+ while(Δrx > 0 || Δry > 0){
+ x = mo->x;
+ y = mo->y;
+ if(Δrx > 0){
+ sx += Δu;
+ Δrx -= Δx;
+ if(Δrx < 0)
+ sx += mo->u < 0 ? -Δrx : Δrx;
+ x = (sx >> Subpxshift) + ((sx & Subpxmask) != 0);
+ x /= Nodewidth;
+ }
+ if(Δry > 0){
+ sy += Δv;
+ Δry -= Δy;
+ if(Δry < 0)
+ sy += mo->v < 0 ? -Δry : Δry;
+ y = (sy >> Subpxshift) + ((sy & Subpxmask) != 0);
+ y /= Nodewidth;
+ }
+ if(isblocked(x, y, mo->o))
+ goto end;
+ /* disallow corner coasting */
+ if(x != mo->x && y != mo->y
+ && (isblocked(x, mo->y, mo->o) || isblocked(mo->x, y, mo->o))){
+ dprint("detected corner coasting %d,%d vs %d,%d\n",
+ x, y, mo->x, mo->y);
+ goto end;
+ }
+ mo->subpx = sx;
+ mo->subpy = sy;
+ mo->px = sx >> Subpxshift;
+ mo->py = sy >> Subpxshift;
+ mo->x = mo->px / Nodewidth;
+ mo->y = mo->py / Nodeheight;
+ }
+ markmobj(mo, 1);
+ dx = mo->px - px;
+ dx *= dx;
+ dy = mo->py - py;
+ dy *= dy;
+ mo->pathlen -= sqrt(dx + dy) / Nodewidth;
+ return 0;
+end:
+ werrstr("trymove: can't move to %d,%d", x, y);
+ mo->subpx = mo->px << Subpxshift;
+ mo->subpy = mo->py << Subpxshift;
+ markmobj(mo, 1);
+ dx = mo->px - px;
+ dx *= dx;
+ dy = mo->py - py;
+ dy *= dy;
+ mo->pathlen -= sqrt(dx + dy) / Nodewidth;
+ return -1;
+}
+
+static int
+domove(Mobj *mo)
+{
+ int r;
+
+ updatespeed(mo);
+ unlinkmobj(mo->mobjl);
+ r = trymove(mo);
+ linktomap(mo);
+ return r;
+}
+
+static void
+stepmove(Mobj *mo)
+{
+ int n;
+
+ n = 0;
+restart:
+ n++;
+ if(tryturn(mo))
+ return;
+ if(domove(mo) < 0){
+ if(n > 1){
+ fprint(2, "stepmove: %s %#p bug inducing infinite loop!\n",
+ mo->o->name, mo);
+ return;
+ }
+ dprint("stepmove: failed to move: %r\n");
+ if(repath(mo->target, mo) < 0){
+ dprint("stepmove: %s %#p moving towards target: %r\n",
+ mo->o->name, mo);
+ mo->speed = 0.0;
+ return;
+ }
+ goto restart;
+ }
+ if(mo->px == mo->pathp->x && mo->py == mo->pathp->y){
+ mo->pathp++;
+ if(mo->pathp < mo->pathe){
+ nextmove(mo);
+ return;
+ }else if(mo->x == mo->target.x && mo->y == mo->target.y){
+ mo->npatherr = 0;
+ mo->speed = 0.0;
+ freemove(mo);
+ return;
+ }
+ dprint("stepmove: %s %#p reached final node, but not target\n",
+ mo->o->name, mo);
+ if(mo->goalblocked && isblocked(mo->target.x, mo->target.y, mo->o)){
+ dprint("stepmove: %s %#p goal still blocked, stopping\n",
+ mo->o->name, mo);
+ mo->speed = 0.0;
+ freemove(mo);
+ return;
+ }
+ if(mo->npatherr++ > 1
+ || repath(mo->target, mo) < 0){
+ dprint("stepmove: %s %#p trying to find target: %r\n",
+ mo->o->name, mo);
+ mo->npatherr = 0;
+ mo->speed = 0.0;
+ freemove(mo);
+ }
+ }
+}
+
+void
+updatemoves(void)
+{
+ Mobjl *ml, *oml;
+
+ for(oml=moving->l, ml=oml->l; oml!=moving; oml=ml, ml=ml->l)
+ stepmove(oml->mo);
+}