shithub: sce

Download patch

ref: 94f786ad93b4e5f1f3158062f4a0400c6b1b80df
parent: a1c6005292984c6c2c6327cf4f6dfa1b5b2e72cb
author: qwx <qwx@sciops.net>
date: Sat Aug 29 07:38:46 EDT 2020

add acceleration, deceleration and turning speed

halt distance is also there, but unused.
current heuristic for deceleration seems to work alright.

--- a/dat.h
+++ b/dat.h
@@ -48,6 +48,8 @@
 	double g;
 	double Δg;
 	double h;
+	double len;
+	double Δlen;
 	int step;
 	int dir;
 	Node *from;
@@ -98,10 +100,13 @@
 	Attack *atk[2];
 	int hp;
 	int def;
-	int speed;
 	int vis;
 	int cost[Nresource];
 	int time;
+	double speed;
+	double accel;
+	double halt;
+	double turn;
 	Obj **spawn;
 	int nspawn;
 };
@@ -110,6 +115,7 @@
 	int goalblocked;
 	int npatherr;
 	int npathbuf;
+	double pathlen;
 	Point *paths;
 	Point *pathp;
 	Point *pathe;
@@ -117,14 +123,15 @@
 struct Mobj{
 	Obj *o;
 	Pics *pics;
-	int θ;
 	Point;
 	int px;
 	int py;
 	int subpx;
 	int subpy;
+	double θ;
+	double Δθ;
+	int Δθs;
 	Path;
-	int Δθ;
 	double u;
 	double v;
 	double speed;
--- a/drw.c
+++ b/drw.c
@@ -269,9 +269,10 @@
 	Pics *pp;
 	Pic *p;
 
+	θ = mo->θ * 32.0 / 256;
 	pp = mo->pics;
 	switch(pp->nr){
-	case 17: θ = rot17[mo->θ]; break;
+	case 17: θ = rot17[θ]; break;
 	default: θ = 0; break;
 	}
 	if(notshadow){
--- a/fs.c
+++ b/fs.c
@@ -230,6 +230,7 @@
 vunpack(char **fld, char *fmt, va_list a)
 {
 	int n;
+	double d;
 	char *s;
 	Attack *atk;
 	Resource *r;
@@ -244,6 +245,11 @@
 				sysfatal("vunpack: illegal positive integer %d", n);
 			*va_arg(a, int*) = n;
 			break;
+		case 'f':
+			if((d = strtod(*fld++, nil)) < 0.0)
+				sysfatal("vunpack: illegal positive double %f", d);
+			*va_arg(a, double*) = d;
+			break;
 		case 'a':
 			s = *fld++;
 			if(*s == 0){
@@ -389,10 +395,14 @@
 		obj = emalloc(nobj * sizeof *obj);
 	o = obj + tab->row;
 	o->name = estrdup(*fld++);
-	unpack(fld, "dddddddddddaa", &o->f, &o->w, &o->h,
-		&o->hp, &o->def, &o->speed, &o->vis,
+	unpack(fld, "ddddddddddaaffff", &o->f, &o->w, &o->h,
+		&o->hp, &o->def, &o->vis,
 		o->cost, o->cost+1, o->cost+2, &o->time,
-		o->atk, o->atk+1);
+		o->atk, o->atk+1, &o->speed, &o->accel, &o->halt, &o->turn);
+	o->accel /= 256.0;
+	o->halt /= 256.0;
+	/* halting distance in path node units */
+	o->halt /= Tlsubwidth;
 	if(o->w < 1 || o->h < 1)
 		sysfatal("readobj: %s invalid dimensions %d,%d", o->name, o->w, o->h);
 }
@@ -433,7 +443,7 @@
 
 Table table[] = {
 	{"mapobj", readmapobj, 4, &nobjp},
-	{"obj", readobj, 14, &nobj},
+	{"obj", readobj, 17, &nobj},
 	{"attack", readattack, 4, &nattack},
 	{"resource", readresource, 2, &nresource},
 	{"spawn", readspawn, -1, nil},
--- a/map.c
+++ b/map.c
@@ -102,7 +102,7 @@
 	mo->o = o;
 	mo->f = o->f;
 	mo->hp = o->hp;
-	mo->θ = nrand(Nrot);
+	mo->θ = frand() * 256;
 	updatemap(mo);
 	return mo;
 }
--- a/path.c
+++ b/path.c
@@ -155,6 +155,7 @@
 		return nil;
 	if(Δvg == 0 && (Δug < 0) ^ (Δug2 < 0)){
 		b->Δg = steps - abs(Δug2);
+		b->Δlen = b->Δg;
 		return b;
 	}
 	if(end)
@@ -164,6 +165,7 @@
 	n->x = x;
 	n->y = y;
 	n->Δg = steps;
+	n->Δlen = steps;
 	return n;
 }
 
@@ -198,6 +200,7 @@
 	n->x = x;
 	n->y = y;
 	n->Δg = steps;
+	n->Δlen = steps * SQRT2;
 	return n;
 }
 
@@ -343,6 +346,7 @@
 				n->from = x;
 				n->g = g;
 				n->h = octdist(n, b);
+				n->len = x->len + n->Δlen;
 				n->open = 1;
 				n->step = x->step + 1;
 				pushqueue(n, &queue);
@@ -349,6 +353,7 @@
 			}else if(Δg > 0){
 				n->from = x;
 				n->step = x->step + 1;
+				n->len = x->len + n->Δlen;
 				n->g -= Δg;
 				decreasekey(n->p, Δg, &queue);
 			}
@@ -372,6 +377,7 @@
 			mo->npathbuf * sizeof mo->paths);
 		mo->npathbuf = n->step;
 	}
+	mo->pathlen = n->len;
 	p = mo->paths + n->step;
 	mo->pathe = p--;
 	for(; n!=a; n=n->from){
--- a/sce/sce.db
+++ b/sce/sce.db
@@ -5,11 +5,11 @@
 # attack: name, dmg, range, cool
 attack,fusion cutter,5,1,15
 attack,spines,5,1,22
-# obj: name, flags, w, h, hp, def, speed, vis, cost[3], time, attack[2]
-obj,scv,3,4,4,60,0,5,7,1,50,0,20,fusion cutter,
-obj,drone,1,4,4,40,0,5,7,1,50,0,20,spines,
-obj,control,8,16,12,1500,1,0,1,10,400,0,1800,,
-obj,hatchery,8,16,12,1250,1,0,1,10,300,0,1800,,
+# obj: name, flags, w, h, hp, def, vis, cost[3], time, attack[2], speed, accel, halt, turn
+obj,scv,3,4,4,60,0,7,1,50,0,20,fusion cutter,,4.97,67,12227,40
+obj,drone,1,4,4,40,0,7,1,50,0,20,spines,,4.97,67,12227,40
+obj,control,8,16,12,1500,1,1,10,400,0,1800,,,0,0,0,0
+obj,hatchery,8,16,12,1250,1,1,10,300,0,1800,,,0,0,0,0
 # spawn: objname, [obj..]
 spawn,control,scv
 # spr: objname, flags (PF enum), rotations, [frame..]
--- a/sim.c
+++ b/sim.c
@@ -52,11 +52,11 @@
 	markmobj(mo, 1);
 }
 
-static int
+static double
 facemobj(Point p, Mobj *mo)
 {
 	int dx, dy;
-	double vx, vy, θ, d;
+	double vx, vy, d, θ, θ256, Δθ;
 
 	dx = p.x - mo->x;
 	dy = p.y - mo->y;
@@ -63,14 +63,24 @@
 	d = sqrt(dx * dx + dy * dy);
 	vx = dx / d;
 	vy = dy / d;
-	mo->u = vx;
-	mo->v = vy;
+	/* angle in radians [0;2π[ with 0 facing north */
 	θ = atan2(vy, vx) + PI / 2;
 	if(θ < 0)
 		θ += 2 * PI;
 	else if(θ >= 2 * PI)
 		θ -= 2 * PI;
-	return (θ / (2 * PI) * 360) / (90. / (Nrot / 4));
+	/* 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
@@ -85,16 +95,8 @@
 static void
 nextmove(Mobj *mo)
 {
-	int Δθ;
-
 	resetcoords(mo);
-	Δθ = facemobj(*mo->pathp, mo) - mo->θ;
-	if(Δθ <= -Nrot / 2)
-		Δθ += Nrot;
-	else if(Δθ >= Nrot / 2)
-		Δθ -= Nrot;
-	mo->Δθ = Δθ;
-	mo->speed = mo->o->speed;
+	facemobj(*mo->pathp, mo);
 }
 
 static int
@@ -122,6 +124,7 @@
 	}
 	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;
 	}
@@ -144,25 +147,50 @@
 	return 0;
 }
 
-static void
+static int
 tryturn(Mobj *mo)
 {
-	int Δθ;
+	int r;
+	double Δθ;
 
-	if(mo->Δθ < 0)
-		Δθ = mo->Δθ < -2 ? -2 : mo->Δθ;
-	else
-		Δθ = mo->Δθ > 2 ? 2 : mo->Δθ;
-	mo->θ = mo->θ + Δθ & Nrot - 1;
+	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(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, sx, sy, Δx, Δy, Δu, Δv, Δrx, Δry, Δpx, Δpy;
+	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);
@@ -169,8 +197,8 @@
 	Δv = mo->v * (1 << Subpxshift);
 	Δx = abs(Δu);
 	Δy = abs(Δv);
-	Δrx = Δx * mo->speed;
-	Δry = Δy * mo->speed;
+	Δrx = fabs(mo->u * mo->speed) * (1 << Subpxshift);
+	Δry = fabs(mo->v * mo->speed) * (1 << Subpxshift);
 	Δpx = abs((mo->pathp->x * Tlsubwidth << Subpxshift) - sx);
 	Δpy = abs((mo->pathp->y * Tlsubwidth << Subpxshift) - sy);
 	if(Δpx < Δrx)
@@ -213,6 +241,11 @@
 		mo->y = mo->py / Tlsubheight;
 	}
 	markmobj(mo, 1);
+	dx = mo->px - px;
+	dx *= dx;
+	dy = mo->py - py;
+	dy *= dy;
+	mo->pathlen -= sqrt(dx + dy) / Tlsubwidth;
 	return 0;
 end:
 	werrstr("trymove: can't move to %d,%d", x, y);
@@ -219,25 +252,37 @@
 	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) / Tlsubwidth;
 	return -1;
 }
 
+static int
+domove(Mobj *mo)
+{
+	int r;
+
+	updatespeed(mo);
+	unlinkmobj(mo->mapp);
+	r = trymove(mo);
+	linktomap(mo);
+	return r;
+}
+
 static void
 stepmove(Mobj *mo)
 {
-	int r, n;
+	int n;
 
 	n = 0;
 restart:
 	n++;
-	if(mo->Δθ != 0){
-		tryturn(mo);
+	if(tryturn(mo))
 		return;
-	}
-	unlinkmobj(mo->mapp);
-	r = trymove(mo);
-	linktomap(mo);
-	if(r < 0){
+	if(domove(mo) < 0){
 		if(n > 1){
 			fprint(2, "stepmove: %s %#p bug inducing infinite loop!\n",
 				mo->o->name, mo);
@@ -247,6 +292,7 @@
 		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;
@@ -258,6 +304,7 @@
 			return;
 		}else if(mo->x == mo->target.x && mo->y == mo->target.y){
 			mo->npatherr = 0;
+			mo->speed = 0.0;
 			freemove(mo);
 			return;
 		}
@@ -266,6 +313,7 @@
 		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;
 		}
@@ -274,6 +322,7 @@
 			dprint("stepmove: %s %#p trying to find target: %r\n",
 				mo->o->name, mo);
 			mo->npatherr = 0;
+			mo->speed = 0.0;
 			freemove(mo);
 		}
 	}