1 /* Copyright (C) 1993, 1992 Nathan Sidwell */ 2 /* RCS $Id: apple.c,v 4.10 1993/12/10 11:52:23 nathan Stable $ */ 3 #include "xmris.h" 4 /*{{{ prototypes*/ 5 static APPLE *apple_search PROTOARG((int, int, unsigned, unsigned, unsigned)); 6 /*}}}*/ 7 /*{{{ APPLE *apple_search(x, y, width, height, found)*/ 8 static APPLE *apple_search 9 FUNCARG((x, y, width, height, found), 10 int x /* x coord start */ 11 ARGSEP int y /* y coord start */ 12 ARGSEP unsigned width /* width of box */ 13 ARGSEP unsigned height /* height of box */ 14 ARGSEP unsigned found /* already found ones */ 15 ) 16 /* 17 * looks for an apple in the specified box 18 * and returns a ptr to it, if found 19 */ 20 { 21 unsigned i; 22 APPLE *aptr; 23 24 for(aptr = apple.list, i = 0; i != apple.apples; i++, aptr++, found >>= 1) 25 if(!(found & 1) && INRANGE(aptr->pixel.x + aptr->push - x, 0, width) && 26 INRANGE(aptr->pixel.y - y, 0, height)) 27 return aptr; 28 return NULL; 29 } 30 /*}}}*/ 31 /*{{{ int apple_stop(mptr, cptr)*/ 32 extern int apple_stop 33 FUNCARG((mptr, cptr), 34 MONSTER *mptr 35 ARGSEP CELL *cptr 36 ) 37 /* 38 * sees if the monster is about to walk into an apple 39 * returns 0 if clear, 1 if stopped 40 * sets mptr->pause & mptr->stop as required 41 * the apples and other monsters are altered 42 * if they're pushed about 43 * called before we've moved the monster 44 */ 45 { 46 unsigned stop; 47 unsigned pause; 48 49 pause = stop = 0; 50 switch(mptr->dir) 51 { 52 /*{{{ case 0: (up)*/ 53 case 0: 54 { 55 unsigned i; 56 APPLE *aptr; 57 int px, py; 58 59 px = mptr->pixel.x; 60 py = mptr->pixel.y; 61 for(aptr = apple.list, i = apple.apples; i--; aptr++) 62 { 63 if(INRANGE(aptr->pixel.x + aptr->push - px, 64 1 - CELL_WIDTH, CELL_WIDTH) && 65 INRANGE(py - aptr->pixel.y, CELL_HEIGHT / 2, 66 CELL_HEIGHT + VEL_Y) && !aptr->ghost) 67 { 68 stop = 1; 69 break; 70 } 71 } 72 break; 73 } 74 /*}}}*/ 75 /*{{{ case 1: (down)*/ 76 case 1: 77 { 78 unsigned i; 79 APPLE *aptr; 80 int px, py; 81 82 px = mptr->pixel.x; 83 py = mptr->pixel.y; 84 for(aptr = apple.list, i = apple.apples; i--; aptr++) 85 { 86 if(INRANGE(aptr->pixel.x + aptr->push - px, 87 1 - CELL_WIDTH, CELL_WIDTH) && 88 INRANGE(aptr->pixel.y + apple_sizes[aptr->state].offset.y - py, 89 CELL_HEIGHT / 2, CELL_HEIGHT + VEL_Y) && !aptr->ghost) 90 { 91 stop = 1; 92 break; 93 } 94 } 95 break; 96 } 97 /*}}}*/ 98 /*{{{ case 2: (left)*/ 99 case 2: 100 { 101 unsigned found; 102 int x, y; 103 int width; 104 APPLE *final; 105 106 found = 0; 107 final = NULL; 108 width = VEL_X; 109 x = mptr->pixel.x - CELL_WIDTH + 1 - width; 110 y = mptr->pixel.y - CELL_HEIGHT + VEL_Y; 111 /*{{{ look for apple*/ 112 for(;;) 113 { 114 APPLE *aptr; 115 CELL *cptr; 116 117 aptr = apple_search(x, y, (unsigned)width + CELL_WIDTH / 2, 118 2 * (CELL_HEIGHT - VEL_Y), found); 119 if(!aptr) 120 break; 121 else if(aptr->push || aptr->pixel.x - width < PIXELX(0, 0)) 122 { 123 stop = 1; 124 break; 125 } 126 else if(aptr->state == 2 && 127 ((mptr->type != 1 && mptr->type != 4) || 128 (aptr->offset.x < (cptr = BOARDCELL(aptr->cell.x, aptr->cell.y + 129 (aptr->offset.y <= 0)))->depths[2] && 130 !cptr[-1].visit))) 131 break; 132 else 133 { 134 final = aptr; 135 found |= 1 << (aptr - apple.list); 136 width = aptr->pixel.x - x + 1; 137 width = (width + APPLE_VEL_X - 1) / APPLE_VEL_X * APPLE_VEL_X; 138 aptr->maypush = width; 139 x = aptr->pixel.x - CELL_WIDTH + 1 - width; 140 if(aptr->state != 2 && aptr->offset.y > 0 && 141 apple_search(x, aptr->pixel.y - aptr->offset.y + CELL_HEIGHT, 142 (unsigned)width, (unsigned)aptr->offset.y, found)) 143 { 144 stop = 1; 145 break; 146 } 147 y = aptr->pixel.y - CELL_HEIGHT + VEL_Y; 148 if(!width || aptr->state == 2) 149 break; 150 } 151 } 152 /*}}}*/ 153 if(found && !stop) 154 { 155 /*{{{ check if against monster*/ 156 if(width) 157 { 158 unsigned i; 159 MONSTER *mptr; 160 MONSTER *list; 161 162 list = NULL; 163 for(mptr = monster.list, i = monster.monsters; i--; mptr++) 164 { 165 if(!mptr->squished && !mptr->shot && 166 INRANGE(mptr->pixel.x - x, 0, width + CELL_WIDTH) && 167 INRANGE(mptr->pixel.y - y, 0, 2 * (CELL_HEIGHT - VEL_Y))) 168 { 169 if(mptr->type == 4) 170 stop = 1; 171 else if(mptr->type == 1) 172 { 173 if(mptr->dir & 2 || 174 mptr->pixel.x - x >= width + CELL_WIDTH / 2) 175 stop = 1; 176 } 177 else if(final->state < 2 && (!mptr->type || mptr->chew)) 178 { 179 CELL *cptr; 180 181 cptr = BOARDCELL(mptr->cell.x, mptr->cell.y); 182 if(cptr->depths[2] <= mptr->offset.x - width || 183 ((cptr->depths[1] || cptr->depths[0]) && 184 mptr->offset.x >= 0)) 185 { 186 mptr->list = list; 187 list = mptr; 188 mptr->push = -1; 189 } 190 else 191 stop = 1; 192 } 193 } 194 } 195 if(final->state < 2) 196 final->list = list; 197 } 198 /*}}}*/ 199 if(!stop) 200 { 201 pause = 1; 202 /*{{{ push the apples*/ 203 { 204 unsigned i; 205 APPLE *aptr; 206 207 for(aptr = apple.list, i = apple.apples; 208 i--; aptr++, found >>= 1) 209 if(found & 1) 210 aptr->push = -aptr->maypush; 211 } 212 /*}}}*/ 213 } 214 } 215 break; 216 } 217 /*}}}*/ 218 /*{{{ case 3: (right)*/ 219 case 3: 220 { 221 unsigned found; 222 int x, y; 223 int width; 224 APPLE *final; 225 226 found = 0; 227 final = NULL; 228 width = VEL_X; 229 x = mptr->pixel.x + CELL_WIDTH; 230 y = mptr->pixel.y - CELL_HEIGHT + VEL_Y; 231 /*{{{ look for apple*/ 232 for(;;) 233 { 234 APPLE *aptr; 235 236 aptr = apple_search(x - CELL_WIDTH / 2, y, 237 (unsigned)width + CELL_WIDTH / 2, 238 2 * (CELL_HEIGHT - VEL_Y), found); 239 if(!aptr) 240 break; 241 else if(aptr->push || 242 aptr->pixel.x + width > PIXELX(CELLS_ACROSS - 1, 0)) 243 { 244 stop = 1; 245 break; 246 } 247 else if(aptr->state == 2 && ((mptr->type != 1 && mptr->type != 4) || 248 (aptr->offset.x > (cptr = BOARDCELL(aptr->cell.x, aptr->cell.y + 249 (aptr->offset.y <= 0)))->depths[3] && 250 !cptr[1].visit))) 251 break; 252 else 253 { 254 final = aptr; 255 found |= 1 << (aptr - apple.list); 256 width -= aptr->pixel.x - x; 257 width = (width + APPLE_VEL_X - 1) / APPLE_VEL_X * APPLE_VEL_X; 258 aptr->maypush = width; 259 x = aptr->pixel.x + CELL_WIDTH; 260 if(aptr->state != 2 && aptr->offset.y > 0 && 261 apple_search(x, aptr->pixel.y - aptr->offset.y + CELL_HEIGHT, 262 (unsigned)width, (unsigned)aptr->offset.y, found)) 263 { 264 stop = 1; 265 break; 266 } 267 y = aptr->pixel.y - CELL_HEIGHT + VEL_Y; 268 if(!width || aptr->state == 2) 269 break; 270 } 271 } 272 /*}}}*/ 273 if(found && !stop) 274 { 275 /*{{{ check if against monster*/ 276 if(width) 277 { 278 unsigned i; 279 MONSTER *mptr; 280 MONSTER *list; 281 282 list = NULL; 283 for(mptr = monster.list, i = monster.monsters; i--; mptr++) 284 { 285 if(!mptr->squished && !mptr->shot && 286 INRANGE(mptr->pixel.x - x, -CELL_WIDTH, width) && 287 INRANGE(mptr->pixel.y - y, 0, 2 * (CELL_HEIGHT - VEL_Y))) 288 { 289 if(mptr->type == 4) 290 stop = 1; 291 else if(mptr->type == 1) 292 { 293 if(mptr->dir & 2 || 294 mptr->pixel.x - x < -CELL_WIDTH / 2) 295 stop = 1; 296 } 297 else if(final->state < 2 && (!mptr->type || mptr->chew)) 298 { 299 CELL *cptr; 300 301 cptr = BOARDCELL(mptr->cell.x, mptr->cell.y); 302 if(cptr->depths[3] >= mptr->offset.x + width || 303 ((cptr->depths[1] || cptr->depths[0]) && 304 mptr->offset.x <= 0)) 305 { 306 mptr->list = list; 307 list = mptr; 308 mptr->push = 1; 309 } 310 else 311 stop = 1; 312 } 313 } 314 } 315 if(final->state < 2) 316 final->list = list; 317 } 318 /*}}}*/ 319 if(!stop) 320 { 321 pause = 1; 322 /*{{{ push the apples*/ 323 { 324 unsigned i; 325 APPLE *aptr; 326 327 for(aptr = apple.list, i = apple.apples; i--; aptr++, found >>= 1) 328 if(found & 1) 329 aptr->push = aptr->maypush; 330 } 331 /*}}}*/ 332 } 333 } 334 break; 335 } 336 /*}}}*/ 337 } 338 mptr->stop = stop; 339 mptr->pause = pause; 340 return stop; 341 } 342 /*}}}*/ 343 /*{{{ void move_apples()*/ 344 extern VOIDFUNC move_apples FUNCARGVOID 345 /* 346 * moves all the apples 347 */ 348 { 349 APPLE *aptr; 350 unsigned i; 351 352 apple.moving = 0; 353 for(aptr = apple.list, i = apple.apples; i--; aptr++) 354 { 355 CELL *cptr; 356 357 cptr = BOARDCELL(aptr->cell.x, aptr->cell.y); 358 if(aptr->chewed) 359 { 360 assert(!aptr->monsters); 361 aptr->state = 6; 362 } 363 else 364 { 365 if(aptr->ghost) 366 aptr->ghost--; 367 /*{{{ pushed?*/ 368 if(aptr->push) 369 { 370 aptr->pixel.x += aptr->push; 371 aptr->offset.x += aptr->push; 372 assert(!(aptr->offset.x % APPLE_VEL_X)); 373 if(aptr->offset.x < -(CELL_WIDTH / 2)) 374 { 375 aptr->offset.x += CELL_WIDTH + GAP_WIDTH; 376 aptr->cell.x -= 1; 377 cptr -= 1; 378 } 379 else if(aptr->offset.x > (CELL_WIDTH / 2)) 380 { 381 aptr->offset.x -= CELL_WIDTH + GAP_WIDTH; 382 aptr->cell.x += 1; 383 cptr += 1; 384 } 385 } 386 /*}}}*/ 387 switch(aptr->state) 388 { 389 /*{{{ case 0: (static) case 1: (rock)*/ 390 case 0: case 1: 391 { 392 unsigned old; 393 unsigned new; 394 int offset; 395 396 old = aptr->state; 397 new = 0; 398 offset = 0; 399 if(aptr->offset.y < cptr->depths[1]) 400 new = 2; 401 else if(aptr->cell.y == CELLS_DOWN - 1) 402 { 403 new = 3; 404 aptr->ghost = 0; 405 } 406 else if(cptr[CELL_STRIDE].visit) 407 new = 1; 408 else if(aptr->offset.y - cptr[CELL_STRIDE*2].depths[0] >= 409 CELL_HEIGHT + GAP_HEIGHT) 410 new = 1; 411 else if(cptr[CELL_STRIDE + 1].visit && 412 cptr[CELL_STRIDE + 1].depths[2] - aptr->offset.x < 413 -(CELL_WIDTH / 2)) 414 { 415 new = 1; 416 offset = 1; 417 } 418 else if(cptr[CELL_STRIDE - 1].visit && 419 cptr[CELL_STRIDE - 1].depths[3] - aptr->offset.x > 420 CELL_WIDTH / 2) 421 { 422 new = 1; 423 offset = -1; 424 } 425 if(new == 1 && old == 1 && !aptr->count--) 426 new = 2; 427 if(new) 428 /*{{{ check for supporting monster*/ 429 { 430 MONSTER *mptr; 431 unsigned count; 432 int x, y; 433 434 x = aptr->pixel.x; 435 y = aptr->pixel.y; 436 for(mptr = monster.list, count = monster.monsters; 437 count--; mptr++) 438 if((mptr->type == 4 || mptr->type == 1) && !mptr->shot && 439 INRANGE(mptr->pixel.x - x, 1 + VEL_X - CELL_WIDTH, 440 CELL_WIDTH - VEL_X) && 441 INRANGE(mptr->pixel.y - y, CELL_HEIGHT / 2, 442 CELL_HEIGHT + GAP_HEIGHT + 1)) 443 { 444 new = 0; 445 break; 446 } 447 else if(mptr->type & 2 && !mptr->dir && 448 INRANGE(mptr->pixel.y - y, 0, CELL_HEIGHT + 1) && 449 INRANGE(mptr->pixel.x - x, 1 - CELL_WIDTH / 2, 450 CELL_WIDTH / 2)) 451 { 452 new = 0; 453 break; 454 } 455 } 456 /*}}}*/ 457 aptr->state = new; 458 if(new == 0) 459 /*{{{ doesn't fall*/ 460 { 461 aptr->list = NULL; 462 if(aptr->offset.y) 463 { 464 aptr->offset.y += APPLE_SINK_Y; 465 aptr->pixel.y += APPLE_SINK_Y; 466 if(aptr->offset.y >= CELL_HEIGHT + GAP_HEIGHT) 467 { 468 aptr->pixel.y -= aptr->offset.y - 469 (CELL_HEIGHT + GAP_HEIGHT); 470 aptr->offset.y = 0; 471 aptr->cell.y++; 472 } 473 } 474 } 475 /*}}}*/ 476 else if(new == 1) 477 /*{{{ rock*/ 478 { 479 aptr->list = NULL; 480 if(old != new) 481 aptr->count = APPLE_ROCK_DELAY; 482 } 483 /*}}}*/ 484 else if(new == 2) 485 /*{{{ start to fall*/ 486 { 487 MONSTER *mptr; 488 MONSTER *prev; 489 490 aptr->count = APPLE_ACC; 491 aptr->distance = 0; 492 if(!cptr[offset].visit || aptr->offset.y > 0) 493 { 494 aptr->cell.y += 1; 495 aptr->offset.y -= CELL_HEIGHT + GAP_HEIGHT; 496 } 497 aptr->cell.x += offset; 498 aptr->offset.x -= offset * (CELL_WIDTH + GAP_WIDTH); 499 for(prev = NULL, mptr = aptr->list; mptr; 500 prev = mptr, mptr = mptr->list) 501 if(mptr->squished) 502 /*{{{ already put on a squish list*/ 503 { 504 if(prev) 505 prev->list = NULL; 506 else 507 aptr->list = NULL; 508 break; 509 } 510 /*}}}*/ 511 else 512 { 513 squish_monster(mptr); 514 if(mptr->pixel.y > aptr->pixel.y) 515 mptr->pixel.y = aptr->pixel.y; 516 mptr->pixel.y += CELL_HEIGHT - CELL_HEIGHT / 4; 517 aptr->monsters++; 518 aptr->distance = APPLE_FALL_SPLIT + 1; 519 } 520 panic_monsters(aptr->cell.x, aptr->cell.y, 521 BOARDCELL(aptr->cell.x, aptr->cell.y)); 522 } 523 /*}}}*/ 524 else 525 aptr->count = APPLE_SPLIT_DELAY; 526 break; 527 } 528 /*}}}*/ 529 /*{{{ case 2: (fall)*/ 530 case 2: 531 { 532 int j; 533 APPLE *optr; 534 535 /*{{{ horizontal movement*/ 536 if(!aptr->push) 537 { 538 int shift; 539 int x; 540 541 shift = x = 0; 542 /*{{{ desired direction*/ 543 if(aptr->offset.x < 0) 544 { 545 if(aptr->offset.x < cptr->depths[2]) 546 { 547 shift = APPLE_VEL_X; 548 x = aptr->pixel.x + CELL_WIDTH; 549 } 550 } 551 else if(aptr->offset.x > 0) 552 { 553 if(aptr->offset.x > cptr->depths[3]) 554 { 555 shift = -APPLE_VEL_X; 556 x = aptr->pixel.x - CELL_WIDTH - APPLE_VEL_X; 557 } 558 } 559 /*}}}*/ 560 if(shift) 561 /*{{{ move if not blocked*/ 562 { 563 MONSTER *mptr; 564 unsigned count; 565 566 for(mptr = monster.list, count = monster.monsters; 567 count--; mptr++) 568 if((mptr->type == 1 || mptr->type == 2) && 569 !mptr->shot && !mptr->squished && 570 INRANGE(mptr->pixel.x - x, 0, APPLE_VEL_X) && 571 INRANGE(mptr->pixel.y - aptr->pixel.y, 572 VEL_Y - CELL_HEIGHT + 1, CELL_HEIGHT - VEL_Y)) 573 { 574 shift = 0; 575 break; 576 } 577 if(shift) 578 { 579 aptr->offset.x += shift; 580 aptr->pixel.x += shift; 581 } 582 } 583 /*}}}*/ 584 } 585 /*}}}*/ 586 /*{{{ bashes into another?*/ 587 { 588 int x, y; 589 590 x = aptr->pixel.x; 591 y = aptr->pixel.y + aptr->count; 592 for(optr = apple.list, j = apple.apples; j--; optr++) 593 if(optr != aptr && INRANGE(optr->pixel.x - x, 594 1 - CELL_WIDTH, CELL_WIDTH) && 595 INRANGE(optr->pixel.y + 596 apple_sizes[optr->state].offset.y - y, 1, 597 CELL_HEIGHT - APPLE_VEL_Y) && 598 (optr->state || 599 BOARDCELL(optr->cell.x, optr->cell.y)->visit)) 600 { 601 if(optr->ghost || aptr->ghost) 602 /* EMPTY */; 603 else if(optr->state < 2) 604 { 605 optr->list = NULL; 606 optr->state = 3; 607 optr->count = APPLE_SPLIT_DELAY; 608 } 609 else if(optr->state == 2) 610 optr->distance = APPLE_FALL_SPLIT + 1; 611 break; 612 } 613 } 614 /*}}}*/ 615 if(j >= 0) 616 { 617 aptr->count = 0; 618 if(aptr->distance > APPLE_FALL_SPLIT) 619 { 620 aptr->state = 3; 621 aptr->count = APPLE_SPLIT_DELAY; 622 } 623 else 624 aptr->distance = 0; 625 } 626 else 627 { 628 CELL *nptr; 629 630 aptr->offset.y += aptr->count; 631 aptr->pixel.y += aptr->count; 632 aptr->distance += aptr->count; 633 aptr->count += APPLE_ACC; 634 if(aptr->count > APPLE_VEL_Y) 635 aptr->count = APPLE_VEL_Y; 636 nptr = drop_apple(aptr, cptr); 637 if(nptr) 638 panic_monsters(aptr->cell.x, aptr->cell.y, nptr); 639 else if(aptr->offset.y <= cptr[0].depths[1]) 640 /*{{{ not broken*/ 641 { 642 if(aptr->offset.y > 0 && cptr[CELL_STRIDE].visit) 643 { 644 aptr->cell.y += 1; 645 aptr->offset.y -= CELL_HEIGHT + GAP_HEIGHT; 646 } 647 } 648 /*}}}*/ 649 else 650 /*{{{ stop falling*/ 651 { 652 aptr->pixel.y += cptr[0].depths[1] - aptr->offset.y; 653 aptr->offset.y = cptr[0].depths[1]; 654 assert(aptr->offset.y < CELL_HEIGHT + GAP_HEIGHT); 655 if(aptr->distance > APPLE_FALL_SPLIT || 656 aptr->cell.y == CELLS_DOWN - 1) 657 { 658 aptr->state = 3; 659 aptr->count = APPLE_SPLIT_DELAY; 660 aptr->ghost = 0; 661 } 662 else 663 { 664 assert(!aptr->list); 665 aptr->state = 0; 666 } 667 } 668 /*}}}*/ 669 } 670 if(aptr->state < 6) 671 /*{{{ crushed someone?*/ 672 { 673 unsigned i; 674 MONSTER *mptr; 675 int x, y; 676 677 x = aptr->pixel.x; 678 y = aptr->pixel.y; 679 for(mptr = monster.list, i = monster.monsters; i--; mptr++) 680 if(!mptr->squished && !mptr->shot && mptr->type < 5 && 681 (mptr->type != 4 || 682 (global.state != 4 && !aptr->ghost)) && 683 INRANGE(mptr->pixel.x - x, VEL_X - CELL_WIDTH, 684 CELL_WIDTH - VEL_X + 1) && INRANGE(mptr->pixel.y - y, 685 mptr->type & 2 && mptr->dir != 1 ? 686 -CELL_HEIGHT / 2 : VEL_Y, 687 CELL_HEIGHT / 2 + VEL_Y + 1)) 688 { 689 unsigned squish; 690 691 if(!(mptr->type & 2) || mptr->chew || 692 aptr->monsters || mptr->dir == 1 || 693 global.state == 4) 694 squish = mptr->pixel.y - y >= VEL_Y; 695 else if(!mptr->dir) 696 /*{{{ going up*/ 697 { 698 squish = 0; 699 if(mptr->pixel.y - y >= -APPLE_VEL_Y && 700 INRANGE(mptr->pixel.x - x, 701 -VEL_X * 2, VEL_X * 2 + 1)) 702 { 703 aptr->chewed = 1; 704 mptr->chew = 1; 705 break; 706 } 707 } 708 /*}}}*/ 709 else if(mptr->dir == 2) 710 /*{{{ going left*/ 711 { 712 squish = mptr->pixel.x - x + y - mptr->pixel.y < 713 CELL_WIDTH / 2; 714 if(!squish && mptr->pixel.x - x <= 2 * VEL_X) 715 { 716 aptr->chewed = 1; 717 mptr->chew = 1; 718 break; 719 } 720 } 721 /*}}}*/ 722 else 723 /*{{{ going right*/ 724 { 725 squish = x - mptr->pixel.x + y - mptr->pixel.y < 726 CELL_WIDTH /2; 727 if(!squish && x - mptr->pixel.x <= 2 * VEL_X) 728 { 729 aptr->chewed = 1; 730 mptr->chew = 1; 731 break; 732 } 733 } 734 /*}}}*/ 735 if(squish) 736 /*{{{ squish it*/ 737 { 738 mptr->list = aptr->list; 739 aptr->list = mptr; 740 if(mptr != &monster.list[0]) 741 aptr->monsters++; 742 aptr->distance = APPLE_FALL_SPLIT + 1; 743 if(!aptr->state) 744 { 745 aptr->state = 3; 746 aptr->count = APPLE_SPLIT_DELAY; 747 } 748 squish_monster(mptr); 749 } 750 /*}}}*/ 751 } 752 } 753 /*}}}*/ 754 /*{{{ move the crushed monsters*/ 755 { 756 MONSTER *mptr; 757 unsigned count; 758 759 count = 0; /* XXX DEBUG */ 760 for(mptr = aptr->list; mptr; mptr = mptr->list) 761 { 762 mptr->pixel.y = aptr->pixel.y + CELL_HEIGHT; 763 count += mptr->type != 4; 764 } 765 assert(count == aptr->monsters); 766 } 767 /*}}}*/ 768 break; 769 } 770 /*}}}*/ 771 /*{{{ case 3: (split)*/ 772 case 3: 773 if(!aptr->count--) 774 { 775 aptr->state = 4; 776 aptr->count = APPLE_DECAY_DELAY; 777 assert(!aptr->monsters || aptr->list); 778 /*{{{ delete the crushed monsters*/ 779 { 780 MONSTER *mptr; 781 unsigned count; 782 783 count = 0; /* XXX */ 784 for(mptr = aptr->list; mptr; mptr = mptr->list) 785 if(mptr->type != 4) 786 { 787 mptr->type = 5; 788 count++; 789 } 790 assert(count == aptr->monsters); 791 } 792 /*}}}*/ 793 aptr->list = NULL; 794 if(aptr->monsters) 795 add_score(squish_scores[aptr->monsters >= SQUISH_SCORES ? 796 SQUISH_SCORES - 1 : aptr->monsters], 797 aptr->pixel.x + CELL_WIDTH / 2, 798 aptr->pixel.y + (int)(apple_sizes[4].size.y / 2)); 799 if(!aptr->offset.x && !aptr->offset.y && !global.diamond && 800 global.state != 4 && chaotic() < DIAMOND_PROB) 801 { 802 global.diamond = 1; 803 spawn_monster(1, 6, 1, 1, aptr->cell.x, aptr->cell.y, 804 0, 0)->count = DIAMOND_DELAY; 805 } 806 } 807 break; 808 /*}}}*/ 809 /*{{{ case 4: (decay)*/ 810 case 4: 811 if(!aptr->count--) 812 { 813 aptr->state = 5; 814 aptr->count = APPLE_ROT_DELAY; 815 } 816 break; 817 /*}}}*/ 818 /*{{{ case 5: (rot)*/ 819 case 5: 820 if(!aptr->count--) 821 aptr->state = 6; 822 break; 823 /*}}}*/ 824 /*{{{ default:*/ 825 default: 826 assert(0); 827 /*}}}*/ 828 } 829 apple.moving |= aptr->state; 830 } 831 aptr->push = 0; 832 } 833 return; 834 } 835 /*}}}*/ 836 /*{{{ void panic_monsters(cx, cy, cptr)*/ 837 extern VOIDFUNC panic_monsters 838 FUNCARG((cx, cy, cptr), 839 int cx 840 ARGSEP int cy 841 ARGSEP CELL *cptr 842 ) 843 /* 844 * looks underneath a newly falling apple and 845 * sees if there are any normal monsters to panic 846 */ 847 { 848 MONSTER *mptr; 849 unsigned count; 850 unsigned by; 851 852 for(by = ++cy; cptr->depths[1] >= GAP_HEIGHT; cptr++) 853 by++; 854 for(mptr = &monster.list[1], count = monster.monsters - 1; count--; mptr++) 855 if(!mptr->squished && !mptr->shot && !mptr->type && !mptr->panic && 856 mptr->cell.x == cx && INRANGE(mptr->cell.y, cy, by) && 857 (mptr->offset.x >= 0 || mptr->dir != 2) && 858 (mptr->offset.x <= 0 || mptr->dir != 3)) 859 mptr->panic = 1; 860 return; 861 } 862 /*}}}*/ 863 /*{{{ APPLE *spawn_apple(cx, cy, ox, oy)*/ 864 extern APPLE *spawn_apple 865 FUNCARG((cx, cy, ox, oy), 866 int cx 867 ARGSEP int cy 868 ARGSEP int ox 869 ARGSEP int oy 870 ) 871 /* 872 * spawns a new apple in state 0 873 */ 874 { 875 APPLE *aptr; 876 877 assert(apple.apples != APPLES); 878 aptr = &apple.list[apple.apples++]; 879 aptr->cell.x = cx; 880 aptr->cell.y = cy; 881 aptr->offset.x = ox = ox / APPLE_VEL_X * APPLE_VEL_X; 882 aptr->offset.y = oy; 883 aptr->old_pixel.x = aptr->pixel.x = PIXELX(cx, ox); 884 aptr->old_pixel.y = aptr->pixel.y = PIXELY(cy, oy); 885 aptr->ghost = aptr->state = 0; 886 aptr->count = 1; 887 aptr->distance = 0; 888 aptr->monsters = 0; 889 aptr->list = NULL; 890 aptr->push = 0; 891 aptr->chewed = 0; 892 aptr->old_state = 7; 893 aptr->back = 0; 894 return aptr; 895 } 896 /*}}}*/ 897 /*{{{ void squish_monster(mptr)*/ 898 extern VOIDFUNC squish_monster 899 FUNCARG((mptr), 900 MONSTER *mptr 901 ) 902 /* 903 * oh no, I've been squashed! 904 */ 905 { 906 mptr->squished = 1; 907 new_face(mptr); 908 if(mptr == &monster.list[0]) 909 mptr->shot = 1; 910 else 911 { 912 mptr->chew = 0; 913 if(mptr->type < 2) 914 monster.normals--; 915 else if(mptr->type == 2) 916 extra_dies(); 917 else if(mptr->type == 3) 918 monster.drones--; 919 } 920 return; 921 } 922 /*}}}*/ 923