]>
git.cameronkatri.com Git - bsdgames-darwin.git/blob - hunt/huntd/shots.c
1 /* $NetBSD: shots.c,v 1.3 1997/10/11 08:13:50 lukem Exp $ */
4 * Copyright (c) 1985 Conrad C. Huang, Gregory S. Couch, Kenneth C.R.C. Arnold
5 * San Francisco, California
10 __RCSID("$NetBSD: shots.c,v 1.3 1997/10/11 08:13:50 lukem Exp $");
18 # define PLUS_DELTA(x, max) if (x < max) x++; else x--
19 # define MINUS_DELTA(x, min) if (x > min) x--; else x++
21 static void chkshot
__P((BULLET
*, BULLET
*));
22 static void chkslime
__P((BULLET
*, BULLET
*));
23 static void explshot
__P((BULLET
*, int, int));
24 static void find_under
__P((BULLET
*, BULLET
*));
25 static int iswall
__P((int, int));
26 static void mark_boot
__P((BULLET
*));
27 static void mark_player
__P((BULLET
*));
29 static void move_drone
__P((BULLET
*));
31 static void move_flyer
__P((PLAYER
*));
32 static int move_normal_shot
__P((BULLET
*));
33 static void move_slime
__P((BULLET
*, int, BULLET
*));
34 static void save_bullet
__P((BULLET
*));
35 static void zapshot
__P((BULLET
*, BULLET
*));
39 * Move the shots already in the air, taking explosions into account
54 * First we move through the bullet list BULSPD times, looking
55 * for things we may have run into. If we do run into
56 * something, we set up the explosion and disappear, checking
57 * for damage to any player who got in the way.
62 for (bp
= blist
; bp
!= NULL
; bp
= next
) {
66 Maze
[y
][x
] = bp
->b_over
;
67 for (pp
= Player
; pp
< End_player
; pp
++)
70 for (pp
= Monitor
; pp
< End_monitor
; pp
++)
79 if (move_normal_shot(bp
)) {
86 if (bp
->b_expl
|| move_normal_shot(bp
)) {
101 bp
->b_next
= Bullets
;
109 for (bp
= blist
; bp
!= NULL
; bp
= next
) {
114 for (pp
= Monitor
; pp
< End_monitor
; pp
++)
115 check(pp
, bp
->b_y
, bp
->b_x
);
118 if (bp
->b_type
== DSHOT
)
119 for (pp
= Player
; pp
< End_player
; pp
++)
121 check(pp
, bp
->b_y
, bp
->b_x
);
130 for (pp
= Player
; pp
< End_player
; pp
++)
131 Maze
[pp
->p_y
][pp
->p_x
] = pp
->p_face
;
135 for (pp
= Boot
; pp
< &Boot
[NBOOTS
]; pp
++)
136 if (pp
->p_flying
>= 0)
139 for (pp
= Player
; pp
< End_player
; pp
++) {
141 if (pp
->p_flying
>= 0)
144 sendcom(pp
, REFRESH
); /* Flush out the explosions */
146 sendcom(pp
, REFRESH
);
149 for (pp
= Monitor
; pp
< End_monitor
; pp
++)
150 sendcom(pp
, REFRESH
);
158 * Move a normal shot along its trajectory
167 for (i
= 0; i
< BULSPD
; i
++) {
174 switch (bp
->b_face
) {
189 switch (Maze
[y
][x
]) {
191 if (rand_num(100) < 5) {
192 zapshot(Bullets
, bp
);
193 zapshot(bp
->b_next
, bp
);
197 if (rand_num(100) < 10) {
198 zapshot(Bullets
, bp
);
199 zapshot(bp
->b_next
, bp
);
203 case WALL4
: /* reflecting walls */
204 switch (bp
->b_face
) {
220 for (pp
= Monitor
; pp
< End_monitor
; pp
++)
225 switch (bp
->b_face
) {
241 for (pp
= Monitor
; pp
< End_monitor
; pp
++)
248 switch (rand_num(4)) {
267 message(pp
, "Zing!");
275 * give the person a chance to catch a
276 * grenade if s/he is facing it
279 pp
->p_ident
->i_shot
+= bp
->b_charge
;
280 if (opposite(bp
->b_face
, Maze
[y
][x
])) {
281 if (rand_num(100) < 10) {
282 if (bp
->b_owner
!= NULL
)
284 "Your charge was absorbed!");
285 if (bp
->b_score
!= NULL
)
286 bp
->b_score
->i_robbed
+= bp
->b_charge
;
287 pp
->p_ammo
+= bp
->b_charge
;
288 if (pp
->p_damage
+ bp
->b_size
* MINDAM
290 pp
->p_ident
->i_saved
++;
291 message(pp
, "Absorbed charge (good shield!)");
292 pp
->p_ident
->i_absorbed
+= bp
->b_charge
;
294 (void) sprintf(Buf
, "%3d", pp
->p_ammo
);
295 cgoto(pp
, STAT_AMMO_ROW
, STAT_VALUE_COL
);
299 pp
->p_ident
->i_faced
+= bp
->b_charge
;
302 * Small chance that the bullet just misses the
303 * person. If so, the bullet just goes on its
304 * merry way without exploding.
306 if (rand_num(100) < 5) {
307 pp
->p_ident
->i_ducked
+= bp
->b_charge
;
308 if (pp
->p_damage
+ bp
->b_size
* MINDAM
310 pp
->p_ident
->i_saved
++;
311 if (bp
->b_score
!= NULL
)
312 bp
->b_score
->i_missed
+= bp
->b_charge
;
313 message(pp
, "Zing!");
314 if (bp
->b_owner
== NULL
)
317 ((bp
->b_score
->i_missed
& 0x7) == 0x7) ?
318 "My! What a bad shot you are!" :
323 * The shot hit that sucker! Blow it up.
345 * Move the drone to the next square
356 * See if we can give someone a blast
358 if (isplayer(Maze
[bp
->b_y
][bp
->b_x
- 1])) {
362 if (isplayer(Maze
[bp
->b_y
- 1][bp
->b_x
])) {
366 if (isplayer(Maze
[bp
->b_y
+ 1][bp
->b_x
])) {
370 if (isplayer(Maze
[bp
->b_y
][bp
->b_x
+ 1])) {
376 * Find out what directions are clear
379 if (!iswall(bp
->b_y
, bp
->b_x
- 1))
380 mask
|= WEST
, count
++;
381 if (!iswall(bp
->b_y
- 1, bp
->b_x
))
382 mask
|= NORTH
, count
++;
383 if (!iswall(bp
->b_y
+ 1, bp
->b_x
))
384 mask
|= SOUTH
, count
++;
385 if (!iswall(bp
->b_y
, bp
->b_x
+ 1))
386 mask
|= EAST
, count
++;
389 * All blocked up, just you wait
395 * Only one way to go.
403 * Get rid of the direction that we came from
405 switch (bp
->b_face
) {
408 mask
&= ~EAST
, count
--;
412 mask
&= ~WEST
, count
--;
416 mask
&= ~SOUTH
, count
--;
420 mask
&= ~NORTH
, count
--;
425 * Pick one of the remaining directions
428 if (n
>= 0 && mask
& NORTH
)
430 if (n
>= 0 && mask
& SOUTH
)
432 if (n
>= 0 && mask
& EAST
)
434 if (n
>= 0 && mask
& WEST
)
438 * Now that we know the direction of movement,
439 * just update the position of the drone
460 switch (Maze
[bp
->b_y
][bp
->b_x
]) {
466 * give the person a chance to catch a
467 * drone if s/he is facing it
469 if (rand_num(100) < 1 &&
470 opposite(bp
->b_face
, Maze
[bp
->b_y
][bp
->b_x
])) {
471 pp
= play_at(bp
->b_y
, bp
->b_x
);
472 pp
->p_ammo
+= bp
->b_charge
;
473 message(pp
, "**** Absorbed drone ****");
475 (void) sprintf(Buf
, "%3d", pp
->p_ammo
);
476 cgoto(pp
, STAT_AMMO_ROW
, STAT_VALUE_COL
);
489 * Put this bullet back onto the bullet list
495 bp
->b_over
= Maze
[bp
->b_y
][bp
->b_x
];
496 switch (bp
->b_over
) {
510 find_under(Bullets
, bp
);
514 switch (bp
->b_over
) {
531 Maze
[bp
->b_y
][bp
->b_x
] = bp
->b_type
;
535 bp
->b_next
= Bullets
;
541 * Update the position of a player in flight
549 if (pp
->p_undershot
) {
550 fixshots(pp
->p_y
, pp
->p_x
, pp
->p_over
);
551 pp
->p_undershot
= FALSE
;
553 Maze
[pp
->p_y
][pp
->p_x
] = pp
->p_over
;
554 x
= pp
->p_x
+ pp
->p_flyx
;
555 y
= pp
->p_y
+ pp
->p_flyy
;
558 pp
->p_flyx
= -pp
->p_flyx
;
560 else if (x
> WIDTH
- 2) {
561 x
= (WIDTH
- 2) - (x
- (WIDTH
- 2));
562 pp
->p_flyx
= -pp
->p_flyx
;
566 pp
->p_flyy
= -pp
->p_flyy
;
568 else if (y
> HEIGHT
- 2) {
569 y
= (HEIGHT
- 2) - (y
- (HEIGHT
- 2));
570 pp
->p_flyy
= -pp
->p_flyy
;
573 switch (Maze
[y
][x
]) {
575 switch (rand_num(4)) {
577 PLUS_DELTA(x
, WIDTH
- 2);
583 PLUS_DELTA(y
, HEIGHT
- 2);
600 if (pp
->p_flying
== 0)
608 if (pp
->p_flying
-- == 0) {
610 if (pp
->p_face
!= BOOT
&& pp
->p_face
!= BOOT_PAIR
) {
612 checkdam(pp
, (PLAYER
*) NULL
, (IDENT
*) NULL
,
613 rand_num(pp
->p_damage
/ 5), FALL
);
614 pp
->p_face
= rand_dir();
619 if (Maze
[y
][x
] == BOOT
)
620 pp
->p_face
= BOOT_PAIR
;
625 pp
->p_over
= Maze
[y
][x
];
626 Maze
[y
][x
] = pp
->p_face
;
627 showexpl(y
, x
, pp
->p_face
);
646 switch (bp
->b_type
) {
653 delta
= bp
->b_size
- 1;
670 for (y
= bp
->b_y
- delta
; y
<= bp
->b_y
+ delta
; y
++) {
671 if (y
< 0 || y
>= HEIGHT
)
674 absdy
= (dy
< 0) ? -dy
: dy
;
675 for (x
= bp
->b_x
- delta
; x
<= bp
->b_x
+ delta
; x
++) {
676 if (x
< 0 || x
>= WIDTH
)
680 expl
= (dy
== 0) ? '*' : '|';
689 showexpl(y
, x
, expl
);
690 switch (Maze
[y
][x
]) {
701 damage
= bp
->b_size
- absdy
;
703 damage
= bp
->b_size
- dx
;
705 checkdam(pp
, bp
->b_owner
, bp
->b_score
,
706 damage
* MINDAM
, bp
->b_type
);
710 add_shot((Maze
[y
][x
] == GMINE
) ?
713 (Maze
[y
][x
] == GMINE
) ?
715 (PLAYER
*) NULL
, TRUE
, SPACE
);
726 * handle slime shot exploding
735 switch (Maze
[bp
->b_y
][bp
->b_x
]) {
746 switch (bp
->b_face
) {
762 nbp
= (BULLET
*) malloc(sizeof (BULLET
));
765 move_slime(nbp
, nbp
->b_type
== SLIME
? SLIMESPEED
: LAVASPEED
, next
);
767 move_slime(nbp
, SLIMESPEED
, next
);
773 * move the given slime shot speed times and add it back if
774 * it hasn't fizzled yet
777 move_slime(bp
, speed
, next
)
782 int i
, j
, dirmask
, count
;
787 if (bp
->b_charge
<= 0)
795 showexpl(bp
->b_y
, bp
->b_x
, bp
->b_type
== LAVA
? LAVA
: '*');
797 showexpl(bp
->b_y
, bp
->b_x
, '*');
799 switch (Maze
[bp
->b_y
][bp
->b_x
]) {
807 pp
= play_at(bp
->b_y
, bp
->b_x
);
808 message(pp
, "You've been slimed.");
809 checkdam(pp
, bp
->b_owner
, bp
->b_score
, MINDAM
, bp
->b_type
);
818 explshot(next
, bp
->b_y
, bp
->b_x
);
819 explshot(Bullets
, bp
->b_y
, bp
->b_x
);
823 if (--bp
->b_charge
<= 0) {
830 switch (bp
->b_face
) {
832 if (!iswall(bp
->b_y
, bp
->b_x
- 1))
833 dirmask
|= WEST
, count
++;
834 if (!iswall(bp
->b_y
- 1, bp
->b_x
))
835 dirmask
|= NORTH
, count
++;
836 if (!iswall(bp
->b_y
+ 1, bp
->b_x
))
837 dirmask
|= SOUTH
, count
++;
839 if (!iswall(bp
->b_y
, bp
->b_x
+ 1))
840 dirmask
|= EAST
, count
++;
843 if (!iswall(bp
->b_y
, bp
->b_x
+ 1))
844 dirmask
|= EAST
, count
++;
845 if (!iswall(bp
->b_y
- 1, bp
->b_x
))
846 dirmask
|= NORTH
, count
++;
847 if (!iswall(bp
->b_y
+ 1, bp
->b_x
))
848 dirmask
|= SOUTH
, count
++;
850 if (!iswall(bp
->b_y
, bp
->b_x
- 1))
851 dirmask
|= WEST
, count
++;
854 if (!iswall(bp
->b_y
- 1, bp
->b_x
))
855 dirmask
|= NORTH
, count
++;
856 if (!iswall(bp
->b_y
, bp
->b_x
- 1))
857 dirmask
|= WEST
, count
++;
858 if (!iswall(bp
->b_y
, bp
->b_x
+ 1))
859 dirmask
|= EAST
, count
++;
861 if (!iswall(bp
->b_y
+ 1, bp
->b_x
))
862 dirmask
|= SOUTH
, count
++;
865 if (!iswall(bp
->b_y
+ 1, bp
->b_x
))
866 dirmask
|= SOUTH
, count
++;
867 if (!iswall(bp
->b_y
, bp
->b_x
- 1))
868 dirmask
|= WEST
, count
++;
869 if (!iswall(bp
->b_y
, bp
->b_x
+ 1))
870 dirmask
|= EAST
, count
++;
872 if (!iswall(bp
->b_y
- 1, bp
->b_x
))
873 dirmask
|= NORTH
, count
++;
878 * No place to go. Just sit here for a while and wait
879 * for adjacent squares to clear out.
884 if (bp
->b_charge
< count
) {
885 /* Only bp->b_charge paths may be taken */
886 while (count
> bp
->b_charge
) {
889 else if (dirmask
& EAST
)
891 else if (dirmask
& NORTH
)
893 else if (dirmask
& SOUTH
)
899 i
= bp
->b_charge
/ count
;
900 j
= bp
->b_charge
% count
;
901 if (dirmask
& WEST
) {
903 nbp
= create_shot(bp
->b_type
, bp
->b_y
, bp
->b_x
- 1, LEFTS
,
904 i
, bp
->b_size
, bp
->b_owner
, bp
->b_score
, TRUE
, SPACE
);
905 move_slime(nbp
, speed
- 1, next
);
907 if (dirmask
& EAST
) {
909 nbp
= create_shot(bp
->b_type
, bp
->b_y
, bp
->b_x
+ 1, RIGHT
,
910 (count
< j
) ? i
+ 1 : i
, bp
->b_size
, bp
->b_owner
,
911 bp
->b_score
, TRUE
, SPACE
);
912 move_slime(nbp
, speed
- 1, next
);
914 if (dirmask
& NORTH
) {
916 nbp
= create_shot(bp
->b_type
, bp
->b_y
- 1, bp
->b_x
, ABOVE
,
917 (count
< j
) ? i
+ 1 : i
, bp
->b_size
, bp
->b_owner
,
918 bp
->b_score
, TRUE
, SPACE
);
919 move_slime(nbp
, speed
- 1, next
);
921 if (dirmask
& SOUTH
) {
923 nbp
= create_shot(bp
->b_type
, bp
->b_y
+ 1, bp
->b_x
, BELOW
,
924 (count
< j
) ? i
+ 1 : i
, bp
->b_size
, bp
->b_owner
,
925 bp
->b_score
, TRUE
, SPACE
);
926 move_slime(nbp
, speed
- 1, next
);
934 * returns whether the given location is a wall
940 if (y
< 0 || x
< 0 || y
>= HEIGHT
|| x
>= WIDTH
)
942 switch (Maze
[y
][x
]) {
967 * Take a shot out of the air.
977 for (bp
= blist
; bp
!= NULL
; bp
= bp
->b_next
) {
978 if (bp
->b_x
!= obp
->b_x
|| bp
->b_y
!= obp
->b_y
)
980 if (bp
->b_face
== obp
->b_face
)
987 explshot(blist
, obp
->b_y
, obp
->b_x
);
992 * Make all shots at this location blow up
995 explshot(blist
, y
, x
)
1001 for (bp
= blist
; bp
!= NULL
; bp
= bp
->b_next
)
1002 if (bp
->b_x
== x
&& bp
->b_y
== y
) {
1004 if (bp
->b_owner
!= NULL
)
1005 message(bp
->b_owner
, "Shot intercepted");
1011 * Return a pointer to the player at the given location
1019 for (pp
= Player
; pp
< End_player
; pp
++)
1020 if (pp
->p_x
== x
&& pp
->p_y
== y
)
1022 errx(1, "driver: couldn't find player at (%d,%d)", x
, y
);
1028 * Return TRUE if the bullet direction faces the opposite direction
1029 * of the player in the maze
1038 return (dir
== RIGHT
);
1040 return (dir
== LEFTS
);
1042 return (dir
== BELOW
);
1044 return (dir
== ABOVE
);
1052 * Is there a bullet at the given coordinates? If so, return
1053 * a pointer to the bullet, otherwise return NULL
1061 for (bp
= Bullets
; bp
!= NULL
; bp
= bp
->b_next
)
1062 if (bp
->b_y
== y
&& bp
->b_x
== x
)
1069 * change the underlying character of the shots at a location
1070 * to the given character.
1073 fixshots(y
, x
, over
)
1079 for (bp
= Bullets
; bp
!= NULL
; bp
= bp
->b_next
)
1080 if (bp
->b_y
== y
&& bp
->b_x
== x
)
1086 * find the underlying character for a bullet when it lands
1087 * on another bullet.
1090 find_under(blist
, bp
)
1095 for (nbp
= blist
; nbp
!= NULL
; nbp
= nbp
->b_next
)
1096 if (bp
->b_y
== nbp
->b_y
&& bp
->b_x
== nbp
->b_x
) {
1097 bp
->b_over
= nbp
->b_over
;
1104 * mark a player as under a shot
1112 for (pp
= Player
; pp
< End_player
; pp
++)
1113 if (pp
->p_y
== bp
->b_y
&& pp
->p_x
== bp
->b_x
) {
1114 pp
->p_undershot
= TRUE
;
1122 * mark a boot as under a shot
1130 for (pp
= Boot
; pp
< &Boot
[NBOOTS
]; pp
++)
1131 if (pp
->p_y
== bp
->b_y
&& pp
->p_x
== bp
->b_x
) {
1132 pp
->p_undershot
= TRUE
;