2 * Copyright (c) 1983-2003, Regents of the University of California.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of the University of California, San Francisco nor
15 * the names of its contributors may be used to endorse or promote
16 * products derived from this software without specific prior written
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
20 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
22 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 * $OpenBSD: execute.c,v 1.8 2004/01/16 00:13:19 espie Exp $
32 * $NetBSD: execute.c,v 1.2 1997/10/10 16:33:13 lukem Exp $
33 * $DragonFly: src/games/hunt/huntd/execute.c,v 1.2 2008/09/04 16:12:51 swildner Exp $
43 static void cloak(PLAYER
*);
44 static void face(PLAYER
*, int);
45 static void fire(PLAYER
*, int);
46 static void fire_slime(PLAYER
*, int);
47 static void move_player(PLAYER
*, int);
48 static void pickup(PLAYER
*, int, int, int, int);
49 static void scan(PLAYER
*);
54 * Execute a single monitor command
57 mon_execute(PLAYER
*pp
)
61 ch
= pp
->p_cbuf
[pp
->p_ncount
++];
65 /* Redraw messed-up screen */
70 (void) strlcpy(pp
->p_death
, "| Quit |", sizeof pp
->p_death
);
73 /* Ignore everything else */
80 * Execute a single command from a player
87 ch
= pp
->p_cbuf
[pp
->p_ncount
++];
89 /* When flying, only allow refresh and quit. */
90 if (pp
->p_flying
>= 0) {
96 (void) strlcpy(pp
->p_death
, "| Quit |",
103 /* Decode the command character: */
106 sendcom(pp
, REDRAW
); /* Refresh */
109 move_player(pp
, LEFTS
); /* Move left */
112 face(pp
, LEFTS
); /* Face left */
115 move_player(pp
, BELOW
); /* Move down */
118 face(pp
, BELOW
); /* Face down */
121 move_player(pp
, ABOVE
); /* Move up */
124 face(pp
, ABOVE
); /* Face up */
127 move_player(pp
, RIGHT
); /* Move right */
130 face(pp
, RIGHT
); /* Face right */
134 fire(pp
, 0); /* SHOT */
138 fire(pp
, 1); /* GRENADE */
142 fire(pp
, 2); /* SATCHEL */
146 fire(pp
, 3); /* 7x7 BOMB */
149 fire(pp
, 4); /* 9x9 BOMB */
152 fire(pp
, 5); /* 11x11 BOMB */
155 fire(pp
, 6); /* 13x13 BOMB */
158 fire(pp
, 7); /* 15x15 BOMB */
161 fire(pp
, 8); /* 17x17 BOMB */
164 fire(pp
, 9); /* 19x19 BOMB */
167 fire(pp
, 10); /* 21x21 BOMB */
170 fire_slime(pp
, 0); /* SLIME */
173 fire_slime(pp
, 1); /* SSLIME */
176 fire_slime(pp
, 2); /* large slime */
179 fire_slime(pp
, 3); /* very large slime */
181 case 's': /* start scanning */
184 case 'c': /* start cloaking */
188 (void) strlcpy(pp
->p_death
, "| Quit |", sizeof pp
->p_death
);
195 * Try to move player 'pp' in direction 'dir'.
198 move_player(PLAYER
*pp
, int dir
)
225 /* What would the player move over: */
226 switch (Maze
[y
][x
]) {
227 /* Players can move through spaces and doors, no problem: */
232 /* Can't move through walls: */
239 /* Moving over a mine - try to pick it up: */
242 if (dir
== pp
->p_face
)
243 /* facing it: 2% chance of trip */
244 pickup(pp
, y
, x
, conf_ptrip_face
, Maze
[y
][x
]);
245 else if (opposite(dir
, pp
->p_face
))
246 /* facing away: 95% chance of trip */
247 pickup(pp
, y
, x
, conf_ptrip_back
, Maze
[y
][x
]);
249 /* facing sideways: 50% chance of trip */
250 pickup(pp
, y
, x
, conf_ptrip_side
, Maze
[y
][x
]);
251 /* Remove the mine: */
255 /* Moving into a bullet: */
262 /* Find which bullet: */
263 bp
= is_bullet(y
, x
);
271 /* Moving into another player: */
276 if (dir
!= pp
->p_face
)
277 /* Can't walk backwards/sideways into another player: */
280 /* Stab the other player */
281 newp
= play_at(y
, x
);
282 checkdam(newp
, pp
, pp
->p_ident
, conf_stabdam
, KNIFE
);
285 /* Moving into a player flying overhead: */
287 newp
= play_at(y
, x
);
288 message(newp
, "Oooh, there's a short guy waving at you!");
289 message(pp
, "You couldn't quite reach him!");
291 /* Picking up a boot, or two: */
296 for (newp
= Boot
; newp
< &Boot
[NBOOTS
]; newp
++) {
297 if (newp
->p_flying
< 0)
299 if (newp
->p_y
== y
&& newp
->p_x
== x
) {
301 if (newp
->p_undershot
)
302 fixshots(y
, x
, newp
->p_over
);
305 if (pp
->p_nboots
== 2)
306 message(pp
, "Wow! A pair of boots!");
308 message(pp
, "You can hobble around on one boot.");
314 /* Can the player be moved? */
316 /* Check the gun status: */
317 if (pp
->p_ncshot
> 0)
318 if (--pp
->p_ncshot
== conf_maxncshot
)
319 outyx(pp
, STAT_GUN_ROW
, STAT_VALUE_COL
, " ok");
320 /* Check for bullets flying past: */
321 if (pp
->p_undershot
) {
322 fixshots(pp
->p_y
, pp
->p_x
, pp
->p_over
);
323 pp
->p_undershot
= FALSE
;
325 /* Erase the player: */
326 drawplayer(pp
, FALSE
);
328 pp
->p_over
= Maze
[y
][x
];
329 /* Move the player: */
332 /* Draw the player in their new position */
333 drawplayer(pp
, TRUE
);
339 * Change the direction the player is facing
342 face(PLAYER
*pp
, int dir
)
344 if (pp
->p_face
!= dir
) {
346 drawplayer(pp
, TRUE
);
352 * Fire a shot of the given type in the given direction
355 fire(PLAYER
*pp
, int req_index
)
360 /* Drop the shot type down until we can afford it: */
361 while (req_index
>= 0 && pp
->p_ammo
< shot_req
[req_index
])
364 /* Can we shoot at all? */
366 message(pp
, "Not enough charges.");
370 /* Check if the gun is too hot: */
371 if (pp
->p_ncshot
> conf_maxncshot
)
374 /* Heat up the gun: */
375 if (pp
->p_ncshot
++ == conf_maxncshot
) {
376 /* The gun has overheated: */
377 outyx(pp
, STAT_GUN_ROW
, STAT_VALUE_COL
, " ");
380 /* Use up some ammo: */
381 pp
->p_ammo
-= shot_req
[req_index
];
384 /* Start the bullet moving: */
385 add_shot(shot_type
[req_index
], pp
->p_y
, pp
->p_x
, pp
->p_face
,
386 shot_req
[req_index
], pp
, FALSE
, pp
->p_face
);
387 pp
->p_undershot
= TRUE
;
389 /* Show the bullet to everyone: */
390 showexpl(pp
->p_y
, pp
->p_x
, shot_type
[req_index
]);
391 sendcom(ALL_PLAYERS
, REFRESH
);
396 * Fire a slime shot in the given direction
399 fire_slime(PLAYER
*pp
, int req_index
)
404 /* Check configuration: */
408 /* Drop the slime type back util we can afford it: */
409 while (req_index
>= 0 && pp
->p_ammo
< slime_req
[req_index
])
412 /* Can we afford to slime at all? */
414 message(pp
, "Not enough charges.");
418 /* Is the gun too hot? */
419 if (pp
->p_ncshot
> conf_maxncshot
)
422 /* Heat up the gun: */
423 if (pp
->p_ncshot
++ == conf_maxncshot
) {
424 /* The gun has overheated: */
425 outyx(pp
, STAT_GUN_ROW
, STAT_VALUE_COL
, " ");
428 /* Use up some ammo: */
429 pp
->p_ammo
-= slime_req
[req_index
];
432 /* Start the slime moving: */
433 add_shot(SLIME
, pp
->p_y
, pp
->p_x
, pp
->p_face
,
434 slime_req
[req_index
] * conf_slimefactor
, pp
, FALSE
, pp
->p_face
);
435 pp
->p_undershot
= TRUE
;
437 /* Show the object to everyone: */
438 showexpl(pp
->p_y
, pp
->p_x
, SLIME
);
439 sendcom(ALL_PLAYERS
, REFRESH
);
444 * Create a shot with the given properties
447 add_shot(int type
, int y
, int x
, char wface
, int charge
, PLAYER
*owner
,
453 /* Determine the bullet's size based on its type and charge: */
467 for (size
= 3; size
< MAXBOMB
; size
++)
468 if (shot_req
[size
] >= charge
)
477 /* Create the bullet: */
478 bp
= create_shot(type
, y
, x
, wface
, charge
, size
, owner
,
479 (owner
== NULL
) ? NULL
: owner
->p_ident
, expl
, over
);
481 /* Insert the bullet into the front of the bullet list: */
482 bp
->b_next
= Bullets
;
488 * allocate storage for an (unlinked) bullet structure;
489 * initialize and return it
492 create_shot(int type
, int y
, int x
, char wface
, int charge
, int size
,
493 PLAYER
*owner
, IDENT
*score
, int expl
, char over
)
497 bp
= (BULLET
*) malloc(sizeof (BULLET
)); /* NOSTRICT */
499 logit(LOG_ERR
, "malloc");
501 message(owner
, "Out of memory");
508 bp
->b_charge
= charge
;
522 * Turn on or increase length of a cloak
527 /* Check configuration: */
531 /* Can we afford it?: */
532 if (pp
->p_ammo
<= 0) {
533 message(pp
, "No more charges");
537 /* Can't cloak with boots: */
538 if (pp
->p_nboots
> 0) {
539 message(pp
, "Boots are too noisy to cloak!");
543 /* Consume a unit of ammo: */
547 /* Add to the duration of a cloak: */
548 pp
->p_cloak
+= conf_cloaklen
;
550 /* Disable scan, if enabled: */
554 /* Re-draw the player's scan/cloak status: */
560 * Turn on or increase length of a scan
565 /* Check configuration: */
569 /* Can we afford it?: */
570 if (pp
->p_ammo
<= 0) {
571 message(pp
, "No more charges");
575 /* Consume one unit of ammo: */
579 /* Increase the scan time: */
580 pp
->p_scan
+= Nplayer
* conf_scanlen
;
582 /* Disable cloak, if enabled: */
583 if (pp
->p_cloak
>= 0)
586 /* Re-draw the player's scan/cloak status: */
592 * pick up a mine or grenade, with some probability of it exploding
595 pickup(PLAYER
*pp
, int y
, int x
, int prob
, int obj
)
599 /* Figure out how much ammo the player is trying to pick up: */
614 /* Does it explode? */
615 if (rand_num(100) < prob
)
616 /* Ooooh, unlucky: (Boom) */
617 add_shot(obj
, y
, x
, LEFTS
, req
, NULL
, TRUE
, pp
->p_face
);
619 /* Safely picked it up. Add to player's ammo: */
626 ammo_update(PLAYER
*pp
)
628 outyx(pp
, STAT_AMMO_ROW
, STAT_VALUE_COL
- 1, "%4d", pp
->p_ammo
);