1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33: #include <sys/cdefs.h>
34: #ifndef lint
35: __RCSID("$NetBSD: shots.c,v 1.5 2004/01/27 20:30:29 jsm Exp $");
36: #endif
37:
38: # include <err.h>
39: # include <signal.h>
40: # include <stdlib.h>
41: # include "hunt.h"
42:
43: # define PLUS_DELTA(x, max) if (x < max) x++; else x--
44: # define MINUS_DELTA(x, min) if (x > min) x--; else x++
45:
46: static void chkshot(BULLET *, BULLET *);
47: static void chkslime(BULLET *, BULLET *);
48: static void explshot(BULLET *, int, int);
49: static void find_under(BULLET *, BULLET *);
50: static int iswall(int, int);
51: static void mark_boot(BULLET *);
52: static void mark_player(BULLET *);
53: #ifdef DRONE
54: static void move_drone(BULLET *);
55: #endif
56: static void move_flyer(PLAYER *);
57: static int move_normal_shot(BULLET *);
58: static void move_slime(BULLET *, int, BULLET *);
59: static void save_bullet(BULLET *);
60: static void zapshot(BULLET *, BULLET *);
61:
62:
63:
64:
65:
66: void
67: moveshots()
68: {
69: BULLET *bp, *next;
70: PLAYER *pp;
71: int x, y;
72: BULLET *blist;
73:
74: rollexpl();
75: if (Bullets == NULL)
76: goto ret;
77:
78:
79:
80:
81:
82:
83:
84:
85: blist = Bullets;
86: Bullets = NULL;
87: for (bp = blist; bp != NULL; bp = next) {
88: next = bp->b_next;
89: x = bp->b_x;
90: y = bp->b_y;
91: Maze[y][x] = bp->b_over;
92: for (pp = Player; pp < End_player; pp++)
93: check(pp, y, x);
94: # ifdef MONITOR
95: for (pp = Monitor; pp < End_monitor; pp++)
96: check(pp, y, x);
97: # endif
98:
99: switch (bp->b_type) {
100: case SHOT:
101: case GRENADE:
102: case SATCHEL:
103: case BOMB:
104: if (move_normal_shot(bp)) {
105: bp->b_next = Bullets;
106: Bullets = bp;
107: }
108: break;
109: # ifdef OOZE
110: case SLIME:
111: if (bp->b_expl || move_normal_shot(bp)) {
112: bp->b_next = Bullets;
113: Bullets = bp;
114: }
115: break;
116: # endif
117: # ifdef DRONE
118: case DSHOT:
119: if (move_drone(bp)) {
120: bp->b_next = Bullets;
121: Bullets = bp;
122: }
123: break;
124: # endif
125: default:
126: bp->b_next = Bullets;
127: Bullets = bp;
128: break;
129: }
130: }
131:
132: blist = Bullets;
133: Bullets = NULL;
134: for (bp = blist; bp != NULL; bp = next) {
135: next = bp->b_next;
136: if (!bp->b_expl) {
137: save_bullet(bp);
138: # ifdef MONITOR
139: for (pp = Monitor; pp < End_monitor; pp++)
140: check(pp, bp->b_y, bp->b_x);
141: # endif
142: # ifdef DRONE
143: if (bp->b_type == DSHOT)
144: for (pp = Player; pp < End_player; pp++)
145: if (pp->p_scan >= 0)
146: check(pp, bp->b_y, bp->b_x);
147: # endif
148: continue;
149: }
150:
151: chkshot(bp, next);
152: free((char *) bp);
153: }
154:
155: for (pp = Player; pp < End_player; pp++)
156: Maze[pp->p_y][pp->p_x] = pp->p_face;
157:
158: ret:
159: # ifdef BOOTS
160: for (pp = Boot; pp < &Boot[NBOOTS]; pp++)
161: if (pp->p_flying >= 0)
162: move_flyer(pp);
163: # endif
164: for (pp = Player; pp < End_player; pp++) {
165: # ifdef FLY
166: if (pp->p_flying >= 0)
167: move_flyer(pp);
168: # endif
169: sendcom(pp, REFRESH);
170: look(pp);
171: sendcom(pp, REFRESH);
172: }
173: # ifdef MONITOR
174: for (pp = Monitor; pp < End_monitor; pp++)
175: sendcom(pp, REFRESH);
176: # endif
177:
178: return;
179: }
180:
181:
182:
183:
184:
185: static int
186: move_normal_shot(bp)
187: BULLET *bp;
188: {
189: int i, x, y;
190: PLAYER *pp;
191:
192: for (i = 0; i < BULSPD; i++) {
193: if (bp->b_expl)
194: break;
195:
196: x = bp->b_x;
197: y = bp->b_y;
198:
199: switch (bp->b_face) {
200: case LEFTS:
201: x--;
202: break;
203: case RIGHT:
204: x++;
205: break;
206: case ABOVE:
207: y--;
208: break;
209: case BELOW:
210: y++;
211: break;
212: }
213:
214: switch (Maze[y][x]) {
215: case SHOT:
216: if (rand_num(100) < 5) {
217: zapshot(Bullets, bp);
218: zapshot(bp->b_next, bp);
219: }
220: break;
221: case GRENADE:
222: if (rand_num(100) < 10) {
223: zapshot(Bullets, bp);
224: zapshot(bp->b_next, bp);
225: }
226: break;
227: # ifdef REFLECT
228: case WALL4:
229: switch (bp->b_face) {
230: case LEFTS:
231: bp->b_face = BELOW;
232: break;
233: case RIGHT:
234: bp->b_face = ABOVE;
235: break;
236: case ABOVE:
237: bp->b_face = RIGHT;
238: break;
239: case BELOW:
240: bp->b_face = LEFTS;
241: break;
242: }
243: Maze[y][x] = WALL5;
244: # ifdef MONITOR
245: for (pp = Monitor; pp < End_monitor; pp++)
246: check(pp, y, x);
247: # endif
248: break;
249: case WALL5:
250: switch (bp->b_face) {
251: case LEFTS:
252: bp->b_face = ABOVE;
253: break;
254: case RIGHT:
255: bp->b_face = BELOW;
256: break;
257: case ABOVE:
258: bp->b_face = LEFTS;
259: break;
260: case BELOW:
261: bp->b_face = RIGHT;
262: break;
263: }
264: Maze[y][x] = WALL4;
265: # ifdef MONITOR
266: for (pp = Monitor; pp < End_monitor; pp++)
267: check(pp, y, x);
268: # endif
269: break;
270: # endif
271: # ifdef RANDOM
272: case DOOR:
273: switch (rand_num(4)) {
274: case 0:
275: bp->b_face = ABOVE;
276: break;
277: case 1:
278: bp->b_face = BELOW;
279: break;
280: case 2:
281: bp->b_face = LEFTS;
282: break;
283: case 3:
284: bp->b_face = RIGHT;
285: break;
286: }
287: break;
288: # endif
289: # ifdef FLY
290: case FLYER:
291: pp = play_at(y, x);
292: message(pp, "Zing!");
293: break;
294: # endif
295: case LEFTS:
296: case RIGHT:
297: case BELOW:
298: case ABOVE:
299:
300:
301:
302:
303: pp = play_at(y, x);
304: pp->p_ident->i_shot += bp->b_charge;
305: if (opposite(bp->b_face, Maze[y][x])) {
306: if (rand_num(100) < 10) {
307: if (bp->b_owner != NULL)
308: message(bp->b_owner,
309: "Your charge was absorbed!");
310: if (bp->b_score != NULL)
311: bp->b_score->i_robbed += bp->b_charge;
312: pp->p_ammo += bp->b_charge;
313: if (pp->p_damage + bp->b_size * MINDAM
314: > pp->p_damcap)
315: pp->p_ident->i_saved++;
316: message(pp, "Absorbed charge (good shield!)");
317: pp->p_ident->i_absorbed += bp->b_charge;
318: free((char *) bp);
319: (void) sprintf(Buf, "%3d", pp->p_ammo);
320: cgoto(pp, STAT_AMMO_ROW, STAT_VALUE_COL);
321: outstr(pp, Buf, 3);
322: return FALSE;
323: }
324: pp->p_ident->i_faced += bp->b_charge;
325: }
326:
327:
328:
329:
330:
331: if (rand_num(100) < 5) {
332: pp->p_ident->i_ducked += bp->b_charge;
333: if (pp->p_damage + bp->b_size * MINDAM
334: > pp->p_damcap)
335: pp->p_ident->i_saved++;
336: if (bp->b_score != NULL)
337: bp->b_score->i_missed += bp->b_charge;
338: message(pp, "Zing!");
339: if (bp->b_owner == NULL)
340: break;
341: message(bp->b_owner,
342: ((bp->b_score->i_missed & 0x7) == 0x7) ?
343: "My! What a bad shot you are!" :
344: "Missed him");
345: break;
346: }
347:
348:
349:
350:
351: # ifndef RANDOM
352: case DOOR:
353: # endif
354: case WALL1:
355: case WALL2:
356: case WALL3:
357: bp->b_expl = TRUE;
358: break;
359: }
360:
361: bp->b_x = x;
362: bp->b_y = y;
363: }
364: return TRUE;
365: }
366:
367: # ifdef DRONE
368:
369:
370:
371:
372: static void
373: move_drone(bp)
374: BULLET *bp;
375: {
376: int mask, count;
377: int n, dir;
378: PLAYER *pp;
379:
380:
381:
382:
383: if (is_player(Maze[bp->b_y][bp->b_x - 1])) {
384: dir = WEST;
385: goto drone_move;
386: }
387: if (is_player(Maze[bp->b_y - 1][bp->b_x])) {
388: dir = NORTH;
389: goto drone_move;
390: }
391: if (is_player(Maze[bp->b_y + 1][bp->b_x])) {
392: dir = SOUTH;
393: goto drone_move;
394: }
395: if (is_player(Maze[bp->b_y][bp->b_x + 1])) {
396: dir = EAST;
397: goto drone_move;
398: }
399:
400:
401:
402:
403: mask = count = 0;
404: if (!iswall(bp->b_y, bp->b_x - 1))
405: mask |= WEST, count++;
406: if (!iswall(bp->b_y - 1, bp->b_x))
407: mask |= NORTH, count++;
408: if (!iswall(bp->b_y + 1, bp->b_x))
409: mask |= SOUTH, count++;
410: if (!iswall(bp->b_y, bp->b_x + 1))
411: mask |= EAST, count++;
412:
413:
414:
415:
416: if (count == 0)
417: return TRUE;
418:
419:
420:
421:
422: if (count == 1) {
423: dir = mask;
424: goto drone_move;
425: }
426:
427:
428:
429:
430: switch (bp->b_face) {
431: case LEFTS:
432: if (mask & EAST)
433: mask &= ~EAST, count--;
434: break;
435: case RIGHT:
436: if (mask & WEST)
437: mask &= ~WEST, count--;
438: break;
439: case ABOVE:
440: if (mask & SOUTH)
441: mask &= ~SOUTH, count--;
442: break;
443: case BELOW:
444: if (mask & NORTH)
445: mask &= ~NORTH, count--;
446: break;
447: }
448:
449:
450:
451:
452: n = rand_num(count);
453: if (n >= 0 && mask & NORTH)
454: dir = NORTH, n--;
455: if (n >= 0 && mask & SOUTH)
456: dir = SOUTH, n--;
457: if (n >= 0 && mask & EAST)
458: dir = EAST, n--;
459: if (n >= 0 && mask & WEST)
460: dir = WEST, n--;
461:
462:
463:
464:
465:
466: drone_move:
467: switch (dir) {
468: case WEST:
469: bp->b_x--;
470: bp->b_face = LEFTS;
471: break;
472: case EAST:
473: bp->b_x++;
474: bp->b_face = RIGHT;
475: break;
476: case NORTH:
477: bp->b_y--;
478: bp->b_face = ABOVE;
479: break;
480: case SOUTH:
481: bp->b_y++;
482: bp->b_face = BELOW;
483: break;
484: }
485: switch (Maze[bp->b_y][bp->b_x]) {
486: case LEFTS:
487: case RIGHT:
488: case BELOW:
489: case ABOVE:
490:
491:
492:
493:
494: if (rand_num(100) < 1 &&
495: opposite(bp->b_face, Maze[bp->b_y][bp->b_x])) {
496: pp = play_at(bp->b_y, bp->b_x);
497: pp->p_ammo += bp->b_charge;
498: message(pp, "**** Absorbed drone ****");
499: free((char *) bp);
500: (void) sprintf(Buf, "%3d", pp->p_ammo);
501: cgoto(pp, STAT_AMMO_ROW, STAT_VALUE_COL);
502: outstr(pp, Buf, 3);
503: return FALSE;
504: }
505: bp->b_expl = TRUE;
506: break;
507: }
508: return TRUE;
509: }
510: # endif
511:
512:
513:
514:
515:
516: static void
517: save_bullet(bp)
518: BULLET *bp;
519: {
520: bp->b_over = Maze[bp->b_y][bp->b_x];
521: switch (bp->b_over) {
522: case SHOT:
523: case GRENADE:
524: case SATCHEL:
525: case BOMB:
526: # ifdef OOZE
527: case SLIME:
528: # ifdef VOLCANO
529: case LAVA:
530: # endif
531: # endif
532: # ifdef DRONE
533: case DSHOT:
534: # endif
535: find_under(Bullets, bp);
536: break;
537: }
538:
539: switch (bp->b_over) {
540: case LEFTS:
541: case RIGHT:
542: case ABOVE: