xref: /csrg-svn/games/rogue/move.c (revision 60842)
132689Sbostic /*
2*60842Sbostic  * Copyright (c) 1988, 1993
3*60842Sbostic  *	The Regents of the University of California.  All rights reserved.
436704Sbostic  *
536704Sbostic  * This code is derived from software contributed to Berkeley by
636704Sbostic  * Timothy C. Stoehr.
736704Sbostic  *
842598Sbostic  * %sccs.include.redist.c%
936704Sbostic  */
1036704Sbostic 
1136704Sbostic #ifndef lint
12*60842Sbostic static char sccsid[] = "@(#)move.c	8.1 (Berkeley) 05/31/93";
1336704Sbostic #endif /* not lint */
1436704Sbostic 
1536704Sbostic /*
1632689Sbostic  * move.c
1732689Sbostic  *
1832689Sbostic  * This source herein may be modified and/or distributed by anybody who
1932689Sbostic  * so desires, with the following restrictions:
2032689Sbostic  *    1.)  No portion of this notice shall be removed.
2132689Sbostic  *    2.)  Credit shall not be taken for the creation of this source.
2232689Sbostic  *    3.)  This code is not to be traded, sold, or used for personal
2332689Sbostic  *         gain or profit.
2432689Sbostic  *
2532689Sbostic  */
2632689Sbostic 
2732689Sbostic #include "rogue.h"
2832689Sbostic 
2932689Sbostic short m_moves = 0;
3032689Sbostic boolean jump = 0;
3132689Sbostic char *you_can_move_again = "you can move again";
3232689Sbostic 
3332689Sbostic extern short cur_room, halluc, blind, levitate;
3432689Sbostic extern short cur_level, max_level;
3532689Sbostic extern short bear_trap, haste_self, confused;
3632689Sbostic extern short e_rings, regeneration, auto_search;
3732689Sbostic extern char hunger_str[];
3832689Sbostic extern boolean being_held, interrupted, r_teleport, passgo;
3932689Sbostic 
one_move_rogue(dirch,pickup)4032689Sbostic one_move_rogue(dirch, pickup)
4132689Sbostic short dirch, pickup;
4232689Sbostic {
4332689Sbostic 	short row, col;
4432689Sbostic 	object *obj;
4532689Sbostic 	char desc[DCOLS];
4632689Sbostic 	short n, status, d;
4732689Sbostic 
4832689Sbostic 	row = rogue.row;
4932689Sbostic 	col = rogue.col;
5032689Sbostic 
5132689Sbostic 	if (confused) {
5232689Sbostic 		dirch = gr_dir();
5332689Sbostic 	}
5432689Sbostic 	(void) is_direction(dirch, &d);
5532689Sbostic 	get_dir_rc(d, &row, &col, 1);
5632689Sbostic 
5732689Sbostic 	if (!can_move(rogue.row, rogue.col, row, col)) {
5832689Sbostic 		return(MOVE_FAILED);
5932689Sbostic 	}
6032689Sbostic 	if (being_held || bear_trap) {
6132689Sbostic 		if (!(dungeon[row][col] & MONSTER)) {
6232689Sbostic 			if (being_held) {
6332689Sbostic 				message("you are being held", 1);
6432689Sbostic 			} else {
6532689Sbostic 				message("you are still stuck in the bear trap", 0);
6632689Sbostic 				(void) reg_move();
6732689Sbostic 			}
6832689Sbostic 			return(MOVE_FAILED);
6932689Sbostic 		}
7032689Sbostic 	}
7132689Sbostic 	if (r_teleport) {
7232689Sbostic 		if (rand_percent(R_TELE_PERCENT)) {
7332689Sbostic 			tele();
7432689Sbostic 			return(STOPPED_ON_SOMETHING);
7532689Sbostic 		}
7632689Sbostic 	}
7732689Sbostic 	if (dungeon[row][col] & MONSTER) {
7832689Sbostic 		rogue_hit(object_at(&level_monsters, row, col), 0);
7932689Sbostic 		(void) reg_move();
8032689Sbostic 		return(MOVE_FAILED);
8132689Sbostic 	}
8232689Sbostic 	if (dungeon[row][col] & DOOR) {
8332689Sbostic 		if (cur_room == PASSAGE) {
8432689Sbostic 			cur_room = get_room_number(row, col);
8532689Sbostic 			light_up_room(cur_room);
8632689Sbostic 			wake_room(cur_room, 1, row, col);
8732689Sbostic 		} else {
8832689Sbostic 			light_passage(row, col);
8932689Sbostic 		}
9032689Sbostic 	} else if ((dungeon[rogue.row][rogue.col] & DOOR) &&
9132689Sbostic 		   (dungeon[row][col] & TUNNEL)) {
9232689Sbostic 		light_passage(row, col);
9332689Sbostic 		wake_room(cur_room, 0, rogue.row, rogue.col);
9432689Sbostic 		darken_room(cur_room);
9532689Sbostic 		cur_room = PASSAGE;
9632689Sbostic 	} else if (dungeon[row][col] & TUNNEL) {
9732689Sbostic 			light_passage(row, col);
9832689Sbostic 	}
9932689Sbostic 	mvaddch(rogue.row, rogue.col, get_dungeon_char(rogue.row, rogue.col));
10032689Sbostic 	mvaddch(row, col, rogue.fchar);
10132689Sbostic 
10232689Sbostic 	if (!jump) {
10332689Sbostic 		refresh();
10432689Sbostic 	}
10532689Sbostic 	rogue.row = row;
10632689Sbostic 	rogue.col = col;
10732689Sbostic 	if (dungeon[row][col] & OBJECT) {
10832689Sbostic 		if (levitate && pickup) {
10932689Sbostic 			return(STOPPED_ON_SOMETHING);
11032689Sbostic 		}
11132689Sbostic 		if (pickup && !levitate) {
11232689Sbostic 			if (obj = pick_up(row, col, &status)) {
11332689Sbostic 				get_desc(obj, desc);
11432689Sbostic 				if (obj->what_is == GOLD) {
11532689Sbostic 					free_object(obj);
11632689Sbostic 					goto NOT_IN_PACK;
11732689Sbostic 				}
11832689Sbostic 			} else if (!status) {
11932689Sbostic 				goto MVED;
12032689Sbostic 			} else {
12132689Sbostic 				goto MOVE_ON;
12232689Sbostic 			}
12332689Sbostic 		} else {
12432689Sbostic MOVE_ON:
12532689Sbostic 			obj = object_at(&level_objects, row, col);
12632689Sbostic 			(void) strcpy(desc, "moved onto ");
12732689Sbostic 			get_desc(obj, desc+11);
12832689Sbostic 			goto NOT_IN_PACK;
12932689Sbostic 		}
13032689Sbostic 		n = strlen(desc);
13132689Sbostic 		desc[n] = '(';
13232689Sbostic 		desc[n+1] = obj->ichar;
13332689Sbostic 		desc[n+2] = ')';
13432689Sbostic 		desc[n+3] = 0;
13532689Sbostic NOT_IN_PACK:
13632689Sbostic 		message(desc, 1);
13732689Sbostic 		(void) reg_move();
13832689Sbostic 		return(STOPPED_ON_SOMETHING);
13932689Sbostic 	}
14032689Sbostic 	if (dungeon[row][col] & (DOOR | STAIRS | TRAP)) {
14132689Sbostic 		if ((!levitate) && (dungeon[row][col] & TRAP)) {
14232689Sbostic 			trap_player(row, col);
14332689Sbostic 		}
14432689Sbostic 		(void) reg_move();
14532689Sbostic 		return(STOPPED_ON_SOMETHING);
14632689Sbostic 	}
14732689Sbostic MVED:	if (reg_move()) {			/* fainted from hunger */
14832689Sbostic 			return(STOPPED_ON_SOMETHING);
14932689Sbostic 	}
15032689Sbostic 	return((confused ? STOPPED_ON_SOMETHING : MOVED));
15132689Sbostic }
15232689Sbostic 
multiple_move_rogue(dirch)15332689Sbostic multiple_move_rogue(dirch)
15432689Sbostic short dirch;
15532689Sbostic {
15632689Sbostic 	short row, col;
15732689Sbostic 	short m;
15832689Sbostic 
15932689Sbostic 	switch(dirch) {
16032689Sbostic 	case '\010':
16132689Sbostic 	case '\012':
16232689Sbostic 	case '\013':
16332689Sbostic 	case '\014':
16432689Sbostic 	case '\031':
16532689Sbostic 	case '\025':
16632689Sbostic 	case '\016':
16732689Sbostic 	case '\002':
16832689Sbostic 		do {
16932689Sbostic 			row = rogue.row;
17032689Sbostic 			col = rogue.col;
17132689Sbostic 			if (((m = one_move_rogue((dirch + 96), 1)) == MOVE_FAILED) ||
17232689Sbostic 				(m == STOPPED_ON_SOMETHING) ||
17332689Sbostic 				interrupted) {
17432689Sbostic 				break;
17532689Sbostic 			}
17632689Sbostic 		} while (!next_to_something(row, col));
17732689Sbostic 		if (	(!interrupted) && passgo && (m == MOVE_FAILED) &&
17832689Sbostic 				(dungeon[rogue.row][rogue.col] & TUNNEL)) {
17932689Sbostic 			turn_passage(dirch + 96, 0);
18032689Sbostic 		}
18132689Sbostic 		break;
18232689Sbostic 	case 'H':
18332689Sbostic 	case 'J':
18432689Sbostic 	case 'K':
18532689Sbostic 	case 'L':
18632689Sbostic 	case 'B':
18732689Sbostic 	case 'Y':
18832689Sbostic 	case 'U':
18932689Sbostic 	case 'N':
19032689Sbostic 		while ((!interrupted) && (one_move_rogue((dirch + 32), 1) == MOVED)) ;
19132689Sbostic 
19232689Sbostic 		if (	(!interrupted) && passgo &&
19332689Sbostic 				(dungeon[rogue.row][rogue.col] & TUNNEL)) {
19432689Sbostic 			turn_passage(dirch + 32, 1);
19532689Sbostic 		}
19632689Sbostic 		break;
19732689Sbostic 	}
19832689Sbostic }
19932689Sbostic 
is_passable(row,col)20032689Sbostic is_passable(row, col)
20132689Sbostic register row, col;
20232689Sbostic {
20332689Sbostic 	if ((row < MIN_ROW) || (row > (DROWS - 2)) || (col < 0) ||
20432689Sbostic 		(col > (DCOLS-1))) {
20532689Sbostic 		return(0);
20632689Sbostic 	}
20732689Sbostic 	if (dungeon[row][col] & HIDDEN) {
20832689Sbostic 		return((dungeon[row][col] & TRAP) ? 1 : 0);
20932689Sbostic 	}
21032689Sbostic 	return(dungeon[row][col] & (FLOOR | TUNNEL | DOOR | STAIRS | TRAP));
21132689Sbostic }
21232689Sbostic 
next_to_something(drow,dcol)21332689Sbostic next_to_something(drow, dcol)
21432689Sbostic register drow, dcol;
21532689Sbostic {
21632689Sbostic 	short i, j, i_end, j_end, row, col;
21732689Sbostic 	short pass_count = 0;
21832689Sbostic 	unsigned short s;
21932689Sbostic 
22032689Sbostic 	if (confused) {
22132689Sbostic 		return(1);
22232689Sbostic 	}
22332689Sbostic 	if (blind) {
22432689Sbostic 		return(0);
22532689Sbostic 	}
22632689Sbostic 	i_end = (rogue.row < (DROWS-2)) ? 1 : 0;
22732689Sbostic 	j_end = (rogue.col < (DCOLS-1)) ? 1 : 0;
22832689Sbostic 
22932689Sbostic 	for (i = ((rogue.row > MIN_ROW) ? -1 : 0); i <= i_end; i++) {
23032689Sbostic 		for (j = ((rogue.col > 0) ? -1 : 0); j <= j_end; j++) {
23132689Sbostic 			if ((i == 0) && (j == 0)) {
23232689Sbostic 				continue;
23332689Sbostic 			}
23432689Sbostic 			if (((rogue.row+i) == drow) && ((rogue.col+j) == dcol)) {
23532689Sbostic 				continue;
23632689Sbostic 			}
23732689Sbostic 			row = rogue.row + i;
23832689Sbostic 			col = rogue.col + j;
23932689Sbostic 			s = dungeon[row][col];
24032689Sbostic 			if (s & HIDDEN) {
24132689Sbostic 				continue;
24232689Sbostic 			}
24332689Sbostic 			/* If the rogue used to be right, up, left, down, or right of
24432689Sbostic 			 * row,col, and now isn't, then don't stop */
24532689Sbostic 			if (s & (MONSTER | OBJECT | STAIRS)) {
24632689Sbostic 				if (((row == drow) || (col == dcol)) &&
24732689Sbostic 					(!((row == rogue.row) || (col == rogue.col)))) {
24832689Sbostic 					continue;
24932689Sbostic 				}
25032689Sbostic 				return(1);
25132689Sbostic 			}
25232689Sbostic 			if (s & TRAP) {
25332689Sbostic 				if (!(s & HIDDEN)) {
25432689Sbostic 					if (((row == drow) || (col == dcol)) &&
25532689Sbostic 						(!((row == rogue.row) || (col == rogue.col)))) {
25632689Sbostic 						continue;
25732689Sbostic 					}
25832689Sbostic 					return(1);
25932689Sbostic 				}
26032689Sbostic 			}
26132689Sbostic 			if ((((i - j) == 1) || ((i - j) == -1)) && (s & TUNNEL)) {
26232689Sbostic 				if (++pass_count > 1) {
26332689Sbostic 					return(1);
26432689Sbostic 				}
26532689Sbostic 			}
26632689Sbostic 			if ((s & DOOR) && ((i == 0) || (j == 0))) {
26732689Sbostic 					return(1);
26832689Sbostic 			}
26932689Sbostic 		}
27032689Sbostic 	}
27132689Sbostic 	return(0);
27232689Sbostic }
27332689Sbostic 
can_move(row1,col1,row2,col2)27432689Sbostic can_move(row1, col1, row2, col2)
27532689Sbostic {
27632689Sbostic 	if (!is_passable(row2, col2)) {
27732689Sbostic 		return(0);
27832689Sbostic 	}
27932689Sbostic 	if ((row1 != row2) && (col1 != col2)) {
28032689Sbostic 		if ((dungeon[row1][col1] & DOOR) || (dungeon[row2][col2] & DOOR)) {
28132689Sbostic 			return(0);
28232689Sbostic 		}
28332689Sbostic 		if ((!dungeon[row1][col2]) || (!dungeon[row2][col1])) {
28432689Sbostic 			return(0);
28532689Sbostic 		}
28632689Sbostic 	}
28732689Sbostic 	return(1);
28832689Sbostic }
28932689Sbostic 
move_onto()29032689Sbostic move_onto()
29132689Sbostic {
29232689Sbostic 	short ch, d;
29332689Sbostic 	boolean first_miss = 1;
29432689Sbostic 
29532689Sbostic 	while (!is_direction(ch = rgetchar(), &d)) {
29632689Sbostic 		sound_bell();
29732689Sbostic 		if (first_miss) {
29832689Sbostic 			message("direction? ", 0);
29932689Sbostic 			first_miss = 0;
30032689Sbostic 		}
30132689Sbostic 	}
30232689Sbostic 	check_message();
30332689Sbostic 	if (ch != CANCEL) {
30432689Sbostic 		(void) one_move_rogue(ch, 0);
30532689Sbostic 	}
30632689Sbostic }
30732689Sbostic 
30832689Sbostic boolean
is_direction(c,d)30932689Sbostic is_direction(c, d)
31032689Sbostic short c;
31132689Sbostic short *d;
31232689Sbostic {
31332689Sbostic 	switch(c) {
31432689Sbostic 	case 'h':
31532689Sbostic 		*d = LEFT;
31632689Sbostic 		break;
31732689Sbostic 	case 'j':
31832689Sbostic 		*d = DOWN;
31932689Sbostic 		break;
32032689Sbostic 	case 'k':
32132689Sbostic 		*d = UPWARD;
32232689Sbostic 		break;
32332689Sbostic 	case 'l':
32432689Sbostic 		*d = RIGHT;
32532689Sbostic 		break;
32632689Sbostic 	case 'b':
32732689Sbostic 		*d = DOWNLEFT;
32832689Sbostic 		break;
32932689Sbostic 	case 'y':
33032689Sbostic 		*d = UPLEFT;
33132689Sbostic 		break;
33232689Sbostic 	case 'u':
33332689Sbostic 		*d = UPRIGHT;
33432689Sbostic 		break;
33532689Sbostic 	case 'n':
33632689Sbostic 		*d = DOWNRIGHT;
33732689Sbostic 		break;
33832689Sbostic 	case CANCEL:
33932689Sbostic 		break;
34032689Sbostic 	default:
34132689Sbostic 		return(0);
34232689Sbostic 	}
34332689Sbostic 	return(1);
34432689Sbostic }
34532689Sbostic 
34632689Sbostic boolean
check_hunger(msg_only)34732689Sbostic check_hunger(msg_only)
34832689Sbostic boolean msg_only;
34932689Sbostic {
35032689Sbostic 	register short i, n;
35132689Sbostic 	boolean fainted = 0;
35232689Sbostic 
35332689Sbostic 	if (rogue.moves_left == HUNGRY) {
35432689Sbostic 		(void) strcpy(hunger_str, "hungry");
35532689Sbostic 		message(hunger_str, 0);
35632689Sbostic 		print_stats(STAT_HUNGER);
35732689Sbostic 	}
35832689Sbostic 	if (rogue.moves_left == WEAK) {
35932689Sbostic 		(void) strcpy(hunger_str, "weak");
36032689Sbostic 		message(hunger_str, 1);
36132689Sbostic 		print_stats(STAT_HUNGER);
36232689Sbostic 	}
36332689Sbostic 	if (rogue.moves_left <= FAINT) {
36432689Sbostic 		if (rogue.moves_left == FAINT) {
36532689Sbostic 			(void) strcpy(hunger_str, "faint");
36632689Sbostic 			message(hunger_str, 1);
36732689Sbostic 			print_stats(STAT_HUNGER);
36832689Sbostic 		}
36932689Sbostic 		n = get_rand(0, (FAINT - rogue.moves_left));
37032689Sbostic 		if (n > 0) {
37132689Sbostic 			fainted = 1;
37232689Sbostic 			if (rand_percent(40)) {
37332689Sbostic 				rogue.moves_left++;
37432689Sbostic 			}
37532689Sbostic 			message("you faint", 1);
37632689Sbostic 			for (i = 0; i < n; i++) {
37732689Sbostic 				if (coin_toss()) {
37832689Sbostic 					mv_mons();
37932689Sbostic 				}
38032689Sbostic 			}
38132689Sbostic 			message(you_can_move_again, 1);
38232689Sbostic 		}
38332689Sbostic 	}
38432689Sbostic 	if (msg_only) {
38532689Sbostic 		return(fainted);
38632689Sbostic 	}
38732689Sbostic 	if (rogue.moves_left <= STARVE) {
38832689Sbostic 		killed_by((object *) 0, STARVATION);
38932689Sbostic 	}
39032689Sbostic 
39132689Sbostic 	switch(e_rings) {
39232689Sbostic 	/*case -2:
39332689Sbostic 		Subtract 0, i.e. do nothing.
39432689Sbostic 		break;*/
39532689Sbostic 	case -1:
39632689Sbostic 		rogue.moves_left -= (rogue.moves_left % 2);
39732689Sbostic 		break;
39832689Sbostic 	case 0:
39932689Sbostic 		rogue.moves_left--;
40032689Sbostic 		break;
40132689Sbostic 	case 1:
40232689Sbostic 		rogue.moves_left--;
40332689Sbostic 		(void) check_hunger(1);
40432689Sbostic 		rogue.moves_left -= (rogue.moves_left % 2);
40532689Sbostic 		break;
40632689Sbostic 	case 2:
40732689Sbostic 		rogue.moves_left--;
40832689Sbostic 		(void) check_hunger(1);
40932689Sbostic 		rogue.moves_left--;
41032689Sbostic 		break;
41132689Sbostic 	}
41232689Sbostic 	return(fainted);
41332689Sbostic }
41432689Sbostic 
41532689Sbostic boolean
reg_move()41632689Sbostic reg_move()
41732689Sbostic {
41832689Sbostic 	boolean fainted;
41932689Sbostic 
42032689Sbostic 	if ((rogue.moves_left <= HUNGRY) || (cur_level >= max_level)) {
42132689Sbostic 		fainted = check_hunger(0);
42232689Sbostic 	} else {
42332689Sbostic 		fainted = 0;
42432689Sbostic 	}
42532689Sbostic 
42632689Sbostic 	mv_mons();
42732689Sbostic 
42832689Sbostic 	if (++m_moves >= 120) {
42932689Sbostic 		m_moves = 0;
43032689Sbostic 		wanderer();
43132689Sbostic 	}
43232689Sbostic 	if (halluc) {
43332689Sbostic 		if (!(--halluc)) {
43432689Sbostic 			unhallucinate();
43532689Sbostic 		} else {
43632689Sbostic 			hallucinate();
43732689Sbostic 		}
43832689Sbostic 	}
43932689Sbostic 	if (blind) {
44032689Sbostic 		if (!(--blind)) {
44132689Sbostic 			unblind();
44232689Sbostic 		}
44332689Sbostic 	}
44432689Sbostic 	if (confused) {
44532689Sbostic 		if (!(--confused)) {
44632689Sbostic 			unconfuse();
44732689Sbostic 		}
44832689Sbostic 	}
44932689Sbostic 	if (bear_trap) {
45032689Sbostic 		bear_trap--;
45132689Sbostic 	}
45232689Sbostic 	if (levitate) {
45332689Sbostic 		if (!(--levitate)) {
45432689Sbostic 			message("you float gently to the ground", 1);
45532689Sbostic 			if (dungeon[rogue.row][rogue.col] & TRAP) {
45632689Sbostic 				trap_player(rogue.row, rogue.col);
45732689Sbostic 			}
45832689Sbostic 		}
45932689Sbostic 	}
46032689Sbostic 	if (haste_self) {
46132689Sbostic 		if (!(--haste_self)) {
46232689Sbostic 			message("you feel yourself slowing down", 0);
46332689Sbostic 		}
46432689Sbostic 	}
46532689Sbostic 	heal();
46632689Sbostic 	if (auto_search > 0) {
46732689Sbostic 		search(auto_search, auto_search);
46832689Sbostic 	}
46932689Sbostic 	return(fainted);
47032689Sbostic }
47132689Sbostic 
rest(count)47232689Sbostic rest(count)
47332689Sbostic {
47432689Sbostic 	int i;
47532689Sbostic 
47632689Sbostic 	interrupted = 0;
47732689Sbostic 
47832689Sbostic 	for (i = 0; i < count; i++) {
47932689Sbostic 		if (interrupted) {
48032689Sbostic 			break;
48132689Sbostic 		}
48232689Sbostic 		(void) reg_move();
48332689Sbostic 	}
48432689Sbostic }
48532689Sbostic 
gr_dir()48632689Sbostic gr_dir()
48732689Sbostic {
48832689Sbostic 	short d;
48932689Sbostic 
49032689Sbostic 	d = get_rand(1, 8);
49132689Sbostic 
49232689Sbostic 	switch(d) {
49332689Sbostic 		case 1:
49432689Sbostic 			d = 'j';
49532689Sbostic 			break;
49632689Sbostic 		case 2:
49732689Sbostic 			d = 'k';
49832689Sbostic 			break;
49932689Sbostic 		case 3:
50032689Sbostic 			d = 'l';
50132689Sbostic 			break;
50232689Sbostic 		case 4:
50332689Sbostic 			d = 'h';
50432689Sbostic 			break;
50532689Sbostic 		case 5:
50632689Sbostic 			d = 'y';
50732689Sbostic 			break;
50832689Sbostic 		case 6:
50932689Sbostic 			d = 'u';
51032689Sbostic 			break;
51132689Sbostic 		case 7:
51232689Sbostic 			d = 'b';
51332689Sbostic 			break;
51432689Sbostic 		case 8:
51532689Sbostic 			d = 'n';
51632689Sbostic 			break;
51732689Sbostic 	}
51832689Sbostic 	return(d);
51932689Sbostic }
52032689Sbostic 
heal()52132689Sbostic heal()
52232689Sbostic {
52332689Sbostic 	static short heal_exp = -1, n, c = 0;
52432689Sbostic 	static boolean alt;
52532689Sbostic 
52632689Sbostic 	if (rogue.hp_current == rogue.hp_max) {
52732689Sbostic 		c = 0;
52832689Sbostic 		return;
52932689Sbostic 	}
53032689Sbostic 	if (rogue.exp != heal_exp) {
53132689Sbostic 		heal_exp = rogue.exp;
53232689Sbostic 
53332689Sbostic 		switch(heal_exp) {
53432689Sbostic 		case 1:
53532689Sbostic 			n = 20;
53632689Sbostic 			break;
53732689Sbostic 		case 2:
53832689Sbostic 			n = 18;
53932689Sbostic 			break;
54032689Sbostic 		case 3:
54132689Sbostic 			n = 17;
54232689Sbostic 			break;
54332689Sbostic 		case 4:
54432689Sbostic 			n = 14;
54532689Sbostic 			break;
54632689Sbostic 		case 5:
54732689Sbostic 			n = 13;
54832689Sbostic 			break;
54932689Sbostic 		case 6:
55032689Sbostic 			n = 10;
55132689Sbostic 			break;
55232689Sbostic 		case 7:
55332689Sbostic 			n = 9;
55432689Sbostic 			break;
55532689Sbostic 		case 8:
55632689Sbostic 			n = 8;
55732689Sbostic 			break;
55832689Sbostic 		case 9:
55932689Sbostic 			n = 7;
56032689Sbostic 			break;
56132689Sbostic 		case 10:
56232689Sbostic 			n = 4;
56332689Sbostic 			break;
56432689Sbostic 		case 11:
56532689Sbostic 			n = 3;
56632689Sbostic 			break;
56732689Sbostic 		case 12:
56832689Sbostic 		default:
56932689Sbostic 			n = 2;
57032689Sbostic 		}
57132689Sbostic 	}
57232689Sbostic 	if (++c >= n) {
57332689Sbostic 		c = 0;
57432689Sbostic 		rogue.hp_current++;
57532689Sbostic 		if (alt = !alt) {
57632689Sbostic 			rogue.hp_current++;
57732689Sbostic 		}
57832689Sbostic 		if ((rogue.hp_current += regeneration) > rogue.hp_max) {
57932689Sbostic 			rogue.hp_current = rogue.hp_max;
58032689Sbostic 		}
58132689Sbostic 		print_stats(STAT_HP);
58232689Sbostic 	}
58332689Sbostic }
58432689Sbostic 
58532689Sbostic static boolean
can_turn(nrow,ncol)58632689Sbostic can_turn(nrow, ncol)
58732689Sbostic short nrow, ncol;
58832689Sbostic {
58932689Sbostic 	if ((dungeon[nrow][ncol] & TUNNEL) && is_passable(nrow, ncol)) {
59032689Sbostic 		return(1);
59132689Sbostic 	}
59232689Sbostic 	return(0);
59332689Sbostic }
59432689Sbostic 
turn_passage(dir,fast)59532689Sbostic turn_passage(dir, fast)
59632689Sbostic short dir;
59732689Sbostic boolean fast;
59832689Sbostic {
59932689Sbostic 	short crow = rogue.row, ccol = rogue.col, turns = 0;
60032689Sbostic 	short ndir;
60132689Sbostic 
60232689Sbostic 	if ((dir != 'h') && can_turn(crow, ccol + 1)) {
60332689Sbostic 		turns++;
60432689Sbostic 		ndir = 'l';
60532689Sbostic 	}
60632689Sbostic 	if ((dir != 'l') && can_turn(crow, ccol - 1)) {
60732689Sbostic 		turns++;
60832689Sbostic 		ndir = 'h';
60932689Sbostic 	}
61032689Sbostic 	if ((dir != 'k') && can_turn(crow + 1, ccol)) {
61132689Sbostic 		turns++;
61232689Sbostic 		ndir = 'j';
61332689Sbostic 	}
61432689Sbostic 	if ((dir != 'j') && can_turn(crow - 1, ccol)) {
61532689Sbostic 		turns++;
61632689Sbostic 		ndir = 'k';
61732689Sbostic 	}
61832689Sbostic 	if (turns == 1) {
61932689Sbostic 		multiple_move_rogue(ndir - (fast ? 32 : 96));
62032689Sbostic 	}
62132689Sbostic }
622