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