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