NetBSD/games/warp/move.c

671 lines
16 KiB
C

/* Header: move.c,v 7.0.1.2 86/10/20 14:37:06 lwall Exp */
/* Log: move.c,v
* Revision 7.0.1.2 86/10/20 14:37:06 lwall
* Picked some lint.
*
* Revision 7.0.1.1 86/10/16 10:52:09 lwall
* Added Damage. Fixed random bugs.
*
* Revision 7.0 86/10/08 15:12:40 lwall
* Split into separate files. Added amoebas and pirates.
*
*/
#include "EXTERN.h"
#include "warp.h"
#include "bang.h"
#include "object.h"
#include "move.h"
#include "play.h"
#include "score.h"
#include "term.h"
#include "them.h"
#include "us.h"
#include "util.h"
#include "weapon.h"
#include "INTERN.h"
#include "move.h"
void
move_init(void)
{
;
}
void
bounce(OBJECT *obj)
{
int x;
int y;
int count=0;
y = (obj->posy - sgn(obj->vely) + YSIZE00) % YSIZE;
x = (obj->posx - sgn(obj->velx) + XSIZE00) % XSIZE;
while (occupant[y][x]) {
y = (y + rand_mod(3) - 1 + YSIZE00) % YSIZE;
x = (x + rand_mod(3) - 1 + XSIZE00) % XSIZE;
if (++count > 10000) { /* if universe full, get out of it fast */
unmake_object(obj);
if (ent) unmake_object(ent);
if (base) unmake_object(base);
finish = 1;
return;
}
}
obj->posy = y;
obj->posx = x;
obj->vely = 0;
obj->velx = 0;
occupant[y][x] = obj;
if (numamoebas && obj->image == ' ')
mvaddc(y+1, x*2, amb[y][x]);
else
mvaddc(y+1, x*2, obj->image);
}
void
move_universe(void)
{
OBJECT *curobj;
int x;
int y;
OBJECT *temp;
OBJECT *thenext;
for (curobj = movers; curobj != &root; curobj = curobj->next) {
x = curobj->posx;
y = curobj->posy;
if (curobj == occupant[y][x]) {
occupant[y][x] = 0;
}
else if (curobj->type != Torp && curobj->type != Web) {
resetty();
abort();
}
}
for (curobj = movers; curobj != &root; curobj = thenext) {
thenext = curobj->next;
if (curobj->vely || curobj->velx) {
y = curobj->posy;
x = curobj->posx;
if (curobj->image != ' ' &&
(!(temp=occupant[y][x]) || temp->image==' ') ) {
move(y+1, x*2, numamoebas ? amb[y][x] : ' ');
}
y = (y + curobj->vely + YSIZE00) % YSIZE;
x = (x + curobj->velx + XSIZE00) % XSIZE;
if (!(temp=occupant[y][x]) || temp->type != Star ||
curobj->type != Torp || curobj->image == '+' ||
curobj->image == 'x') {
curobj->posy = y;
curobj->posx = x;
}
else {
if (curobj->image == '0') {
curobj->vely = rand_mod(3)-1;
curobj->velx = rand_mod(3)-1;
}
else
curobj->vely = curobj->velx = 0;
y = curobj->posy;
x = curobj->posx;
}
}
else { /* not moving */
y = curobj->posy;
x = curobj->posx;
if (curobj->type == Torp ||
curobj->type == Star ||
curobj->type == Web) {
curobj->flags |= STATIC;
curobj->next->prev = curobj->prev;
curobj->prev->next = curobj->next;
curobj->prev = movers->prev;
curobj->next = movers;
movers->prev->next = curobj;
movers->prev = curobj;
}
}
if ((temp = occupant[y][x]) != NULL) { /* already occupied? */
if (!temp->contend) {
if (temp->type == Torp) {
if (temp->image == '+')
blast[y][x] += 1250;
else if (temp->image == 'o' && (base||ent))
blast[y][x] += 500+super*20;
else if (temp->image == 'O' && (base||ent))
blast[y][x] += 5000+super*100;
}
}
yblasted[y] |= 1;
xblasted[x] |= 1;
blasted = true;
curobj->contend = temp;
occupant[y][x] = curobj;
switch (curobj->type) {
case Enemy:
if (numamoebas && curobj == nuke && temp->image == '+')
blast[y][x] += 80000;
else if (temp->type == Enemy)
blast[y][x] += 10;
else
goto defblast;
break;
case Crusher:
if (curobj->velx)
blast[y][x] += 100000;
else
goto defblast;
break;
case Torp:
if (curobj->image == '+')
blast[y][x] += (temp==nuke ? 80000 : 1250);
else if (curobj->image == 'o')
blast[y][x] += 500+super*20;
else if (curobj->image == 'O')
blast[y][x] += 5000+super*100;
goto defblast;
case Star:
if (temp == ent)
goto damshield;
goto defblast;
case Enterprise:
if (temp->type == Star) {
damshield:
if (!rand_mod(10)) {
if (!damflag[NOSHIELDS])
damage++;
if (damflag[NOSHIELDS] < 100)
damflag[NOSHIELDS] += rand_mod(smarts)/5+2;
}
}
goto defblast;
default:
defblast:
blast[y][x] += rand_mod(751)+1;
break;
}
}
else {
occupant[y][x] = curobj;
if (curobj->image != ' ' &&
(curobj->velx || curobj->vely ||
curobj->type == Torp || curobj->type == Web) ) {
mvaddc(y+1, x*2, curobj->image);
}
if (curobj->type == Crusher && curobj->velx) {
blast[y][x] += 100000;
yblasted[y] |= 1;
xblasted[x] |= 1;
blasted = true;
}
}
}
if (blasted) {
int minxblast = -1;
int maxxblast = -2;
long tmpblast;
blasted = numamoebas;
for (x=0; x<XSIZE; x++) {
if (xblasted[x]) {
xblasted[x] = 0;
maxxblast = x;
if (minxblast < 0)
minxblast = x;
}
}
for (y=0; y<YSIZE; y++) {
if (yblasted[y]) {
yblasted[y] = 0;
for (x=minxblast; x<=maxxblast; x++) {
tmpblast = blast[y][x];
if (numamoebas && amb[y][x] == '~') {
if ((temp = occupant[y][x]) != NULL) {
if (temp->image == '&')
tmpblast >>= 1;
else if (temp->type == Web)
tmpblast = 100000;
else
tmpblast += 50 + temp->energy/100;
if (tmpblast > 250 && !rand_mod(5+(inumstars>>4)))
modify_amoeba(y,x,1,'~',5);
}
xblasted[x] = 2;
yblasted[y] = 2;
}
if (tmpblast) {
OBJECT *biggie = 0;
blast[y][x] = 0;
temp = occupant[y][x];
if (tmpblast < 0) {
if (numamoebas && tmpblast < -1000000 &&
amb[y][x] == '~' && temp != nuke) {
amb[y][x] = ' ';
if (!temp)
make_plink(y,x);
ambsize--;
}
tmpblast = 0;
}
if (temp) {
if ((!numamoebas || amb[y][x]==' ') &&
tmpblast < 100000)
make_plink(y,x);
for ( ;temp;
temp = curobj->contend,curobj->contend = 0){
curobj = temp;
switch (curobj->type) {
case Enterprise: {
long tmp = curobj->energy;
if (ent->energy>500 || apolloflag & 1)
curobj->energy -= tmpblast /
((apolloflag & 1)
? 20
: (5+abs(ent->velx)+abs(ent->vely))
/ ((damflag[NOSHIELDS]>>3)+1)+1);
else
curobj->energy -= tmpblast;
if (rand_mod(1 + tmp - curobj->energy) > 100
|| ent->energy < (entmax>>1)) {
if (debug & 128 ||
(damage <= smarts/10 &&
!rand_mod(6-smarts/20-massacre) )) {
tmp = rand_mod(MAXDAMAGE);
if (damflag[tmp]) {
if (damflag[tmp] < 60)
damflag[tmp] += rand_mod(60);
}
else {
damflag[tmp] =
rand_mod(smarts+10)+2;
damage++;
}
}
}
break;
}
case Base:
if (base->energy > 1000 || apolloflag & 2)
curobj->energy -= tmpblast /
((apolloflag & 2)?20:5);
else
curobj->energy -= tmpblast;
break;
case Crusher:
if (tmpblast > 132767)
curobj->energy -= (tmpblast - 100000);
else if (tmpblast >= 100000) {
curobj->energy += (tmpblast - 100000);
if (curobj->energy > 32767)
curobj->energy = 32767;
}
else /* vulnerable while feeding */
curobj->energy -= tmpblast;
break;
case Enemy:
curobj->energy -= tmpblast*10/enemshields;
break;
default:
curobj->energy -= tmpblast;
break;
}
if (curobj->energy < 0) { /* killed it? */
switch (curobj->image) {
case 'A':
tmpblast = 100000;
make_blast(y,x,8192L,1);
numapollos = apolloflag = 0;
numstars--;
numenemies--;
curscore += 5000;
deados = 0;
break;
case 'E': case 'e': case 'C': case 'c':
ent = 0;
numents--;
if (base)
status = 2;
else
status = 3;
deados = 0;
break;
case 'B': case 'b':
base = 0;
numbases--;
if (ent)
status = entmode;
else
status = 3;
deados = 0;
break;
case '&': {
int i, xxx, yyy;
for (i = 0; i < YSIZE; i++)
yblasted[i] &= 1;
for (i = 0; i < XSIZE; i++)
xblasted[i] &= 1;
numamoebas = 0; /* ignore amb[][] now */
for (yyy = 0; yyy < YSIZE; yyy++) {
for (xxx = 0; xxx < XSIZE; xxx++) {
if (amb[yyy][xxx] == '~' &&
!occupant[yyy][xxx]) {
mvaddch(yyy+1,xxx*2,' ');
}
}
}
numenemies--;
curscore += 10000;
if (curobj == enemies)
enemies = curobj->next;
deados = 0;
break;
}
case '<': case '>': {
int i;
numenemies--;
numcrushes = 0;
curscore += 10000;
if (curobj == movers)
movers = curobj->next;
if (curobj == enemies)
enemies = curobj->next;
deados = 0;
tmpblast = 100000;
make_blast(y,(x+XSIZE00)%XSIZE,10000L,0);
if (curobj->image == '<') {
for (i=XSIZE00; i<=XSIZE01; i++)
make_blast(y,(x+i)%XSIZE,
10000L,0);
for (i=XSIZE00; i<=XSIZE02; i++)
make_blast(y,(x+i)%XSIZE,
10000L,0);
make_blast(y,(x+XSIZE03)%XSIZE,
10000L,1);
for (i=XSIZE00; i<=XSIZE08; i++)
make_blast(y,(x+i)%XSIZE,
10000L,0);
}
else {
for (i=XSIZE00; i>=XSIZE99; i--)
make_blast(y,(x+i)%XSIZE,
10000L,0);
for (i=XSIZE00; i>=XSIZE98; i--)
make_blast(y,(x+i)%XSIZE,
10000L,0);
make_blast(y,(x+XSIZE97)%XSIZE,
10000L,1);
for (i=XSIZE00; i>=XSIZE92; i--)
make_blast(y,(x+i)%XSIZE,
10000L,0);
}
}
break;
case 'K':
numenemies--;
curscore += curobj->mass;
if (curobj == enemies)
enemies = curobj->next;
deados = 0;
break;
case 'T':
numenemies--;
curscore += curobj->mass*3/2;
if (curobj == enemies)
enemies = curobj->next;
deados = 0;
break;
case 'R': case ' ': case 'P':
numenemies--;
if (curobj->flags & PIRATE)
curscore += curobj->mass;
else
curscore += curobj->mass*3;
if (curobj == enemies)
enemies = curobj->next;
deados = 0;
break;
case 'G':
numenemies--;
numgorns--;
tmpblast = 100000;
if (madgorns)
curscore += curobj->mass/2;
else
curscore += curobj->mass*2;
if (curobj == enemies)
enemies = curobj->next;
{
int xxx,yyy;
for (xxx = -1; xxx<=1; xxx++)
for (yyy = -1; yyy<=1; yyy++)
if (rand_mod(2+massacre))
fire_torp(curobj,
yyy,xxx);
}
deados = 0;
break;
case '@':
numinhab--;
/* FALL THROUGH */
case '*':
banging = true;
numstars--;
break;
case '|': case '-': case '/': case '\\':
tmpblast = 100000;
make_blast(y,x,curobj->mass,1);
banging = true;
deados = 0;
break;
case 'x':
curscore += 10;
deados = 0;
break;
case 'X':
curscore += 100;
numxes--;
deados = 0;
break;
case '0':
curscore += 35;
numos--;
deados += 3;
break;
case 'o':
curscore += 100;
numos--;
deados++;
break;
case 'O':
curscore += 200;
numos--;
deados += 2;
break;
case 'M':
deadmudds++;
inumfriends--;
numfriends--;
if (curobj == enemies)
enemies = curobj->next;
break;
case 'Q': case 'W': case 'Y': case 'U':
case 'I': case 'S': case 'D': case 'H':
case 'J': case 'L': case 'Z': case 'V':
case 'F':
numfriends--;
if (curobj == enemies)
enemies = curobj->next;
if (inumfriends < 10)
madfriends += 500;
else
madfriends += 10000/inumfriends;
break;
}
if (tmpblast < 100000)
make_blast(y,x,curobj->mass,1);
unmake_object(curobj);
}
else { /* didn't kill anything */
if (!biggie)
biggie = curobj;
else {
if (biggie->mass > curobj->mass)
bounce(curobj);
else {
bounce(biggie);
biggie = curobj;
}
}
}
}
if (biggie) {
occupant[y][x] = biggie;
if (numamoebas && biggie->image == ' ')
mvaddch(y+1,x*2, amb[y][x]);
else
mvaddch(y+1,x*2, biggie->image);
}
else {
occupant[y][x] = 0;
mvaddch(y+1, x*2, numamoebas ? amb[y][x] : ' ');
}
}
}
}
}
}
}
do_bangs();
if (numcrushes && movers->type == Crusher)
movers->vely = 0;
if ((curobj = base) != NULL) {
char ch;
curobj->velx = 0;
curobj->vely = 0;
curobj->energy += 25*lookaround(curobj->posy,curobj->posx,Star);
if (curobj->energy > basemax)
curobj->energy = basemax;
if (curobj->energy >= 1000)
ch = 'B';
else
ch = 'b';
if (ch != curobj->image) {
setimage(curobj, ch);
}
}
if ((curobj = ent) != NULL) {
char ch;
if (entmode == 0) {
curobj->velx = 0;
curobj->vely = 0;
}
if (base && !cloaking && !curobj->velx && !curobj->vely &&
lookfor(curobj->posy,curobj->posx,Base)) {
int tmp;
#ifdef lint
tmp = 0;
#else
tmp = (int) (base->energy - 1000 < entmax - curobj->energy ?
base->energy - 1000 : entmax - curobj->energy);
#endif
if (tmp < 0)
tmp = 0;
curobj->energy += tmp;
base->energy -= tmp;
tmp = (btorp < 50 - etorp ?
btorp : 50 - etorp);
etorp += tmp;
btorp -= tmp;
if (damage) {
tmp = rand_mod(MAXDAMAGE);
if (damflag[tmp] > 5) {
damflag[tmp] = rand_mod(5)+1;
}
}
}
if (curobj->energy >= 500 && (!damage || !damflag[NOSHIELDS]))
ch = cloaked?'C':'E';
else
ch = cloaked?'c':'e';
if (ch != curobj->image) {
setimage(curobj, ch);
}
}
}
int
lookaround(int y, int x, char what)
{
OBJECT *obj;
int count=0;
int xp;
int xm;
if ((obj=occupant[y][xp=(x+XSIZE01)%XSIZE])&&obj->type == what) /* 0, 1 */
count++;
if ((obj=occupant[y][xm=(x+XSIZE99)%XSIZE])&&obj->type == what) /* 0, -1 */
count++;
if ((obj=occupant[y=(y+YSIZE99)%YSIZE][xp])&&obj->type == what) /* -1, 1 */
count++;
if ((obj=occupant[y][x])&&obj->type == what) /* -1, 0 */
count++;
if ((obj=occupant[y][xm])&&obj->type == what) /* -1, -1 */
count++;
if ((obj=occupant[y=(y+2)%YSIZE][xp])&&obj->type == what) /* 1, 1 */
count++;
if ((obj=occupant[y][x])&&obj->type == what) /* 1, 0 */
count++;
if ((obj=occupant[y][xm])&&obj->type == what) /* 1, -1 */
count++;
return (count);
}
int
lookfor(int y, int x, char what)
{
OBJECT *obj;
int xp;
int xm;
if (((obj=occupant[y][xp=(x+XSIZE01)%XSIZE])&&obj->type == what)||/* 0, 1 */
((obj=occupant[y][xm=(x+XSIZE99)%XSIZE])&&obj->type == what)||/* 0, -1 */
((obj=occupant[y=(y+YSIZE99)%YSIZE][xp])&&obj->type == what)||/* -1, 1 */
((obj=occupant[y][x])&&obj->type == what) ||/* -1, 0 */
((obj=occupant[y][xm])&&obj->type == what) ||/* -1,-1 */
((obj=occupant[y=(y+2)%YSIZE][xp])&&obj->type == what) ||/* 1, 1 */
((obj=occupant[y][x])&&obj->type == what) ||/* 1, 0 */
((obj=occupant[y][xm])&&obj->type == what)) /* 1, -1 */
return(1);
return (0);
}
OBJECT*
lookimg(int y, int x, char what)
{
OBJECT *obj;
int xp;
int xm;
if (((obj=occupant[y][xp=(x+XSIZE01)%XSIZE])&&obj->image==what)||/* 0, 1 */
((obj=occupant[y][xm=(x+XSIZE99)%XSIZE])&&obj->image==what)||/* 0, -1 */
((obj=occupant[y=(y+YSIZE99)%YSIZE][xp])&&obj->image==what)||/* -1, 1 */
((obj=occupant[y][x])&&obj->image==what) ||/* -1, 0 */
((obj=occupant[y][xm])&&obj->image==what) ||/* -1,-1 */
((obj=occupant[y=(y+2)%YSIZE][xp])&&obj->image==what) ||/* 1, 1 */
((obj=occupant[y][x])&&obj->image==what) ||/* 1, 0 */
((obj=occupant[y][xm])&&obj->image==what)) /* 1, -1 */
return obj;
return NULL;
}