Home | History | Annotate | Line # | Download | only in huntd
execute.c revision 1.4
      1 /*	$NetBSD: execute.c,v 1.4 2004/01/27 20:30:29 jsm Exp $	*/
      2 /*
      3  * Copyright (c) 1983-2003, Regents of the University of California.
      4  * All rights reserved.
      5  *
      6  * Redistribution and use in source and binary forms, with or without
      7  * modification, are permitted provided that the following conditions are
      8  * met:
      9  *
     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
     18  *   permission.
     19  *
     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.
     31  */
     32 
     33 #include <sys/cdefs.h>
     34 #ifndef lint
     35 __RCSID("$NetBSD: execute.c,v 1.4 2004/01/27 20:30:29 jsm Exp $");
     36 #endif /* not lint */
     37 
     38 # include	<stdlib.h>
     39 # include	"hunt.h"
     40 
     41 static	void	cloak(PLAYER *);
     42 static	void	face(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 *);
     48 
     49 
     50 # ifdef MONITOR
     51 /*
     52  * mon_execute:
     53  *	Execute a single monitor command
     54  */
     55 void
     56 mon_execute(pp)
     57 	PLAYER	*pp;
     58 {
     59 	char	ch;
     60 
     61 	ch = pp->p_cbuf[pp->p_ncount++];
     62 	switch (ch) {
     63 	  case CTRL('L'):
     64 		sendcom(pp, REDRAW);
     65 		break;
     66 	  case 'q':
     67 		(void) strcpy(pp->p_death, "| Quit |");
     68 		break;
     69 	}
     70 }
     71 # endif
     72 
     73 /*
     74  * execute:
     75  *	Execute a single command
     76  */
     77 void
     78 execute(pp)
     79 	PLAYER	*pp;
     80 {
     81 	char	ch;
     82 
     83 	ch = pp->p_cbuf[pp->p_ncount++];
     84 
     85 # ifdef	FLY
     86 	if (pp->p_flying >= 0) {
     87 		switch (ch) {
     88 		  case CTRL('L'):
     89 			sendcom(pp, REDRAW);
     90 			break;
     91 		  case 'q':
     92 			(void) strcpy(pp->p_death, "| Quit |");
     93 			break;
     94 		}
     95 		return;
     96 	}
     97 # endif
     98 
     99 	switch (ch) {
    100 	  case CTRL('L'):
    101 		sendcom(pp, REDRAW);
    102 		break;
    103 	  case 'h':
    104 		move_player(pp, LEFTS);
    105 		break;
    106 	  case 'H':
    107 		face(pp, LEFTS);
    108 		break;
    109 	  case 'j':
    110 		move_player(pp, BELOW);
    111 		break;
    112 	  case 'J':
    113 		face(pp, BELOW);
    114 		break;
    115 	  case 'k':
    116 		move_player(pp, ABOVE);
    117 		break;
    118 	  case 'K':
    119 		face(pp, ABOVE);
    120 		break;
    121 	  case 'l':
    122 		move_player(pp, RIGHT);
    123 		break;
    124 	  case 'L':
    125 		face(pp, RIGHT);
    126 		break;
    127 	  case 'f':
    128 	  case '1':
    129 		fire(pp, 0);		/* SHOT */
    130 		break;
    131 	  case 'g':
    132 	  case '2':
    133 		fire(pp, 1);		/* GRENADE */
    134 		break;
    135 	  case 'F':
    136 	  case '3':
    137 		fire(pp, 2);		/* SATCHEL */
    138 		break;
    139 	  case 'G':
    140 	  case '4':
    141 		fire(pp, 3);		/* 7x7 BOMB */
    142 		break;
    143 	  case '5':
    144 		fire(pp, 4);		/* 9x9 BOMB */
    145 		break;
    146 	  case '6':
    147 		fire(pp, 5);		/* 11x11 BOMB */
    148 		break;
    149 	  case '7':
    150 		fire(pp, 6);		/* 13x13 BOMB */
    151 		break;
    152 	  case '8':
    153 		fire(pp, 7);		/* 15x15 BOMB */
    154 		break;
    155 	  case '9':
    156 		fire(pp, 8);		/* 17x17 BOMB */
    157 		break;
    158 	  case '0':
    159 		fire(pp, 9);		/* 19x19 BOMB */
    160 		break;
    161 	  case '@':
    162 		fire(pp, 10);		/* 21x21 BOMB */
    163 		break;
    164 # ifdef	OOZE
    165 	  case 'o':
    166 		fire_slime(pp, 0);	/* SLIME */
    167 		break;
    168 	  case 'O':
    169 		fire_slime(pp, 1);	/* SSLIME */
    170 		break;
    171 	  case 'p':
    172 		fire_slime(pp, 2);
    173 		break;
    174 	  case 'P':
    175 		fire_slime(pp, 3);
    176 		break;
    177 # endif
    178 	  case 's':
    179 		scan(pp);
    180 		break;
    181 	  case 'c':
    182 		cloak(pp);
    183 		break;
    184 	  case 'q':
    185 		(void) strcpy(pp->p_death, "| Quit |");
    186 		break;
    187 	}
    188 }
    189 
    190 /*
    191  * move_player:
    192  *	Execute a move in the given direction
    193  */
    194 static void
    195 move_player(pp, dir)
    196 	PLAYER	*pp;
    197 	int	dir;
    198 {
    199 	PLAYER	*newp;
    200 	int	x, y;
    201 	FLAG	moved;
    202 	BULLET	*bp;
    203 
    204 	y = pp->p_y;
    205 	x = pp->p_x;
    206 
    207 	switch (dir) {
    208 	  case LEFTS:
    209 		x--;
    210 		break;
    211 	  case RIGHT:
    212 		x++;
    213 		break;
    214 	  case ABOVE:
    215 		y--;
    216 		break;
    217 	  case BELOW:
    218 		y++;
    219 		break;
    220 	}
    221 
    222 	moved = FALSE;
    223 	switch (Maze[y][x]) {
    224 	  case SPACE:
    225 # ifdef RANDOM
    226 	  case DOOR:
    227 # endif
    228 		moved = TRUE;
    229 		break;
    230 	  case WALL1:
    231 	  case WALL2:
    232 	  case WALL3:
    233 # ifdef REFLECT
    234 	  case WALL4:
    235 	  case WALL5:
    236 # endif
    237 		break;
    238 	  case MINE:
    239 	  case GMINE:
    240 		if (dir == pp->p_face)
    241 			pickup(pp, y, x, 2, Maze[y][x]);
    242 		else if (opposite(dir, pp->p_face))
    243 			pickup(pp, y, x, 95, Maze[y][x]);
    244 		else
    245 			pickup(pp, y, x, 50, Maze[y][x]);
    246 		Maze[y][x] = SPACE;
    247 		moved = TRUE;
    248 		break;
    249 	  case SHOT:
    250 	  case GRENADE:
    251 	  case SATCHEL:
    252 	  case BOMB:
    253 # ifdef OOZE
    254 	  case SLIME:
    255 # endif
    256 # ifdef DRONE
    257 	  case DSHOT:
    258 # endif
    259 		bp = is_bullet(y, x);
    260 		if (bp != NULL)
    261 			bp->b_expl = TRUE;
    262 		Maze[y][x] = SPACE;
    263 		moved = TRUE;
    264 		break;
    265 	  case LEFTS:
    266 	  case RIGHT:
    267 	  case ABOVE:
    268 	  case BELOW:
    269 		if (dir != pp->p_face)
    270 			sendcom(pp, BELL);
    271 		else {
    272 			newp = play_at(y, x);
    273 			checkdam(newp, pp, pp->p_ident, STABDAM, KNIFE);
    274 		}
    275 		break;
    276 # ifdef FLY
    277 	  case FLYER:
    278 		newp = play_at(y, x);
    279 		message(newp, "Oooh, there's a short guy waving at you!");
    280 		message(pp, "You couldn't quite reach him!");
    281 		break;
    282 # endif
    283 # ifdef BOOTS
    284 	  case BOOT:
    285 	  case BOOT_PAIR:
    286 		if (Maze[y][x] == BOOT)
    287 			pp->p_nboots++;
    288 		else
    289 			pp->p_nboots += 2;
    290 		for (newp = Boot; newp < &Boot[NBOOTS]; newp++) {
    291 			if (newp->p_flying < 0)
    292 				continue;
    293 			if (newp->p_y == y && newp->p_x == x) {
    294 				newp->p_flying = -1;
    295 				if (newp->p_undershot)
    296 					fixshots(y, x, newp->p_over);
    297 			}
    298 		}
    299 		if (pp->p_nboots == 2)
    300 			message(pp, "Wow!  A pair of boots!");
    301 		else
    302 			message(pp, "You can hobble around on one boot.");
    303 		Maze[y][x] = SPACE;
    304 		moved = TRUE;
    305 		break;
    306 # endif
    307 	}
    308 	if (moved) {
    309 		if (pp->p_ncshot > 0)
    310 			if (--pp->p_ncshot == MAXNCSHOT) {
    311 				cgoto(pp, STAT_GUN_ROW, STAT_VALUE_COL);
    312 				outstr(pp, " ok", 3);
    313 			}
    314 		if (pp->p_undershot) {
    315 			fixshots(pp->p_y, pp->p_x, pp->p_over);
    316 			pp->p_undershot = FALSE;
    317 		}
    318 		drawplayer(pp, FALSE);
    319 		pp->p_over = Maze[y][x];
    320 		pp->p_y = y;
    321 		pp->p_x = x;
    322 		drawplayer(pp, TRUE);
    323 	}
    324 }
    325 
    326 /*
    327  * face:
    328  *	Change the direction the player is facing
    329  */
    330 static void
    331 face(pp, dir)
    332 	PLAYER	*pp;
    333 	int	dir;
    334 {
    335 	if (pp->p_face != dir) {
    336 		pp->p_face = dir;
    337 		drawplayer(pp, TRUE);
    338 	}
    339 }
    340 
    341 /*
    342  * fire:
    343  *	Fire a shot of the given type in the given direction
    344  */
    345 static void
    346 fire(pp, req_index)
    347 	PLAYER	*pp;
    348 	int	req_index;
    349 {
    350 	if (pp == NULL)
    351 		return;
    352 # ifdef DEBUG
    353 	if (req_index < 0 || req_index >= MAXBOMB)
    354 		message(pp, "What you do?");
    355 # endif
    356 	while (req_index >= 0 && pp->p_ammo < shot_req[req_index])
    357 		req_index--;
    358 	if (req_index < 0) {
    359 		message(pp, "Not enough charges.");
    360 		return;
    361 	}
    362 	if (pp->p_ncshot > MAXNCSHOT)
    363 		return;
    364 	if (pp->p_ncshot++ == MAXNCSHOT) {
    365 		cgoto(pp, STAT_GUN_ROW, STAT_VALUE_COL);
    366 		outstr(pp, "   ", 3);
    367 	}
    368 	pp->p_ammo -= shot_req[req_index];
    369 	(void) sprintf(Buf, "%3d", pp->p_ammo);
    370 	cgoto(pp, STAT_AMMO_ROW, STAT_VALUE_COL);
    371 	outstr(pp, Buf, 3);
    372 
    373 	add_shot(shot_type[req_index], pp->p_y, pp->p_x, pp->p_face,
    374 		shot_req[req_index], pp, FALSE, pp->p_face);
    375 	pp->p_undershot = TRUE;
    376 
    377 	/*
    378 	 * Show the object to everyone
    379 	 */
    380 	showexpl(pp->p_y, pp->p_x, shot_type[req_index]);
    381 	for (pp = Player; pp < End_player; pp++)
    382 		sendcom(pp, REFRESH);
    383 # ifdef MONITOR
    384 	for (pp = Monitor; pp < End_monitor; pp++)
    385 		sendcom(pp, REFRESH);
    386 # endif
    387 }
    388 
    389 # ifdef	OOZE
    390 /*
    391  * fire_slime:
    392  *	Fire a slime shot in the given direction
    393  */
    394 static void
    395 fire_slime(pp, req_index)
    396 	PLAYER	*pp;
    397 	int	req_index;
    398 {
    399 	if (pp == NULL)
    400 		return;
    401 # ifdef DEBUG
    402 	if (req_index < 0 || req_index >= MAXSLIME)
    403 		message(pp, "What you do?");
    404 # endif
    405 	while (req_index >= 0 && pp->p_ammo < slime_req[req_index])
    406 		req_index--;
    407 	if (req_index < 0) {
    408 		message(pp, "Not enough charges.");
    409 		return;
    410 	}
    411 	if (pp->p_ncshot > MAXNCSHOT)
    412 		return;
    413 	if (pp->p_ncshot++ == MAXNCSHOT) {
    414 		cgoto(pp, STAT_GUN_ROW, STAT_VALUE_COL);
    415 		outstr(pp, "   ", 3);
    416 	}
    417 	pp->p_ammo -= slime_req[req_index];
    418 	(void) sprintf(Buf, "%3d", pp->p_ammo);
    419 	cgoto(pp, STAT_AMMO_ROW, STAT_VALUE_COL);
    420 	outstr(pp, Buf, 3);
    421 
    422 	add_shot(SLIME, pp->p_y, pp->p_x, pp->p_face,
    423 		slime_req[req_index] * SLIME_FACTOR, pp, FALSE, pp->p_face);
    424 	pp->p_undershot = TRUE;
    425 
    426 	/*
    427 	 * Show the object to everyone
    428 	 */
    429 	showexpl(pp->p_y, pp->p_x, SLIME);
    430 	for (pp = Player; pp < End_player; pp++)
    431 		sendcom(pp, REFRESH);
    432 # ifdef MONITOR
    433 	for (pp = Monitor; pp < End_monitor; pp++)
    434 		sendcom(pp, REFRESH);
    435 # endif
    436 }
    437 # endif
    438 
    439 /*
    440  * add_shot:
    441  *	Create a shot with the given properties
    442  */
    443 void
    444 add_shot(type, y, x, face, charge, owner, expl, over)
    445 int	type;
    446 int	y, x;
    447 char	face;
    448 int	charge;
    449 PLAYER	*owner;
    450 int	expl;
    451 char	over;
    452 {
    453 	BULLET	*bp;
    454 	int	size;
    455 
    456 	switch (type) {
    457 	  case SHOT:
    458 	  case MINE:
    459 		size = 1;
    460 		break;
    461 	  case GRENADE:
    462 	  case GMINE:
    463 		size = 2;
    464 		break;
    465 	  case SATCHEL:
    466 		size = 3;
    467 		break;
    468 	  case BOMB:
    469 		for (size = 3; size < MAXBOMB; size++)
    470 			if (shot_req[size] >= charge)
    471 				break;
    472 		size++;
    473 		break;
    474 	  default:
    475 		size = 0;
    476 		break;
    477 	}
    478 
    479 	bp = create_shot(type, y, x, face, charge, size, owner,
    480 		(owner == NULL) ? NULL : owner->p_ident, expl, over);
    481 	bp->b_next = Bullets;
    482 	Bullets = bp;
    483 }
    484 
    485 BULLET *
    486 create_shot(type, y, x, face, charge, size, owner, score, expl, over)
    487 	int	type;
    488 	int	y, x;
    489 	char	face;
    490 	int	charge;
    491 	int	size;
    492 	PLAYER	*owner;
    493 	IDENT	*score;
    494 	int	expl;
    495 	char	over;
    496 {
    497 	BULLET	*bp;
    498 
    499 	bp = (BULLET *) malloc(sizeof (BULLET));	/* NOSTRICT */
    500 	if (bp == NULL) {
    501 		if (owner != NULL)
    502 			message(owner, "Out of memory");
    503 		return NULL;
    504 	}
    505 
    506 	bp->b_face = face;
    507 	bp->b_x = x;
    508 	bp->b_y = y;
    509 	bp->b_charge = charge;
    510 	bp->b_owner = owner;
    511 	bp->b_score = score;
    512 	bp->b_type = type;
    513 	bp->b_size = size;
    514 	bp->b_expl = expl;
    515 	bp->b_over = over;
    516 	bp->b_next = NULL;
    517 
    518 	return bp;
    519 }
    520 
    521 /*
    522  * cloak:
    523  *	Turn on or increase length of a cloak
    524  */
    525 static void
    526 cloak(pp)
    527 	PLAYER	*pp;
    528 {
    529 	if (pp->p_ammo <= 0) {
    530 		message(pp, "No more charges");
    531 		return;
    532 	}
    533 # ifdef BOOTS
    534 	if (pp->p_nboots > 0) {
    535 		message(pp, "Boots are too noisy to cloak!");
    536 		return;
    537 	}
    538 # endif
    539 	(void) sprintf(Buf, "%3d", --pp->p_ammo);
    540 	cgoto(pp, STAT_AMMO_ROW, STAT_VALUE_COL);
    541 	outstr(pp, Buf, 3);
    542 
    543 	pp->p_cloak += CLOAKLEN;
    544 
    545 	if (pp->p_scan >= 0)
    546 		pp->p_scan = -1;
    547 
    548 	showstat(pp);
    549 }
    550 
    551 /*
    552  * scan:
    553  *	Turn on or increase length of a scan
    554  */
    555 static void
    556 scan(pp)
    557 	PLAYER	*pp;
    558 {
    559 	if (pp->p_ammo <= 0) {
    560 		message(pp, "No more charges");
    561 		return;
    562 	}
    563 	(void) sprintf(Buf, "%3d", --pp->p_ammo);
    564 	cgoto(pp, STAT_AMMO_ROW, STAT_VALUE_COL);
    565 	outstr(pp, Buf, 3);
    566 
    567 	pp->p_scan += SCANLEN;
    568 
    569 	if (pp->p_cloak >= 0)
    570 		pp->p_cloak = -1;
    571 
    572 	showstat(pp);
    573 }
    574 
    575 /*
    576  * pickup:
    577  *	check whether the object blew up or whether he picked it up
    578  */
    579 void
    580 pickup(pp, y, x, prob, obj)
    581 	PLAYER	*pp;
    582 	int	y, x;
    583 	int	prob;
    584 	int	obj;
    585 {
    586 	int	req;
    587 
    588 	switch (obj) {
    589 	  case MINE:
    590 		req = BULREQ;
    591 		break;
    592 	  case GMINE:
    593 		req = GRENREQ;
    594 		break;
    595 	  default:
    596 		abort();
    597 	}
    598 	if (rand_num(100) < prob)
    599 		add_shot(obj, y, x, LEFTS, req, (PLAYER *) NULL,
    600 			TRUE, pp->p_face);
    601 	else {
    602 		pp->p_ammo += req;
    603 		(void) sprintf(Buf, "%3d", pp->p_ammo);
    604 		cgoto(pp, STAT_AMMO_ROW, STAT_VALUE_COL);
    605 		outstr(pp, Buf, 3);
    606 	}
    607 }
    608