1 /* $NetBSD: execute.c,v 1.8 2009/07/04 02:37:20 dholland Exp $ */
3 * Copyright (c) 1983-2003, Regents of the University of California.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
10 * + Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * + Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * + Neither the name of the University of California, San Francisco nor
16 * the names of its contributors may be used to endorse or promote
17 * products derived from this software without specific prior written
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
21 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
23 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 #include <sys/cdefs.h>
35 __RCSID("$NetBSD: execute.c,v 1.8 2009/07/04 02:37:20 dholland Exp $");
41 static void cloak(PLAYER
*);
42 static void turn_player(PLAYER
*, int);
43 static void fire(PLAYER
*, int);
44 static void fire_slime(PLAYER
*, int);
45 static void move_player(PLAYER
*, int);
46 static void pickup(PLAYER
*, int, int, int, int);
47 static void scan(PLAYER
*);
53 * Execute a single monitor command
56 mon_execute(PLAYER
*pp
)
60 ch
= pp
->p_cbuf
[pp
->p_ncount
++];
66 (void) strcpy(pp
->p_death
, "| Quit |");
74 * Execute a single command
81 ch
= pp
->p_cbuf
[pp
->p_ncount
++];
84 if (pp
->p_flying
>= 0) {
90 (void) strcpy(pp
->p_death
, "| Quit |");
102 move_player(pp
, LEFTS
);
105 turn_player(pp
, LEFTS
);
108 move_player(pp
, BELOW
);
111 turn_player(pp
, BELOW
);
114 move_player(pp
, ABOVE
);
117 turn_player(pp
, ABOVE
);
120 move_player(pp
, RIGHT
);
123 turn_player(pp
, RIGHT
);
127 fire(pp
, 0); /* SHOT */
131 fire(pp
, 1); /* GRENADE */
135 fire(pp
, 2); /* SATCHEL */
139 fire(pp
, 3); /* 7x7 BOMB */
142 fire(pp
, 4); /* 9x9 BOMB */
145 fire(pp
, 5); /* 11x11 BOMB */
148 fire(pp
, 6); /* 13x13 BOMB */
151 fire(pp
, 7); /* 15x15 BOMB */
154 fire(pp
, 8); /* 17x17 BOMB */
157 fire(pp
, 9); /* 19x19 BOMB */
160 fire(pp
, 10); /* 21x21 BOMB */
164 fire_slime(pp
, 0); /* SLIME */
167 fire_slime(pp
, 1); /* SSLIME */
183 (void) strcpy(pp
->p_death
, "| Quit |");
190 * Execute a move in the given direction
193 move_player(PLAYER
*pp
, int dir
)
219 switch (Maze
[y
][x
]) {
236 if (dir
== pp
->p_face
)
237 pickup(pp
, y
, x
, 2, Maze
[y
][x
]);
238 else if (opposite(dir
, pp
->p_face
))
239 pickup(pp
, y
, x
, 95, Maze
[y
][x
]);
241 pickup(pp
, y
, x
, 50, Maze
[y
][x
]);
255 bp
= is_bullet(y
, x
);
265 if (dir
!= pp
->p_face
)
268 newp
= play_at(y
, x
);
269 checkdam(newp
, pp
, pp
->p_ident
, STABDAM
, KNIFE
);
274 newp
= play_at(y
, x
);
275 message(newp
, "Oooh, there's a short guy waving at you!");
276 message(pp
, "You couldn't quite reach him!");
282 if (Maze
[y
][x
] == BOOT
)
286 for (newp
= Boot
; newp
< &Boot
[NBOOTS
]; newp
++) {
287 if (newp
->p_flying
< 0)
289 if (newp
->p_y
== y
&& newp
->p_x
== x
) {
291 if (newp
->p_undershot
)
292 fixshots(y
, x
, newp
->p_over
);
295 if (pp
->p_nboots
== 2)
296 message(pp
, "Wow! A pair of boots!");
298 message(pp
, "You can hobble around on one boot.");
305 if (pp
->p_ncshot
> 0)
306 if (--pp
->p_ncshot
== MAXNCSHOT
) {
307 cgoto(pp
, STAT_GUN_ROW
, STAT_VALUE_COL
);
308 outstr(pp
, " ok", 3);
310 if (pp
->p_undershot
) {
311 fixshots(pp
->p_y
, pp
->p_x
, pp
->p_over
);
312 pp
->p_undershot
= FALSE
;
314 drawplayer(pp
, FALSE
);
315 pp
->p_over
= Maze
[y
][x
];
318 drawplayer(pp
, TRUE
);
324 * Change the direction the player is facing
327 turn_player(PLAYER
*pp
, int dir
)
329 if (pp
->p_face
!= dir
) {
331 drawplayer(pp
, TRUE
);
337 * Fire a shot of the given type in the given direction
340 fire(PLAYER
*pp
, int req_index
)
345 if (req_index
< 0 || req_index
>= MAXBOMB
)
346 message(pp
, "What you do?");
348 while (req_index
>= 0 && pp
->p_ammo
< shot_req
[req_index
])
351 message(pp
, "Not enough charges.");
354 if (pp
->p_ncshot
> MAXNCSHOT
)
356 if (pp
->p_ncshot
++ == MAXNCSHOT
) {
357 cgoto(pp
, STAT_GUN_ROW
, STAT_VALUE_COL
);
360 pp
->p_ammo
-= shot_req
[req_index
];
361 (void) snprintf(Buf
, sizeof(Buf
), "%3d", pp
->p_ammo
);
362 cgoto(pp
, STAT_AMMO_ROW
, STAT_VALUE_COL
);
365 add_shot(shot_type
[req_index
], pp
->p_y
, pp
->p_x
, pp
->p_face
,
366 shot_req
[req_index
], pp
, FALSE
, pp
->p_face
);
367 pp
->p_undershot
= TRUE
;
370 * Show the object to everyone
372 showexpl(pp
->p_y
, pp
->p_x
, shot_type
[req_index
]);
373 for (pp
= Player
; pp
< End_player
; pp
++)
374 sendcom(pp
, REFRESH
);
376 for (pp
= Monitor
; pp
< End_monitor
; pp
++)
377 sendcom(pp
, REFRESH
);
384 * Fire a slime shot in the given direction
387 fire_slime(PLAYER
*pp
, int req_index
)
392 if (req_index
< 0 || req_index
>= MAXSLIME
)
393 message(pp
, "What you do?");
395 while (req_index
>= 0 && pp
->p_ammo
< slime_req
[req_index
])
398 message(pp
, "Not enough charges.");
401 if (pp
->p_ncshot
> MAXNCSHOT
)
403 if (pp
->p_ncshot
++ == MAXNCSHOT
) {
404 cgoto(pp
, STAT_GUN_ROW
, STAT_VALUE_COL
);
407 pp
->p_ammo
-= slime_req
[req_index
];
408 (void) snprintf(Buf
, sizeof(Buf
), "%3d", pp
->p_ammo
);
409 cgoto(pp
, STAT_AMMO_ROW
, STAT_VALUE_COL
);
412 add_shot(SLIME
, pp
->p_y
, pp
->p_x
, pp
->p_face
,
413 slime_req
[req_index
] * SLIME_FACTOR
, pp
, FALSE
, pp
->p_face
);
414 pp
->p_undershot
= TRUE
;
417 * Show the object to everyone
419 showexpl(pp
->p_y
, pp
->p_x
, SLIME
);
420 for (pp
= Player
; pp
< End_player
; pp
++)
421 sendcom(pp
, REFRESH
);
423 for (pp
= Monitor
; pp
< End_monitor
; pp
++)
424 sendcom(pp
, REFRESH
);
431 * Create a shot with the given properties
434 add_shot(int type
, int y
, int x
, char face
, int charge
,
435 PLAYER
*owner
, int expl
, char over
)
453 for (size
= 3; size
< MAXBOMB
; size
++)
454 if (shot_req
[size
] >= charge
)
463 bp
= create_shot(type
, y
, x
, face
, charge
, size
, owner
,
464 (owner
== NULL
) ? NULL
: owner
->p_ident
, expl
, over
);
465 bp
->b_next
= Bullets
;
470 create_shot(int type
, int y
, int x
, char face
, int charge
,
471 int size
, PLAYER
*owner
, IDENT
*score
, int expl
, char over
)
475 bp
= malloc(sizeof(*bp
));
478 message(owner
, "Out of memory");
485 bp
->b_charge
= charge
;
499 * Turn on or increase length of a cloak
504 if (pp
->p_ammo
<= 0) {
505 message(pp
, "No more charges");
509 if (pp
->p_nboots
> 0) {
510 message(pp
, "Boots are too noisy to cloak!");
514 (void) snprintf(Buf
, sizeof(Buf
), "%3d", --pp
->p_ammo
);
515 cgoto(pp
, STAT_AMMO_ROW
, STAT_VALUE_COL
);
518 pp
->p_cloak
+= CLOAKLEN
;
528 * Turn on or increase length of a scan
533 if (pp
->p_ammo
<= 0) {
534 message(pp
, "No more charges");
537 (void) snprintf(Buf
, sizeof(Buf
), "%3d", --pp
->p_ammo
);
538 cgoto(pp
, STAT_AMMO_ROW
, STAT_VALUE_COL
);
541 pp
->p_scan
+= SCANLEN
;
543 if (pp
->p_cloak
>= 0)
551 * check whether the object blew up or whether he picked it up
554 pickup(PLAYER
*pp
, int y
, int x
, int prob
, int obj
)
568 if (rand_num(100) < prob
)
569 add_shot(obj
, y
, x
, LEFTS
, req
, (PLAYER
*) NULL
,
573 (void) snprintf(Buf
, sizeof(Buf
), "%3d", pp
->p_ammo
);
574 cgoto(pp
, STAT_AMMO_ROW
, STAT_VALUE_COL
);