|
|
1.1 root 1: /*
2: * Hunt
3: * Copyright (c) 1985 Conrad C. Huang, Gregory S. Couch, Kenneth C.R.C. Arnold
4: * San Francisco, California
5: *
6: * Copyright (c) 1985 Regents of the University of California.
7: * All rights reserved. The Berkeley software License Agreement
8: * specifies the terms and conditions for redistribution.
9: */
10:
11: # include "hunt.h"
12: # include <signal.h>
13:
14: # define PLUS_DELTA(x, max) if (x < max) x++; else x--
15: # define MINUS_DELTA(x, min) if (x > min) x--; else x++
16:
17: /*
18: * moveshots:
19: * Move the shots already in the air, taking explosions into account
20: */
21: moveshots()
22: {
23: register BULLET *bp, *next;
24: register PLAYER *pp;
25: register int x, y;
26: register BULLET *blist;
27:
28: rollexpl();
29: if (Bullets == NULL)
30: goto ret;
31:
32: /*
33: * First we move through the bullet list BULSPD times, looking
34: * for things we may have run into. If we do run into
35: * something, we set up the explosion and disappear, checking
36: * for damage to any player who got in the way.
37: */
38:
39: blist = Bullets;
40: Bullets = NULL;
41: for (bp = blist; bp != NULL; bp = next) {
42: next = bp->b_next;
43: x = bp->b_x;
44: y = bp->b_y;
45: Maze[y][x] = bp->b_over;
46: for (pp = Player; pp < End_player; pp++)
47: check(pp, y, x);
48: # ifdef MONITOR
49: for (pp = Monitor; pp < End_monitor; pp++)
50: check(pp, y, x);
51: # endif MONITOR
52:
53: switch (bp->b_type) {
54: case SHOT:
55: case GRENADE:
56: case SATCHEL:
57: case BOMB:
58: if (move_normal_shot(bp)) {
59: bp->b_next = Bullets;
60: Bullets = bp;
61: }
62: break;
63: # ifdef OOZE
64: case SLIME:
65: if (bp->b_expl || move_normal_shot(bp)) {
66: bp->b_next = Bullets;
67: Bullets = bp;
68: }
69: break;
70: # endif OOZE
71: # ifdef DRONE
72: case DSHOT:
73: if (move_drone(bp)) {
74: bp->b_next = Bullets;
75: Bullets = bp;
76: }
77: break;
78: # endif DRONE
79: default:
80: bp->b_next = Bullets;
81: Bullets = bp;
82: break;
83: }
84: }
85:
86: blist = Bullets;
87: Bullets = NULL;
88: for (bp = blist; bp != NULL; bp = next) {
89: next = bp->b_next;
90: if (!bp->b_expl) {
91: save_bullet(bp);
92: # ifdef MONITOR
93: for (pp = Monitor; pp < End_monitor; pp++)
94: check(pp, bp->b_y, bp->b_x);
95: # endif MONITOR
96: # ifdef DRONE
97: if (bp->b_type == DSHOT)
98: for (pp = Player; pp < End_player; pp++)
99: if (pp->p_scan >= 0)
100: check(pp, bp->b_y, bp->b_x);
101: # endif DRONE
102: continue;
103: }
104:
105: chkshot(bp, next);
106: free((char *) bp);
107: }
108:
109: for (pp = Player; pp < End_player; pp++)
110: Maze[pp->p_y][pp->p_x] = pp->p_face;
111:
112: ret:
113: # ifdef BOOTS
114: for (pp = Boot; pp < &Boot[NBOOTS]; pp++)
115: if (pp->p_flying >= 0)
116: move_flyer(pp);
117: # endif BOOTS
118: for (pp = Player; pp < End_player; pp++) {
119: # ifdef FLY
120: if (pp->p_flying >= 0)
121: move_flyer(pp);
122: # endif FLY
123: sendcom(pp, REFRESH); /* Flush out the explosions */
124: look(pp);
125: sendcom(pp, REFRESH);
126: }
127: # ifdef MONITOR
128: for (pp = Monitor; pp < End_monitor; pp++)
129: sendcom(pp, REFRESH);
130: # endif MONITOR
131:
132: return;
133: }
134:
135: /*
136: * move_normal_shot:
137: * Move a normal shot along its trajectory
138: */
139: move_normal_shot(bp)
140: register BULLET *bp;
141: {
142: register int i, x, y;
143: register PLAYER *pp;
144:
145: for (i = 0; i < BULSPD; i++) {
146: if (bp->b_expl)
147: break;
148:
149: x = bp->b_x;
150: y = bp->b_y;
151:
152: switch (bp->b_face) {
153: case LEFTS:
154: x--;
155: break;
156: case RIGHT:
157: x++;
158: break;
159: case ABOVE:
160: y--;
161: break;
162: case BELOW:
163: y++;
164: break;
165: }
166:
167: switch (Maze[y][x]) {
168: case SHOT:
169: if (rand_num(100) < 5) {
170: zapshot(Bullets, bp);
171: zapshot(bp->b_next, bp);
172: }
173: break;
174: case GRENADE:
175: if (rand_num(100) < 10) {
176: zapshot(Bullets, bp);
177: zapshot(bp->b_next, bp);
178: }
179: break;
180: # ifdef REFLECT
181: case WALL4: /* reflecting walls */
182: switch (bp->b_face) {
183: case LEFTS:
184: bp->b_face = BELOW;
185: break;
186: case RIGHT:
187: bp->b_face = ABOVE;
188: break;
189: case ABOVE:
190: bp->b_face = RIGHT;
191: break;
192: case BELOW:
193: bp->b_face = LEFTS;
194: break;
195: }
196: Maze[y][x] = WALL5;
197: # ifdef MONITOR
198: for (pp = Monitor; pp < End_monitor; pp++)
199: check(pp, y, x);
200: # endif MONITOR
201: break;
202: case WALL5:
203: switch (bp->b_face) {
204: case LEFTS:
205: bp->b_face = ABOVE;
206: break;
207: case RIGHT:
208: bp->b_face = BELOW;
209: break;
210: case ABOVE:
211: bp->b_face = LEFTS;
212: break;
213: case BELOW:
214: bp->b_face = RIGHT;
215: break;
216: }
217: Maze[y][x] = WALL4;
218: # ifdef MONITOR
219: for (pp = Monitor; pp < End_monitor; pp++)
220: check(pp, y, x);
221: # endif MONITOR
222: break;
223: # endif REFLECT
224: # ifdef RANDOM
225: case DOOR:
226: switch (rand_num(4)) {
227: case 0:
228: bp->b_face = ABOVE;
229: break;
230: case 1:
231: bp->b_face = BELOW;
232: break;
233: case 2:
234: bp->b_face = LEFTS;
235: break;
236: case 3:
237: bp->b_face = RIGHT;
238: break;
239: }
240: break;
241: # endif RANDOM
242: # ifdef FLY
243: case FLYER:
244: pp = play_at(y, x);
245: message(pp, "Zing!");
246: break;
247: # endif FLY
248: case LEFTS:
249: case RIGHT:
250: case BELOW:
251: case ABOVE:
252: /*
253: * give the person a chance to catch a
254: * grenade if s/he is facing it
255: */
256: pp = play_at(y, x);
257: pp->p_ident->i_shot += bp->b_charge;
258: if (opposite(bp->b_face, Maze[y][x])) {
259: if (rand_num(100) < 10) {
260: if (bp->b_owner != NULL)
261: message(bp->b_owner,
262: "Your charge was absorbed!");
263: if (bp->b_score != NULL)
264: bp->b_score->i_robbed += bp->b_charge;
265: pp->p_ammo += bp->b_charge;
266: if (pp->p_damage + bp->b_size * MINDAM
267: > pp->p_damcap)
268: pp->p_ident->i_saved++;
269: message(pp, "Absorbed charge (good shield!)");
270: pp->p_ident->i_absorbed += bp->b_charge;
271: free((char *) bp);
272: (void) sprintf(Buf, "%3d", pp->p_ammo);
273: cgoto(pp, STAT_AMMO_ROW, STAT_VALUE_COL);
274: outstr(pp, Buf, 3);
275: return FALSE;
276: }
277: pp->p_ident->i_faced += bp->b_charge;
278: }
279: /*
280: * Small chance that the bullet just misses the
281: * person. If so, the bullet just goes on its
282: * merry way without exploding.
283: */
284: if (rand_num(100) < 5) {
285: pp->p_ident->i_ducked += bp->b_charge;
286: if (pp->p_damage + bp->b_size * MINDAM
287: > pp->p_damcap)
288: pp->p_ident->i_saved++;
289: if (bp->b_score != NULL)
290: bp->b_score->i_missed += bp->b_charge;
291: message(pp, "Zing!");
292: if (bp->b_owner == NULL)
293: break;
294: message(bp->b_owner,
295: ((bp->b_score->i_missed & 0x7) == 0x7) ?
296: "My! What a bad shot you are!" :
297: "Missed him");
298: break;
299: }
300: /*
301: * The shot hit that sucker! Blow it up.
302: */
303: /* FALLTHROUGH */
304: # ifndef RANDOM
305: case DOOR:
306: # endif RANDOM
307: case WALL1:
308: case WALL2:
309: case WALL3:
310: bp->b_expl = TRUE;
311: break;
312: }
313:
314: bp->b_x = x;
315: bp->b_y = y;
316: }
317: return TRUE;
318: }
319:
320: # ifdef DRONE
321: /*
322: * move_drone:
323: * Move the drone to the next square
324: */
325: move_drone(bp)
326: register BULLET *bp;
327: {
328: register int mask, count;
329: register int n, dir;
330: register PLAYER *pp;
331:
332: /*
333: * See if we can give someone a blast
334: */
335: if (isplayer(Maze[bp->b_y][bp->b_x - 1])) {
336: dir = WEST;
337: goto drone_move;
338: }
339: if (isplayer(Maze[bp->b_y - 1][bp->b_x])) {
340: dir = NORTH;
341: goto drone_move;
342: }
343: if (isplayer(Maze[bp->b_y + 1][bp->b_x])) {
344: dir = SOUTH;
345: goto drone_move;
346: }
347: if (isplayer(Maze[bp->b_y][bp->b_x + 1])) {
348: dir = EAST;
349: goto drone_move;
350: }
351:
352: /*
353: * Find out what directions are clear
354: */
355: mask = count = 0;
356: if (!iswall(bp->b_y, bp->b_x - 1))
357: mask |= WEST, count++;
358: if (!iswall(bp->b_y - 1, bp->b_x))
359: mask |= NORTH, count++;
360: if (!iswall(bp->b_y + 1, bp->b_x))
361: mask |= SOUTH, count++;
362: if (!iswall(bp->b_y, bp->b_x + 1))
363: mask |= EAST, count++;
364:
365: /*
366: * All blocked up, just you wait
367: */
368: if (count == 0)
369: return TRUE;
370:
371: /*
372: * Only one way to go.
373: */
374: if (count == 1) {
375: dir = mask;
376: goto drone_move;
377: }
378:
379: /*
380: * Get rid of the direction that we came from
381: */
382: switch (bp->b_face) {
383: case LEFTS:
384: if (mask & EAST)
385: mask &= ~EAST, count--;
386: break;
387: case RIGHT:
388: if (mask & WEST)
389: mask &= ~WEST, count--;
390: break;
391: case ABOVE:
392: if (mask & SOUTH)
393: mask &= ~SOUTH, count--;
394: break;
395: case BELOW:
396: if (mask & NORTH)
397: mask &= ~NORTH, count--;
398: break;
399: }
400:
401: /*
402: * Pick one of the remaining directions
403: */
404: n = rand_num(count);
405: if (n >= 0 && mask & NORTH)
406: dir = NORTH, n--;
407: if (n >= 0 && mask & SOUTH)
408: dir = SOUTH, n--;
409: if (n >= 0 && mask & EAST)
410: dir = EAST, n--;
411: if (n >= 0 && mask & WEST)
412: dir = WEST, n--;
413:
414: /*
415: * Now that we know the direction of movement,
416: * just update the position of the drone
417: */
418: drone_move:
419: switch (dir) {
420: case WEST:
421: bp->b_x--;
422: bp->b_face = LEFTS;
423: break;
424: case EAST:
425: bp->b_x++;
426: bp->b_face = RIGHT;
427: break;
428: case NORTH:
429: bp->b_y--;
430: bp->b_face = ABOVE;
431: break;
432: case SOUTH:
433: bp->b_y++;
434: bp->b_face = BELOW;
435: break;
436: }
437: switch (Maze[bp->b_y][bp->b_x]) {
438: case LEFTS:
439: case RIGHT:
440: case BELOW:
441: case ABOVE:
442: /*
443: * give the person a chance to catch a
444: * drone if s/he is facing it
445: */
446: if (rand_num(100) < 1 &&
447: opposite(bp->b_face, Maze[bp->b_y][bp->b_x])) {
448: pp = play_at(bp->b_y, bp->b_x);
449: pp->p_ammo += bp->b_charge;
450: message(pp, "**** Absorbed drone ****");
451: free((char *) bp);
452: (void) sprintf(Buf, "%3d", pp->p_ammo);
453: cgoto(pp, STAT_AMMO_ROW, STAT_VALUE_COL);
454: outstr(pp, Buf, 3);
455: return FALSE;
456: }
457: bp->b_expl = TRUE;
458: break;
459: }
460: return TRUE;
461: }
462: # endif DRONE
463:
464: /*
465: * save_bullet:
466: * Put this bullet back onto the bullet list
467: */
468: save_bullet(bp)
469: register BULLET *bp;
470: {
471: bp->b_over = Maze[bp->b_y][bp->b_x];
472: switch (bp->b_over) {
473: case SHOT:
474: case GRENADE:
475: case SATCHEL:
476: case BOMB:
477: # ifdef OOZE
478: case SLIME:
479: # ifdef VOLCANO
480: case LAVA:
481: # endif VOLCANO
482: # endif OOZE
483: # ifdef DRONE
484: case DSHOT:
485: # endif DRONE
486: find_under(Bullets, bp);
487: break;
488: }
489:
490: switch (bp->b_over) {
491: case LEFTS:
492: case RIGHT:
493: case ABOVE:
494: case BELOW:
495: # ifdef FLY
496: case FLYER:
497: # endif FLY
498: mark_player(bp);
499: break;
500: # ifdef BOOTS
501: case BOOT:
502: case BOOT_PAIR:
503: mark_boot(bp);
504: # endif BOOTS
505:
506: default:
507: Maze[bp->b_y][bp->b_x] = bp->b_type;
508: break;
509: }
510:
511: bp->b_next = Bullets;
512: Bullets = bp;
513: }
514:
515: /*
516: * move_flyer:
517: * Update the position of a player in flight
518: */
519: move_flyer(pp)
520: register PLAYER *pp;
521: {
522: register int x, y;
523:
524: if (pp->p_undershot) {
525: fixshots(pp->p_y, pp->p_x, pp->p_over);
526: pp->p_undershot = FALSE;
527: }
528: Maze[pp->p_y][pp->p_x] = pp->p_over;
529: x = pp->p_x + pp->p_flyx;
530: y = pp->p_y + pp->p_flyy;
531: if (x < 1) {
532: x = 1 - x;
533: pp->p_flyx = -pp->p_flyx;
534: }
535: else if (x > WIDTH - 2) {
536: x = (WIDTH - 2) - (x - (WIDTH - 2));
537: pp->p_flyx = -pp->p_flyx;
538: }
539: if (y < 1) {
540: y = 1 - y;
541: pp->p_flyy = -pp->p_flyy;
542: }
543: else if (y > HEIGHT - 2) {
544: y = (HEIGHT - 2) - (y - (HEIGHT - 2));
545: pp->p_flyy = -pp->p_flyy;
546: }
547: again:
548: switch (Maze[y][x]) {
549: default:
550: switch (rand_num(4)) {
551: case 0:
552: PLUS_DELTA(x, WIDTH - 2);
553: break;
554: case 1:
555: MINUS_DELTA(x, 1);
556: break;
557: case 2:
558: PLUS_DELTA(y, HEIGHT - 2);
559: break;
560: case 3:
561: MINUS_DELTA(y, 1);
562: break;
563: }
564: goto again;
565: case WALL1:
566: case WALL2:
567: case WALL3:
568: # ifdef REFLECT
569: case WALL4:
570: case WALL5:
571: # endif REFLECT
572: # ifdef RANDOM
573: case DOOR:
574: # endif RANDOM
575: if (pp->p_flying == 0)
576: pp->p_flying++;
577: break;
578: case SPACE:
579: break;
580: }
581: pp->p_y = y;
582: pp->p_x = x;
583: if (pp->p_flying-- == 0) {
584: # ifdef BOOTS
585: if (pp->p_face != BOOT && pp->p_face != BOOT_PAIR) {
586: # endif
587: checkdam(pp, (PLAYER *) NULL, (IDENT *) NULL,
588: rand_num(pp->p_damage / 5), FALL);
589: pp->p_face = rand_dir();
590: showstat(pp);
591: # ifdef BOOTS
592: }
593: else {
594: if (Maze[y][x] == BOOT)
595: pp->p_face = BOOT_PAIR;
596: Maze[y][x] = SPACE;
597: }
598: # endif BOOTS
599: }
600: pp->p_over = Maze[y][x];
601: Maze[y][x] = pp->p_face;
602: showexpl(y, x, pp->p_face);
603: }
604:
605: /*
606: * chkshot
607: * Handle explosions
608: */
609: chkshot(bp, next)
610: register BULLET *bp;
611: BULLET *next;
612: {
613: register int y, x;
614: register int dy, dx, absdy;
615: register int delta, damage;
616: register char expl;
617: register PLAYER *pp;
618:
619: switch (bp->b_type) {
620: case SHOT:
621: case MINE:
622: case GRENADE:
623: case GMINE:
624: case SATCHEL:
625: case BOMB:
626: delta = bp->b_size - 1;
627: break;
628: # ifdef OOZE
629: case SLIME:
630: # ifdef VOLCANO
631: case LAVA:
632: # endif VOLCANO
633: chkslime(bp, next);
634: return;
635: # endif OOZE
636: # ifdef DRONE
637: case DSHOT:
638: bp->b_type = SLIME;
639: chkslime(bp, next);
640: return;
641: # endif DRONE
642: }
643: for (y = bp->b_y - delta; y <= bp->b_y + delta; y++) {
644: if (y < 0 || y >= HEIGHT)
645: continue;
646: dy = y - bp->b_y;
647: absdy = (dy < 0) ? -dy : dy;
648: for (x = bp->b_x - delta; x <= bp->b_x + delta; x++) {
649: if (x < 0 || x >= WIDTH)
650: continue;
651: dx = x - bp->b_x;
652: if (dx == 0)
653: expl = (dy == 0) ? '*' : '|';
654: else if (dy == 0)
655: expl = '-';
656: else if (dx == dy)
657: expl = '\\';
658: else if (dx == -dy)
659: expl = '/';
660: else
661: expl = '*';
662: showexpl(y, x, expl);
663: switch (Maze[y][x]) {
664: case LEFTS:
665: case RIGHT:
666: case ABOVE:
667: case BELOW:
668: # ifdef FLY
669: case FLYER:
670: # endif FLY
671: if (dx < 0)
672: dx = -dx;
673: if (absdy > dx)
674: damage = bp->b_size - absdy;
675: else
676: damage = bp->b_size - dx;
677: pp = play_at(y, x);
678: checkdam(pp, bp->b_owner, bp->b_score,
679: damage * MINDAM, bp->b_type);
680: break;
681: case GMINE:
682: case MINE:
683: add_shot((Maze[y][x] == GMINE) ?
684: GRENADE : SHOT,
685: y, x, LEFTS,
686: (Maze[y][x] == GMINE) ?
687: GRENREQ : BULREQ,
688: (PLAYER *) NULL, TRUE, SPACE);
689: Maze[y][x] = SPACE;
690: break;
691: }
692: }
693: }
694: }
695:
696: # ifdef OOZE
697: /*
698: * chkslime:
699: * handle slime shot exploding
700: */
701: chkslime(bp, next)
702: register BULLET *bp;
703: BULLET *next;
704: {
705: register BULLET *nbp;
706:
707: switch (Maze[bp->b_y][bp->b_x]) {
708: case WALL1:
709: case WALL2:
710: case WALL3:
711: # ifdef REFLECT
712: case WALL4:
713: case WALL5:
714: # endif REFLECT
715: # ifdef RANDOM
716: case DOOR:
717: # endif RANDOM
718: switch (bp->b_face) {
719: case LEFTS:
720: bp->b_x++;
721: break;
722: case RIGHT:
723: bp->b_x--;
724: break;
725: case ABOVE:
726: bp->b_y++;
727: break;
728: case BELOW:
729: bp->b_y--;
730: break;
731: }
732: break;
733: }
734: nbp = (BULLET *) malloc(sizeof (BULLET));
735: *nbp = *bp;
736: # ifdef VOLCANO
737: move_slime(nbp, nbp->b_type == SLIME ? SLIMESPEED : LAVASPEED, next);
738: # else VOLCANO
739: move_slime(nbp, SLIMESPEED, next);
740: # endif VOLCANO
741: }
742:
743: /*
744: * move_slime:
745: * move the given slime shot speed times and add it back if
746: * it hasn't fizzled yet
747: */
748: move_slime(bp, speed, next)
749: register BULLET *bp;
750: register int speed;
751: BULLET *next;
752: {
753: register int i, j, dirmask, count;
754: register PLAYER *pp;
755: register BULLET *nbp;
756:
757: if (speed == 0) {
758: if (bp->b_charge <= 0)
759: free((char *) bp);
760: else
761: save_bullet(bp);
762: return;
763: }
764:
765: # ifdef VOLCANO
766: showexpl(bp->b_y, bp->b_x, bp->b_type == LAVA ? LAVA : '*');
767: # else VOLCANO
768: showexpl(bp->b_y, bp->b_x, '*');
769: # endif VOLCANO
770: switch (Maze[bp->b_y][bp->b_x]) {
771: case LEFTS:
772: case RIGHT:
773: case ABOVE:
774: case BELOW:
775: # ifdef FLY
776: case FLYER:
777: # endif FLY
778: pp = play_at(bp->b_y, bp->b_x);
779: message(pp, "You've been slimed.");
780: checkdam(pp, bp->b_owner, bp->b_score, MINDAM, bp->b_type);
781: break;
782: case SHOT:
783: case GRENADE:
784: case SATCHEL:
785: case BOMB:
786: # ifdef DRONE
787: case DSHOT:
788: # endif DRONE
789: explshot(next, bp->b_y, bp->b_x);
790: explshot(Bullets, bp->b_y, bp->b_x);
791: break;
792: }
793:
794: if (--bp->b_charge <= 0) {
795: free((char *) bp);
796: return;
797: }
798:
799: dirmask = 0;
800: count = 0;
801: switch (bp->b_face) {
802: case LEFTS:
803: if (!iswall(bp->b_y, bp->b_x - 1))
804: dirmask |= WEST, count++;
805: if (!iswall(bp->b_y - 1, bp->b_x))
806: dirmask |= NORTH, count++;
807: if (!iswall(bp->b_y + 1, bp->b_x))
808: dirmask |= SOUTH, count++;
809: if (dirmask == 0)
810: if (!iswall(bp->b_y, bp->b_x + 1))
811: dirmask |= EAST, count++;
812: break;
813: case RIGHT:
814: if (!iswall(bp->b_y, bp->b_x + 1))
815: dirmask |= EAST, count++;
816: if (!iswall(bp->b_y - 1, bp->b_x))
817: dirmask |= NORTH, count++;
818: if (!iswall(bp->b_y + 1, bp->b_x))
819: dirmask |= SOUTH, count++;
820: if (dirmask == 0)
821: if (!iswall(bp->b_y, bp->b_x - 1))
822: dirmask |= WEST, count++;
823: break;
824: case ABOVE:
825: if (!iswall(bp->b_y - 1, bp->b_x))
826: dirmask |= NORTH, count++;
827: if (!iswall(bp->b_y, bp->b_x - 1))
828: dirmask |= WEST, count++;
829: if (!iswall(bp->b_y, bp->b_x + 1))
830: dirmask |= EAST, count++;
831: if (dirmask == 0)
832: if (!iswall(bp->b_y + 1, bp->b_x))
833: dirmask |= SOUTH, count++;
834: break;
835: case BELOW:
836: if (!iswall(bp->b_y + 1, bp->b_x))
837: dirmask |= SOUTH, count++;
838: if (!iswall(bp->b_y, bp->b_x - 1))
839: dirmask |= WEST, count++;
840: if (!iswall(bp->b_y, bp->b_x + 1))
841: dirmask |= EAST, count++;
842: if (dirmask == 0)
843: if (!iswall(bp->b_y - 1, bp->b_x))
844: dirmask |= NORTH, count++;
845: break;
846: }
847: if (count == 0) {
848: /*
849: * No place to go. Just sit here for a while and wait
850: * for adjacent squares to clear out.
851: */
852: save_bullet(bp);
853: return;
854: }
855: if (bp->b_charge < count) {
856: /* Only bp->b_charge paths may be taken */
857: while (count > bp->b_charge) {
858: if (dirmask & WEST)
859: dirmask &= ~WEST;
860: else if (dirmask & EAST)
861: dirmask &= ~EAST;
862: else if (dirmask & NORTH)
863: dirmask &= ~NORTH;
864: else if (dirmask & SOUTH)
865: dirmask &= ~SOUTH;
866: count--;
867: }
868: }
869:
870: i = bp->b_charge / count;
871: j = bp->b_charge % count;
872: if (dirmask & WEST) {
873: count--;
874: nbp = create_shot(bp->b_type, bp->b_y, bp->b_x - 1, LEFTS,
875: i, bp->b_size, bp->b_owner, bp->b_score, TRUE, SPACE);
876: move_slime(nbp, speed - 1, next);
877: }
878: if (dirmask & EAST) {
879: count--;
880: nbp = create_shot(bp->b_type, bp->b_y, bp->b_x + 1, RIGHT,
881: (count < j) ? i + 1 : i, bp->b_size, bp->b_owner,
882: bp->b_score, TRUE, SPACE);
883: move_slime(nbp, speed - 1, next);
884: }
885: if (dirmask & NORTH) {
886: count--;
887: nbp = create_shot(bp->b_type, bp->b_y - 1, bp->b_x, ABOVE,
888: (count < j) ? i + 1 : i, bp->b_size, bp->b_owner,
889: bp->b_score, TRUE, SPACE);
890: move_slime(nbp, speed - 1, next);
891: }
892: if (dirmask & SOUTH) {
893: count--;
894: nbp = create_shot(bp->b_type, bp->b_y + 1, bp->b_x, BELOW,
895: (count < j) ? i + 1 : i, bp->b_size, bp->b_owner,
896: bp->b_score, TRUE, SPACE);
897: move_slime(nbp, speed - 1, next);
898: }
899:
900: free((char *) bp);
901: }
902:
903: /*
904: * iswall:
905: * returns whether the given location is a wall
906: */
907: iswall(y, x)
908: register int y, x;
909: {
910: if (y < 0 || x < 0 || y >= HEIGHT || x >= WIDTH)
911: return TRUE;
912: switch (Maze[y][x]) {
913: case WALL1:
914: case WALL2:
915: case WALL3:
916: # ifdef REFLECT
917: case WALL4:
918: case WALL5:
919: # endif REFLECT
920: # ifdef RANDOM
921: case DOOR:
922: # endif RANDOM
923: # ifdef OOZE
924: case SLIME:
925: # ifdef VOLCANO
926: case LAVA:
927: # endif VOLCANO
928: # endif OOZE
929: return TRUE;
930: }
931: return FALSE;
932: }
933: # endif OOZE
934:
935: /*
936: * zapshot:
937: * Take a shot out of the air.
938: */
939: zapshot(blist, obp)
940: register BULLET *blist, *obp;
941: {
942: register BULLET *bp;
943: register FLAG explode;
944:
945: explode = FALSE;
946: for (bp = blist; bp != NULL; bp = bp->b_next) {
947: if (bp->b_x != obp->b_x || bp->b_y != obp->b_y)
948: continue;
949: if (bp->b_face == obp->b_face)
950: continue;
951: explode = TRUE;
952: break;
953: }
954: if (!explode)
955: return;
956: explshot(blist, obp->b_y, obp->b_x);
957: }
958:
959: /*
960: * explshot -
961: * Make all shots at this location blow up
962: */
963: explshot(blist, y, x)
964: register BULLET *blist;
965: register int y, x;
966: {
967: register BULLET *bp;
968:
969: for (bp = blist; bp != NULL; bp = bp->b_next)
970: if (bp->b_x == x && bp->b_y == y) {
971: bp->b_expl = TRUE;
972: if (bp->b_owner != NULL)
973: message(bp->b_owner, "Shot intercepted");
974: }
975: }
976:
977: /*
978: * play_at:
979: * Return a pointer to the player at the given location
980: */
981: PLAYER *
982: play_at(y, x)
983: register int y, x;
984: {
985: register PLAYER *pp;
986:
987: for (pp = Player; pp < End_player; pp++)
988: if (pp->p_x == x && pp->p_y == y)
989: return pp;
990: fprintf(stderr, "driver: couldn't find player at (%d,%d)\n", x, y);
991: abort();
992: /* NOTREACHED */
993: }
994:
995: /*
996: * opposite:
997: * Return TRUE if the bullet direction faces the opposite direction
998: * of the player in the maze
999: */
1000: opposite(face, dir)
1001: int face;
1002: char dir;
1003: {
1004: switch (face) {
1005: case LEFTS:
1006: return (dir == RIGHT);
1007: case RIGHT:
1008: return (dir == LEFTS);
1009: case ABOVE:
1010: return (dir == BELOW);
1011: case BELOW:
1012: return (dir == ABOVE);
1013: default:
1014: return FALSE;
1015: }
1016: }
1017:
1018: /*
1019: * is_bullet:
1020: * Is there a bullet at the given coordinates? If so, return
1021: * a pointer to the bullet, otherwise return NULL
1022: */
1023: BULLET *
1024: is_bullet(y, x)
1025: register int y, x;
1026: {
1027: register BULLET *bp;
1028:
1029: for (bp = Bullets; bp != NULL; bp = bp->b_next)
1030: if (bp->b_y == y && bp->b_x == x)
1031: return bp;
1032: return NULL;
1033: }
1034:
1035: /*
1036: * fixshots:
1037: * change the underlying character of the shots at a location
1038: * to the given character.
1039: */
1040: fixshots(y, x, over)
1041: register int y, x;
1042: char over;
1043: {
1044: register BULLET *bp;
1045:
1046: for (bp = Bullets; bp != NULL; bp = bp->b_next)
1047: if (bp->b_y == y && bp->b_x == x)
1048: bp->b_over = over;
1049: }
1050:
1051: /*
1052: * find_under:
1053: * find the underlying character for a bullet when it lands
1054: * on another bullet.
1055: */
1056: find_under(blist, bp)
1057: register BULLET *blist, *bp;
1058: {
1059: register BULLET *nbp;
1060:
1061: for (nbp = blist; nbp != NULL; nbp = nbp->b_next)
1062: if (bp->b_y == nbp->b_y && bp->b_x == nbp->b_x) {
1063: bp->b_over = nbp->b_over;
1064: break;
1065: }
1066: }
1067:
1068: /*
1069: * mark_player:
1070: * mark a player as under a shot
1071: */
1072: mark_player(bp)
1073: register BULLET *bp;
1074: {
1075: register PLAYER *pp;
1076:
1077: for (pp = Player; pp < End_player; pp++)
1078: if (pp->p_y == bp->b_y && pp->p_x == bp->b_x) {
1079: pp->p_undershot = TRUE;
1080: break;
1081: }
1082: }
1083:
1084: # ifdef BOOTS
1085: /*
1086: * mark_boot:
1087: * mark a boot as under a shot
1088: */
1089: mark_boot(bp)
1090: register BULLET *bp;
1091: {
1092: register PLAYER *pp;
1093:
1094: for (pp = Boot; pp < &Boot[NBOOTS]; pp++)
1095: if (pp->p_y == bp->b_y && pp->p_x == bp->b_x) {
1096: pp->p_undershot = TRUE;
1097: break;
1098: }
1099: }
1100: # endif BOOTS
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.