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