#include "c_includ.h" /* * cbzone_move.c * -- Todd W Mummert, December 1990, CMU * * RCS Info * $Header: c_move.c,v 1.1 91/01/12 02:03:35 mummert Locked $ * * This file is largely based on the Fortran source by * Justin S Revenaugh. I've added the necessary information * to handle multiple objects in placeobjects, but that's * about it. Moved any variables that were controlling * an object that had to be static into the Generic structure. */ void placeobjects(o, missilerun, score) Genericp o; Bool missilerun; LONG score; { static int lander = 1000; static int landercount = 0; static struct timeval clock = {0, 40000}; float odds, scale, r, dazm, ca, sa; Genericp g; Genericp pl = o; int nta = 0; int nsu = 0; int nmi = 0; int nco = 0; int nla = 0; landercount++; for (g=o; gmobjects; g++) if (g->attr & STILL_THERE) switch (g->type) { case IS_TANK: nta++; break; case IS_SUPER: nsu++; break; case IS_MISSILE: nmi++; break; case IS_COPTER: nco++; break; case IS_LANDER: nla++; break; } if (pl->attr & IS_ALIVE && (missilerun && nta + nsu == 0 && nmi + nco < opt->mmissiles || !missilerun && nmi + nco == 0 && nta + nsu < opt->mtanks)) { for (g=o+opt->estart; glstart; g++) if (!(g->attr & STILL_THERE)) break; if (g == o+opt->lstart) { printf("Help! Did not have space available for enemy!\n"); printf("Should not have been possible.\n"); #ifdef WIN32 return; #else //X11 exit(1); #endif } if (missilerun) { /* reset clock usec just in case they change select to return the amount of time remaining after the select finishes. The man page mentions this might occur in future releases. */ tonetime(); clock.tv_usec = 40000; select(0, 0, 0, 0, &clock); tonetime(); clock.tv_usec = 40000; select(0, 0, 0, 0, &clock); tonetime(); odds = score / 500000.0; if (score < 75000) odds = 0.0; if (odds > 0.333) odds = 0.333; if (opt->copters || frand() < odds) { g->type = IS_COPTER; g->lntype = LN_COPTER; scale = 0.2; g->z = 150.0; r = 1900; } else { g->type = IS_MISSILE; g->lntype = LN_MISSILE; scale = 0.1; g->z = 250.0; r = 1750; } dazm = frand() * scale; if (frand() > 0.5) dazm = - dazm; dazm += pl->azm; ca = cos(dazm); sa = sin(dazm); g->x = pl->x - r * sa; g->y = pl->y + r * ca; g->attr = START_LIVING; dazm = frand() * 0.015 / scale; if (frand() > 0.5) dazm = - dazm; g->azm = pl->azm - PI + dazm; } else { odds = (60000.0 - score) / 30000.0; if (odds < 0.10) odds = 0.10; if (frand() < odds) { g->type = IS_TANK; g->lntype = LN_TANK; } else { g->type = IS_SUPER; g->lntype = LN_SUPER; } r = 800.0 + 1200.0 * frand(); dazm = frand() * PI2; g->x = pl->x + r * cos(dazm); g->y = pl->y + r * sin(dazm); g->z = 0.0; g->azm = frand() * PI2; g->attr = START_LIVING; } g->criticalx = 45.0; g->criticaly = 70.0; } if (landercount > lander && nla < opt->mlanders) { for (g=o+opt->lstart; gsstart; g++) if (!(g->attr & STILL_THERE)) break; if (g == o+opt->sstart) { printf("Help! Did not have space available for lander!\n"); printf("Should not have been possible.\n"); #ifdef WIN32 return; #else //X11 exit(1); #endif } r = 1500.0 + 500.0 * frand(); dazm = frand() * PI2; g->x = pl->x + r * cos(dazm); g->y = pl->y + r * sin(dazm); g->z = 0.0; g->azm = frand() * PI2; g->speed = frand() * 10.0; g->criticalx = g->criticaly = 6400.0; g->type = IS_LANDER; g->lntype = LN_LANDER; g->attr = START_LIVING; } for (g=o+opt->bstart; gmobjects; g++) if (!(g->attr & IS_ALIVE)) { if (frand() > 0.5) { g->type = IS_CUBE; g->lntype = LN_CUBE; g->criticalx = g->criticaly = 50.0; } else { g->type = IS_PYRAMID; g->lntype = LN_PYRAMID; g->criticalx = g->criticaly = 35.0; } g->attr = START_LIVING; if (pl->attr & IS_NEW) r = 400 + frand() * 1800.0; else r = 2000.0; dazm = frand() * PI2; g->x = pl->x + r * cos(dazm); g->y = pl->y + r * sin(dazm); g->z = 0.0; } } void movesuper(g, pl) Genericp g; Genericp pl; { int i; float dx, dy, tazm, t1, t3, scrot, sctot, scale, cp, sp, dcp; float dsp, cm, sm, xmt, ymt, xpt, ypt, rate, temp, dist; Genericp s; g->pcount++; g->fcount++; if (g->attr & IS_NEW) { g->attr &= ~(IS_NEW | IS_PRESET); g->bcount = 0; g->ecount = 0; g->pcount = 10; g->fcount = 15; g->orientation = 1.0; } if (g->attr & IS_BLOCKED && g->attr & LAST_BLOCKED) g->orientation = -g->orientation; g->attr &= ~LAST_BLOCKED; if (g->attr & IS_BLOCKED) { if (g->attr & BLOCKED_BY_ENEMY) g->attr |= IS_EVADING; else g->attr &= ~IS_EVADING; g->attr |= IS_PRESET | LAST_BLOCKED; g->bcount = 0; } if (g->attr & IS_PRESET) { g->bcount++; if (!(g->attr & IS_EVADING)) { if (g->bcount == 1) { g->speed = -12.0 * g->orientation; g->rotate = 0.045; if (frand() > 0.5) g->rotate = -g->rotate; } else if (g->bcount == 30) { g->speed = 12.0 * g->orientation; g->rotate = 0.0; } else if (g->bcount > 60) g->attr &= ~IS_PRESET; } else { if (g->bcount == 1) { g->speed = -12.0 * g->orientation; g->rotate = 0.0; } else if (g->bcount == 10 || g->bcount == 15 || g->bcount == 20 || g->bcount == 25) { dx = pl->x - g->x; dy = pl->y - g->y; if (fabs(dy) < 1.e-7) dy = sign(1.e-7, dy); if (dy <= 0.0) tazm = - atan(dx / dy) + ra (180.0); else tazm = - atan(dx / dy) ; if (g->azm > PI2) g->azm -= PI2; if (g->azm < 0.0) g->azm += PI2; t1 = (tazm - g->azm) / 5.0; t3 = (tazm - (g->azm - PI2)) / 5.0; if (fabs(t3) < fabs(t1)) t1 = t3; if (fabs(t1) > 0.045) t1 = sign (.045, t1); g->rotate = t1; g->speed = 0.0; } else if (g->bcount > 30) g->attr &= ~IS_PRESET; } } else if (g->pcount >= 5) { g->orientation = 1.0; g->pcount = 0; dx = pl->x - g->x; dy = pl->y - g->y; if (fabs(dy) < 1.e-7) dy = sign(1.e-7, dy); if (dy <= 0.0) tazm = - atan(dx / dy) + ra (180.0); else tazm = - atan(dx / dy); if (g->azm > PI2) g->azm -= PI2; if (g->azm < 0.0) g->azm += PI2; t1 = (tazm - g->azm) / 5.0; t3 = (tazm - (g->azm - PI2)) / 5.0; if (fabs(t3) < fabs(t1)) t1 = t3; g->speed = 12.0 * (PI - fabs(t1) * 5.0) / PI; if (fabs(t1) > 0.045) t1 = sign (0.045, t1); g->rotate = t1; } scrot = g->rotate / 0.045 * 12.0; sctot = sqrt (g->speed*g->speed + scrot*scrot); if (sctot > 12.0) { scale = 12.0 / sctot; g->speed *= scale; g->rotate *= scale; } s = g->salvo; if (pl->attr & IS_ALIVE && g->fcount>10 && g->ecount>50 && !(s->attr & STILL_THERE)) { g->fcount = 0; cp = pl->ca; sp = pl->sa; dcp = cos(pl->rotate); dsp = sin(pl->rotate); cm = cos(g->azm); sm = sin(g->azm); i = 0; xmt = g->x; ymt = g->y; xpt = pl->x; ypt = pl->y; rate = 40.0; for (i=0; i<50; i++) { temp = cp; cp = cp * dcp - sp * dsp; sp = sp * dcp + dsp * temp; xmt -= sm * rate; ymt += cm * rate; xpt -= sp * pl->speed; ypt += cp * pl->speed; dist = (xpt-xmt)*(xpt-xmt) + (ymt-ypt)*(ymt-ypt); if (dist <= BMS_TOL) { s->attr = START_LIVING; s->x = g->x; s->y = g->y; s->z = 0.0; s->prox = g->prox; s->proy = g->proy; s->azm = g->azm; s->speed = 40.0; s->ecount = 0; message(3, True); break; } } } } void movemissile(g, pl, first) Genericp g; Genericp pl; Bool first; { float dx, dy, tazm, t1, t3, dt1, t2; if (g->attr & IS_NEW) { g->ecount = 0; g->pcount = 0; g->attr &= ~IS_NEW; } g->rotate = 0.0; g->pcount++; g->z -= 25.0; if (g->z <= 0.0) g->z = 0.0; if (g->attr & IS_BLOCKED) g->z = 90.0; g->speed = 35.0; if (g->z > 91.0) g->speed = 0.0; if (g->pcount >= 12) { g->pcount = 0; if (g->proy > 60.0) { dx = pl->x - g->x; dy = pl->y - g->y; if (fabs(dy) < 1.e-7) dy = sign(1.e-7, dy); if (dy <= 0.0) tazm = - atan(dx / dy) + ra (180.0); else tazm = - atan(dx / dy); if (g->azm > PI2) g->azm -= PI2; if (g->azm < 0.0) g->azm += PI2; t1 = (tazm - g->azm); t3 = (tazm - (g->azm - PI2)); if (fabs(t3) < fabs(t1)) t1 = t3; if (!first) { dt1 = frand() * 0.5; dt1 = sign (dt1, t1); if (frand() > 0.8) dt1 = - dt1; t1 += dt1; } if (fabs(t1) > 0.90) t1 = sign (0.90, t1); g->rotate = t1; } else { tazm = pl->azm - PI; if (tazm < 0.0) tazm += PI2; if (tazm > PI2) tazm -= PI2; if (g->azm < 0.0) g->azm += PI2; if (g->azm > PI2) g->azm -= PI2; t1 = (tazm - g->azm); t2 = (tazm - (g->azm - PI2)); if (fabs(t2) < fabs(t1)) t1 = t2; if (fabs(t1) > 0.90) t1 = sign (0.90, t1); g->rotate = t1; } } } void movecopter(g, pl) Genericp g; Genericp pl; { float dx, dy, tazm, t1, t2, t3, cp, sp, dcp, dsp, cm, sm; float xmt, ymt, xpt, ypt, rate, temp, dist; int i; Genericp s; g->pcount++; if (!(pl->attr & IS_ALIVE)) { g->pcount = 0; g->attr &= ~CAN_SHOOT; } if (g->attr & IS_NEW) { g->pcount = 10; g->ecount = 0; g->attr |= CAN_SHOOT; g->attr &= ~IS_NEW; if (frand() > 0.5) g->orientation = PI / 2.0; else g->orientation = -PI / 2.0; } s = g->salvo; if (g->ecount < 150 && g->range > 400.0) if (!(s->attr & STILL_THERE)) g->z -= 5.0; else g->z += 5.0; else g->z += 5.0; if (g->z <= 40.0) g->z = 40.0; if (g->z > 150.0) g->z = 150.0; if (g->attr & IS_BLOCKED && g->z < 90.0) { g->z = 90.0; g->attr &= ~IS_BLOCKED; } g->speed = 20.0; if (g->pcount >= 10) { g->pcount = 0; if (g->range > 400.0 && g->ecount < 150) { dx = pl->x - g->x; dy = pl->y - g->y; if (fabs(dy) < 1.e-7) dy = sign(1.e-7, dy); if (dy <= 0.0) tazm = - atan(dx / dy) + ra (180.0); else tazm = - atan(dx / dy); if (g->azm > PI2) g->azm -= PI2; if (g->azm < 0.0) g->azm += PI2; t1 = (tazm - g->azm) / 10.0; t3 = (tazm - (g->azm - PI2)) /10.0; if (fabs(t3) < fabs(t1)) t1 = t3; if (fabs(t1) > 0.06) t1 = sign (0.06, t1); g->rotate = t1; } else { tazm = g->orientation; if (tazm < 0.0) tazm += PI2; if (tazm > PI2) tazm -= PI2; if (g->azm < 0.0) g->azm += PI2; if (g->azm > PI2) g->azm -= PI2; t1 = (tazm - g->azm) / 10.0; t2 = (tazm - (g->azm - PI2)) / 10.0; if (fabs(t2) < fabs(t1)) t1 = t2; if (fabs(t1) > 0.06) t1 = sign (0.06, t1); g->rotate = t1; g->speed = 30.0; } } if (g->attr & CAN_SHOOT && g->z < 50.0 && !(s->attr & STILL_THERE)) { /* * the original Fortran had the following * sp = pl->sa and cp = pl->ca * * however, sa and ca were undefined...fortran was really good * about making these 0, C doesn't guarantee this will occur. * the two choices to fix this are to make sp and cp * 0 initially or to make them the sin/cos of azm. * the first method makes the copter fire as it hits * the ground, the second method the copter won't fire * until it is very close unless you are moving straight * toward it or straight away from it. */ cp = sp = 0; dcp = cos(pl->rotate); dsp = sin(pl->rotate); cm = cos(g->azm); sm = sin(g->azm); xmt = g->x; ymt = g->y; xpt = pl->x; ypt = pl->y; rate = 40.0; for (i=0; i<50; i++) { temp = cp; cp = cp * dcp - sp * dsp; sp = sp * dcp + dsp * temp; xmt -= sm * rate; ymt += cm * rate; xpt -= sp * pl->speed; ypt += cp * pl->speed; dist = (xpt-xmt)*(xpt-xmt) + (ymt-ypt)*(ymt-ypt); if (dist <= BMC_TOL) { s->attr = START_LIVING; s->x = g->x; s->y = g->y; s->z = 0.0; s->prox = g->prox; s->proy = g->proy; s->azm = g->azm; s->speed = 40.0; s->ecount = 0; message(3, True); break; } } } } void movetank(g, pl) Genericp g; Genericp pl; { int i; float dx, dy, tazm, t1, t3, scrot, sctot, scale, cp, sp, dcp; float dsp, cm, sm, xmt, ymt, xpt, ypt, rate, temp, dist; Genericp s; g->pcount++; g->fcount++; if (g->attr & IS_NEW) { g->attr &= ~(IS_NEW | IS_PRESET); g->bcount = 0; g->ecount = 0; g->pcount = 5; g->fcount = 5; g->orientation = 1.0; } if (g->attr & IS_BLOCKED && g->attr & LAST_BLOCKED) g->orientation = -g->orientation; g->attr &= ~LAST_BLOCKED; if (g->attr & IS_BLOCKED) { if (g->attr & BLOCKED_BY_ENEMY) g->attr |= IS_EVADING; else g->attr &= ~IS_EVADING; g->attr |= IS_PRESET | LAST_BLOCKED; g->bcount = 0; } if (g->attr & IS_PRESET) { g->bcount++; if (!(g->attr & IS_EVADING)) { if (g->bcount == 1) { g->speed = -8.0 * g->orientation; g->rotate = 0.030; if (frand() > 0.5) g->rotate = -g->rotate; } else if (g->bcount == 45) { g->speed = 8.0 * g->orientation; g->rotate = 0.0; } else if (g->bcount > 90) g->attr &= ~IS_PRESET; } else { if (g->bcount == 1) { g->speed = -8.0 * g->orientation; g->rotate = 0.0; } else if (g->bcount == 10 || g->bcount == 15 || g->bcount == 20 || g->bcount == 25) { dx = pl->x - g->x; dy = pl->y - g->y; if (fabs(dy) < 1.e-7) dy = sign(1.e-7, dy); if (dy <= 0.0) tazm = - atan(dx / dy) + ra (180.0); else tazm = - atan(dx / dy) ; if (g->azm > PI2) g->azm -= PI2; if (g->azm < 0.0) g->azm += PI2; t1 = (tazm - g->azm) / 5.0; t3 = (tazm - (g->azm - PI2)) / 5.0; if (fabs(t3) < fabs(t1)) t1 = t3; if (fabs(t1) > 0.030) t1 = sign (.030, t1); g->rotate = t1; g->speed = 0.0; } else if (g->bcount > 30) g->attr &= ~IS_PRESET; } } else if (g->pcount >= 10) { g->orientation = 1.0; g->pcount = 0; dx = pl->x - g->x; dy = pl->y - g->y; if (fabs(dy) < 1.e-7) dy = sign(1.e-7, dy); if (dy <= 0.0) tazm = - atan(dx / dy) + ra (180.0); else tazm = - atan(dx / dy); if (g->azm > PI2) g->azm -= PI2; if (g->azm < 0.0) g->azm += PI2; t1 = (tazm - g->azm) / 10.0; t3 = (tazm - (g->azm - PI2)) / 10.0; if (fabs(t3) < fabs(t1)) t1 = t3; g->speed = 8.0 * (PI - fabs(t1) * 10.0) / PI; if (fabs(t1) > 0.030) t1 = sign (0.030, t1); g->rotate = t1; } scrot = g->rotate / 0.030 * 8.0; sctot = sqrt (g->speed*g->speed + scrot*scrot); if (sctot > 8.0) { scale = 8.0 / sctot; g->speed *= scale; g->rotate *= scale; } s = g->salvo; if (pl->attr & IS_ALIVE && g->fcount>10 && g->ecount>100 && !(s->attr & STILL_THERE)) { g->fcount = 0; cp = pl->ca; sp = pl->sa; dcp = cos(pl->rotate); dsp = sin(pl->rotate); cm = cos(g->azm); sm = sin(g->azm); i = 0; xmt = g->x; ymt = g->y; xpt = pl->x; ypt = pl->y; rate = 40.0; for (i=0; i<50; i++) { temp = cp; cp = cp * dcp - sp * dsp; sp = sp * dcp + dsp * temp; xmt -= sm * rate; ymt += cm * rate; xpt -= sp * pl->speed; ypt += cp * pl->speed; dist = (xpt-xmt)*(xpt-xmt) + (ymt-ypt)*(ymt-ypt); if (dist <= BMT_TOL) { s->attr = START_LIVING; s->x = g->x; s->y = g->y; s->z = 0.0; s->prox = g->prox; s->proy = g->proy; s->azm = g->azm; s->speed = 40.0; s->ecount = 0; message(3, True); break; } } } } void movelander(g, pl) Genericp g; Genericp pl; { float dx, dy, theta; if (++g->pcount > 20) { g->pcount = 0; if (g->range <= 750.0) { dx = g->x - pl->x; dy = g->y - pl->y; theta = atan (dy / (fabs(dx) + 1.0)); if (dx <= 0.0) theta = PI - theta; /* the original fortran went to all the trouble of calculating * theta above, but never used it. perhaps the following * statement was left out. */ g->azm = theta; } if (frand() >= 0.5) { g->azm += frand() * PI / 4.0; } else { g->azm -= frand() * PI / 4.0; } g->speed = frand() * 20.0; } }