1/* Header: move.c,v 7.0.1.2 86/10/20 14:37:06 lwall Exp */ 2 3/* Log: move.c,v 4 * Revision 7.0.1.2 86/10/20 14:37:06 lwall 5 * Picked some lint. 6 * 7 * Revision 7.0.1.1 86/10/16 10:52:09 lwall 8 * Added Damage. Fixed random bugs. 9 * 10 * Revision 7.0 86/10/08 15:12:40 lwall 11 * Split into separate files. Added amoebas and pirates. 12 * 13 */ 14 15#include "EXTERN.h" 16#include "warp.h" 17#include "bang.h" 18#include "object.h" 19#include "move.h" 20#include "play.h" 21#include "score.h" 22#include "term.h" 23#include "them.h" 24#include "us.h" 25#include "util.h" 26#include "weapon.h" 27#include "INTERN.h" 28#include "move.h" 29 30void 31move_init(void) 32{ 33 ; 34} 35 36void 37bounce(OBJECT *obj) 38{ 39 int x; 40 int y; 41 int count=0; 42 43 y = (obj->posy - sgn(obj->vely) + YSIZE00) % YSIZE; 44 x = (obj->posx - sgn(obj->velx) + XSIZE00) % XSIZE; 45 while (occupant[y][x]) { 46 y = (y + rand_mod(3) - 1 + YSIZE00) % YSIZE; 47 x = (x + rand_mod(3) - 1 + XSIZE00) % XSIZE; 48 if (++count > 10000) { /* if universe full, get out of it fast */ 49 unmake_object(obj); 50 if (ent) unmake_object(ent); 51 if (base) unmake_object(base); 52 finish = 1; 53 return; 54 } 55 } 56 obj->posy = y; 57 obj->posx = x; 58 obj->vely = 0; 59 obj->velx = 0; 60 occupant[y][x] = obj; 61 if (numamoebas && obj->image == ' ') 62 mvaddc(y+1, x*2, amb[y][x]); 63 else 64 mvaddc(y+1, x*2, obj->image); 65} 66 67void 68move_universe(void) 69{ 70 OBJECT *curobj; 71 int x; 72 int y; 73 OBJECT *temp; 74 OBJECT *thenext; 75 76 for (curobj = movers; curobj != &root; curobj = curobj->next) { 77 x = curobj->posx; 78 y = curobj->posy; 79 if (curobj == occupant[y][x]) { 80 occupant[y][x] = 0; 81 } 82 else if (curobj->type != Torp && curobj->type != Web) { 83 resetty(); 84 abort(); 85 } 86 } 87 for (curobj = movers; curobj != &root; curobj = thenext) { 88 thenext = curobj->next; 89 if (curobj->vely || curobj->velx) { 90 y = curobj->posy; 91 x = curobj->posx; 92 if (curobj->image != ' ' && 93 (!(temp=occupant[y][x]) || temp->image==' ') ) { 94 move(y+1, x*2, numamoebas ? amb[y][x] : ' '); 95 } 96 y = (y + curobj->vely + YSIZE00) % YSIZE; 97 x = (x + curobj->velx + XSIZE00) % XSIZE; 98 if (!(temp=occupant[y][x]) || temp->type != Star || 99 curobj->type != Torp || curobj->image == '+' || 100 curobj->image == 'x') { 101 curobj->posy = y; 102 curobj->posx = x; 103 } 104 else { 105 if (curobj->image == '0') { 106 curobj->vely = rand_mod(3)-1; 107 curobj->velx = rand_mod(3)-1; 108 } 109 else 110 curobj->vely = curobj->velx = 0; 111 y = curobj->posy; 112 x = curobj->posx; 113 } 114 } 115 else { /* not moving */ 116 y = curobj->posy; 117 x = curobj->posx; 118 if (curobj->type == Torp || 119 curobj->type == Star || 120 curobj->type == Web) { 121 curobj->flags |= STATIC; 122 curobj->next->prev = curobj->prev; 123 curobj->prev->next = curobj->next; 124 curobj->prev = movers->prev; 125 curobj->next = movers; 126 movers->prev->next = curobj; 127 movers->prev = curobj; 128 } 129 } 130 if ((temp = occupant[y][x]) != NULL) { /* already occupied? */ 131 if (!temp->contend) { 132 if (temp->type == Torp) { 133 if (temp->image == '+') 134 blast[y][x] += 1250; 135 else if (temp->image == 'o' && (base||ent)) 136 blast[y][x] += 500+super*20; 137 else if (temp->image == 'O' && (base||ent)) 138 blast[y][x] += 5000+super*100; 139 } 140 } 141 yblasted[y] |= 1; 142 xblasted[x] |= 1; 143 blasted = true; 144 curobj->contend = temp; 145 occupant[y][x] = curobj; 146 switch (curobj->type) { 147 case Enemy: 148 if (numamoebas && curobj == nuke && temp->image == '+') 149 blast[y][x] += 80000; 150 else if (temp->type == Enemy) 151 blast[y][x] += 10; 152 else 153 goto defblast; 154 break; 155 case Crusher: 156 if (curobj->velx) 157 blast[y][x] += 100000; 158 else 159 goto defblast; 160 break; 161 case Torp: 162 if (curobj->image == '+') 163 blast[y][x] += (temp==nuke ? 80000 : 1250); 164 else if (curobj->image == 'o') 165 blast[y][x] += 500+super*20; 166 else if (curobj->image == 'O') 167 blast[y][x] += 5000+super*100; 168 goto defblast; 169 case Star: 170 if (temp == ent) 171 goto damshield; 172 goto defblast; 173 case Enterprise: 174 if (temp->type == Star) { 175 damshield: 176 if (!rand_mod(10)) { 177 if (!damflag[NOSHIELDS]) 178 damage++; 179 if (damflag[NOSHIELDS] < 100) 180 damflag[NOSHIELDS] += rand_mod(smarts)/5+2; 181 } 182 } 183 goto defblast; 184 default: 185 defblast: 186 blast[y][x] += rand_mod(751)+1; 187 break; 188 } 189 } 190 else { 191 occupant[y][x] = curobj; 192 if (curobj->image != ' ' && 193 (curobj->velx || curobj->vely || 194 curobj->type == Torp || curobj->type == Web) ) { 195 mvaddc(y+1, x*2, curobj->image); 196 } 197 if (curobj->type == Crusher && curobj->velx) { 198 blast[y][x] += 100000; 199 yblasted[y] |= 1; 200 xblasted[x] |= 1; 201 blasted = true; 202 } 203 } 204 } 205 if (blasted) { 206 int minxblast = -1; 207 int maxxblast = -2; 208 long tmpblast; 209 210 blasted = numamoebas; 211 for (x=0; x<XSIZE; x++) { 212 if (xblasted[x]) { 213 xblasted[x] = 0; 214 maxxblast = x; 215 if (minxblast < 0) 216 minxblast = x; 217 } 218 } 219 for (y=0; y<YSIZE; y++) { 220 if (yblasted[y]) { 221 yblasted[y] = 0; 222 for (x=minxblast; x<=maxxblast; x++) { 223 tmpblast = blast[y][x]; 224 if (numamoebas && amb[y][x] == '~') { 225 if ((temp = occupant[y][x]) != NULL) { 226 if (temp->image == '&') 227 tmpblast >>= 1; 228 else if (temp->type == Web) 229 tmpblast = 100000; 230 else 231 tmpblast += 50 + temp->energy/100; 232 if (tmpblast > 250 && !rand_mod(5+(inumstars>>4))) 233 modify_amoeba(y,x,1,'~',5); 234 } 235 xblasted[x] = 2; 236 yblasted[y] = 2; 237 } 238 if (tmpblast) { 239 OBJECT *biggie = 0; 240 241 blast[y][x] = 0; 242 temp = occupant[y][x]; 243 if (tmpblast < 0) { 244 if (numamoebas && tmpblast < -1000000 && 245 amb[y][x] == '~' && temp != nuke) { 246 amb[y][x] = ' '; 247 if (!temp) 248 make_plink(y,x); 249 ambsize--; 250 } 251 tmpblast = 0; 252 } 253 if (temp) { 254 if ((!numamoebas || amb[y][x]==' ') && 255 tmpblast < 100000) 256 make_plink(y,x); 257 for ( ;temp; 258 temp = curobj->contend,curobj->contend = 0){ 259 curobj = temp; 260 switch (curobj->type) { 261 case Enterprise: { 262 long tmp = curobj->energy; 263 264 if (ent->energy>500 || apolloflag & 1) 265 curobj->energy -= tmpblast / 266 ((apolloflag & 1) 267 ? 20 268 : (5+abs(ent->velx)+abs(ent->vely)) 269 / ((damflag[NOSHIELDS]>>3)+1)+1); 270 else 271 curobj->energy -= tmpblast; 272 if (rand_mod(1 + tmp - curobj->energy) > 100 273 || ent->energy < (entmax>>1)) { 274 if (debug & 128 || 275 (damage <= smarts/10 && 276 !rand_mod(6-smarts/20-massacre) )) { 277 tmp = rand_mod(MAXDAMAGE); 278 if (damflag[tmp]) { 279 if (damflag[tmp] < 60) 280 damflag[tmp] += rand_mod(60); 281 } 282 else { 283 damflag[tmp] = 284 rand_mod(smarts+10)+2; 285 damage++; 286 } 287 } 288 } 289 break; 290 } 291 case Base: 292 if (base->energy > 1000 || apolloflag & 2) 293 curobj->energy -= tmpblast / 294 ((apolloflag & 2)?20:5); 295 else 296 curobj->energy -= tmpblast; 297 break; 298 case Crusher: 299 if (tmpblast > 132767) 300 curobj->energy -= (tmpblast - 100000); 301 else if (tmpblast >= 100000) { 302 curobj->energy += (tmpblast - 100000); 303 if (curobj->energy > 32767) 304 curobj->energy = 32767; 305 } 306 else /* vulnerable while feeding */ 307 curobj->energy -= tmpblast; 308 break; 309 case Enemy: 310 curobj->energy -= tmpblast*10/enemshields; 311 break; 312 default: 313 curobj->energy -= tmpblast; 314 break; 315 } 316 if (curobj->energy < 0) { /* killed it? */ 317 switch (curobj->image) { 318 case 'A': 319 tmpblast = 100000; 320 make_blast(y,x,8192L,1); 321 numapollos = apolloflag = 0; 322 numstars--; 323 numenemies--; 324 curscore += 5000; 325 deados = 0; 326 break; 327 case 'E': case 'e': case 'C': case 'c': 328 ent = 0; 329 numents--; 330 if (base) 331 status = 2; 332 else 333 status = 3; 334 deados = 0; 335 break; 336 case 'B': case 'b': 337 base = 0; 338 numbases--; 339 if (ent) 340 status = entmode; 341 else 342 status = 3; 343 deados = 0; 344 break; 345 case '&': { 346 int i, xxx, yyy; 347 348 for (i = 0; i < YSIZE; i++) 349 yblasted[i] &= 1; 350 for (i = 0; i < XSIZE; i++) 351 xblasted[i] &= 1; 352 numamoebas = 0; /* ignore amb[][] now */ 353 for (yyy = 0; yyy < YSIZE; yyy++) { 354 for (xxx = 0; xxx < XSIZE; xxx++) { 355 if (amb[yyy][xxx] == '~' && 356 !occupant[yyy][xxx]) { 357 mvaddch(yyy+1,xxx*2,' '); 358 } 359 } 360 } 361 numenemies--; 362 curscore += 10000; 363 if (curobj == enemies) 364 enemies = curobj->next; 365 deados = 0; 366 break; 367 } 368 case '<': case '>': { 369 int i; 370 371 numenemies--; 372 numcrushes = 0; 373 curscore += 10000; 374 if (curobj == movers) 375 movers = curobj->next; 376 if (curobj == enemies) 377 enemies = curobj->next; 378 deados = 0; 379 380 tmpblast = 100000; 381 make_blast(y,(x+XSIZE00)%XSIZE,10000L,0); 382 if (curobj->image == '<') { 383 for (i=XSIZE00; i<=XSIZE01; i++) 384 make_blast(y,(x+i)%XSIZE, 385 10000L,0); 386 for (i=XSIZE00; i<=XSIZE02; i++) 387 make_blast(y,(x+i)%XSIZE, 388 10000L,0); 389 make_blast(y,(x+XSIZE03)%XSIZE, 390 10000L,1); 391 for (i=XSIZE00; i<=XSIZE08; i++) 392 make_blast(y,(x+i)%XSIZE, 393 10000L,0); 394 } 395 else { 396 for (i=XSIZE00; i>=XSIZE99; i--) 397 make_blast(y,(x+i)%XSIZE, 398 10000L,0); 399 for (i=XSIZE00; i>=XSIZE98; i--) 400 make_blast(y,(x+i)%XSIZE, 401 10000L,0); 402 make_blast(y,(x+XSIZE97)%XSIZE, 403 10000L,1); 404 for (i=XSIZE00; i>=XSIZE92; i--) 405 make_blast(y,(x+i)%XSIZE, 406 10000L,0); 407 } 408 } 409 break; 410 case 'K': 411 numenemies--; 412 curscore += curobj->mass; 413 if (curobj == enemies) 414 enemies = curobj->next; 415 deados = 0; 416 break; 417 case 'T': 418 numenemies--; 419 curscore += curobj->mass*3/2; 420 if (curobj == enemies) 421 enemies = curobj->next; 422 deados = 0; 423 break; 424 case 'R': case ' ': case 'P': 425 numenemies--; 426 if (curobj->flags & PIRATE) 427 curscore += curobj->mass; 428 else 429 curscore += curobj->mass*3; 430 if (curobj == enemies) 431 enemies = curobj->next; 432 deados = 0; 433 break; 434 case 'G': 435 numenemies--; 436 numgorns--; 437 tmpblast = 100000; 438 if (madgorns) 439 curscore += curobj->mass/2; 440 else 441 curscore += curobj->mass*2; 442 if (curobj == enemies) 443 enemies = curobj->next; 444 { 445 int xxx,yyy; 446 447 for (xxx = -1; xxx<=1; xxx++) 448 for (yyy = -1; yyy<=1; yyy++) 449 if (rand_mod(2+massacre)) 450 fire_torp(curobj, 451 yyy,xxx); 452 } 453 deados = 0; 454 break; 455 case '@': 456 numinhab--; 457 /* FALL THROUGH */ 458 case '*': 459 banging = true; 460 numstars--; 461 break; 462 case '|': case '-': case '/': case '\\': 463 tmpblast = 100000; 464 make_blast(y,x,curobj->mass,1); 465 banging = true; 466 deados = 0; 467 break; 468 case 'x': 469 curscore += 10; 470 deados = 0; 471 break; 472 case 'X': 473 curscore += 100; 474 numxes--; 475 deados = 0; 476 break; 477 case '0': 478 curscore += 35; 479 numos--; 480 deados += 3; 481 break; 482 case 'o': 483 curscore += 100; 484 numos--; 485 deados++; 486 break; 487 case 'O': 488 curscore += 200; 489 numos--; 490 deados += 2; 491 break; 492 case 'M': 493 deadmudds++; 494 inumfriends--; 495 numfriends--; 496 if (curobj == enemies) 497 enemies = curobj->next; 498 break; 499 case 'Q': case 'W': case 'Y': case 'U': 500 case 'I': case 'S': case 'D': case 'H': 501 case 'J': case 'L': case 'Z': case 'V': 502 case 'F': 503 numfriends--; 504 if (curobj == enemies) 505 enemies = curobj->next; 506 if (inumfriends < 10) 507 madfriends += 500; 508 else 509 madfriends += 10000/inumfriends; 510 break; 511 } 512 if (tmpblast < 100000) 513 make_blast(y,x,curobj->mass,1); 514 unmake_object(curobj); 515 } 516 else { /* didn't kill anything */ 517 if (!biggie) 518 biggie = curobj; 519 else { 520 if (biggie->mass > curobj->mass) 521 bounce(curobj); 522 else { 523 bounce(biggie); 524 biggie = curobj; 525 } 526 } 527 } 528 } 529 if (biggie) { 530 occupant[y][x] = biggie; 531 if (numamoebas && biggie->image == ' ') 532 mvaddch(y+1,x*2, amb[y][x]); 533 else 534 mvaddch(y+1,x*2, biggie->image); 535 } 536 else { 537 occupant[y][x] = 0; 538 mvaddch(y+1, x*2, numamoebas ? amb[y][x] : ' '); 539 } 540 } 541 } 542 } 543 } 544 } 545 } 546 do_bangs(); 547 if (numcrushes && movers->type == Crusher) 548 movers->vely = 0; 549 if ((curobj = base) != NULL) { 550 char ch; 551 552 curobj->velx = 0; 553 curobj->vely = 0; 554 curobj->energy += 25*lookaround(curobj->posy,curobj->posx,Star); 555 if (curobj->energy > basemax) 556 curobj->energy = basemax; 557 if (curobj->energy >= 1000) 558 ch = 'B'; 559 else 560 ch = 'b'; 561 if (ch != curobj->image) { 562 setimage(curobj, ch); 563 } 564 } 565 if ((curobj = ent) != NULL) { 566 char ch; 567 568 if (entmode == 0) { 569 curobj->velx = 0; 570 curobj->vely = 0; 571 } 572 if (base && !cloaking && !curobj->velx && !curobj->vely && 573 lookfor(curobj->posy,curobj->posx,Base)) { 574 int tmp; 575 576#ifdef lint 577 tmp = 0; 578#else 579 tmp = (int) (base->energy - 1000 < entmax - curobj->energy ? 580 base->energy - 1000 : entmax - curobj->energy); 581#endif 582 if (tmp < 0) 583 tmp = 0; 584 curobj->energy += tmp; 585 base->energy -= tmp; 586 tmp = (btorp < 50 - etorp ? 587 btorp : 50 - etorp); 588 etorp += tmp; 589 btorp -= tmp; 590 if (damage) { 591 tmp = rand_mod(MAXDAMAGE); 592 if (damflag[tmp] > 5) { 593 damflag[tmp] = rand_mod(5)+1; 594 } 595 } 596 } 597 if (curobj->energy >= 500 && (!damage || !damflag[NOSHIELDS])) 598 ch = cloaked?'C':'E'; 599 else 600 ch = cloaked?'c':'e'; 601 if (ch != curobj->image) { 602 setimage(curobj, ch); 603 } 604 } 605} 606 607int 608lookaround(int y, int x, char what) 609{ 610 OBJECT *obj; 611 int count=0; 612 int xp; 613 int xm; 614 615 if ((obj=occupant[y][xp=(x+XSIZE01)%XSIZE])&&obj->type == what) /* 0, 1 */ 616 count++; 617 if ((obj=occupant[y][xm=(x+XSIZE99)%XSIZE])&&obj->type == what) /* 0, -1 */ 618 count++; 619 if ((obj=occupant[y=(y+YSIZE99)%YSIZE][xp])&&obj->type == what) /* -1, 1 */ 620 count++; 621 if ((obj=occupant[y][x])&&obj->type == what) /* -1, 0 */ 622 count++; 623 if ((obj=occupant[y][xm])&&obj->type == what) /* -1, -1 */ 624 count++; 625 if ((obj=occupant[y=(y+2)%YSIZE][xp])&&obj->type == what) /* 1, 1 */ 626 count++; 627 if ((obj=occupant[y][x])&&obj->type == what) /* 1, 0 */ 628 count++; 629 if ((obj=occupant[y][xm])&&obj->type == what) /* 1, -1 */ 630 count++; 631 return (count); 632} 633 634int 635lookfor(int y, int x, char what) 636{ 637 OBJECT *obj; 638 int xp; 639 int xm; 640 641 if (((obj=occupant[y][xp=(x+XSIZE01)%XSIZE])&&obj->type == what)||/* 0, 1 */ 642 ((obj=occupant[y][xm=(x+XSIZE99)%XSIZE])&&obj->type == what)||/* 0, -1 */ 643 ((obj=occupant[y=(y+YSIZE99)%YSIZE][xp])&&obj->type == what)||/* -1, 1 */ 644 ((obj=occupant[y][x])&&obj->type == what) ||/* -1, 0 */ 645 ((obj=occupant[y][xm])&&obj->type == what) ||/* -1,-1 */ 646 ((obj=occupant[y=(y+2)%YSIZE][xp])&&obj->type == what) ||/* 1, 1 */ 647 ((obj=occupant[y][x])&&obj->type == what) ||/* 1, 0 */ 648 ((obj=occupant[y][xm])&&obj->type == what)) /* 1, -1 */ 649 return(1); 650 return (0); 651} 652 653OBJECT* 654lookimg(int y, int x, char what) 655{ 656 OBJECT *obj; 657 int xp; 658 int xm; 659 660 if (((obj=occupant[y][xp=(x+XSIZE01)%XSIZE])&&obj->image==what)||/* 0, 1 */ 661 ((obj=occupant[y][xm=(x+XSIZE99)%XSIZE])&&obj->image==what)||/* 0, -1 */ 662 ((obj=occupant[y=(y+YSIZE99)%YSIZE][xp])&&obj->image==what)||/* -1, 1 */ 663 ((obj=occupant[y][x])&&obj->image==what) ||/* -1, 0 */ 664 ((obj=occupant[y][xm])&&obj->image==what) ||/* -1,-1 */ 665 ((obj=occupant[y=(y+2)%YSIZE][xp])&&obj->image==what) ||/* 1, 1 */ 666 ((obj=occupant[y][x])&&obj->image==what) ||/* 1, 0 */ 667 ((obj=occupant[y][xm])&&obj->image==what)) /* 1, -1 */ 668 return obj; 669 return NULL; 670} 671