/* $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 bounce(obj) Reg4 OBJECT *obj; { Reg1 int x; Reg2 int y; Reg3 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() { Reg1 OBJECT *curobj; Reg2 int x; Reg3 int y; Reg4 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]) { /* 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) { Reg7 int minxblast = -1; Reg8 int maxxblast = -2; Reg5 long tmpblast; blasted = numamoebas; for (x=0; ximage == '&') 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) { Reg6 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) { 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) { 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(y, x, what) Reg1 int y; Reg2 int x; Reg4 char what; { Reg3 OBJECT *obj; Reg5 int count=0; Reg6 int xp; Reg7 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(y, x, what) Reg1 int y; Reg2 int x; Reg4 char what; { Reg3 OBJECT *obj; Reg5 int xp; Reg6 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(y, x, what) Reg1 int y; Reg2 int x; Reg4 char what; { Reg3 OBJECT *obj; Reg5 int xp; Reg6 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(OBJECT*); }