Home | History | Annotate | Line # | Download | only in rogue
move.c revision 1.1.1.2
      1      1.1  cgd /*
      2  1.1.1.2  cgd  * Copyright (c) 1988, 1993
      3  1.1.1.2  cgd  *	The Regents of the University of California.  All rights reserved.
      4      1.1  cgd  *
      5      1.1  cgd  * This code is derived from software contributed to Berkeley by
      6      1.1  cgd  * Timothy C. Stoehr.
      7      1.1  cgd  *
      8      1.1  cgd  * Redistribution and use in source and binary forms, with or without
      9      1.1  cgd  * modification, are permitted provided that the following conditions
     10      1.1  cgd  * are met:
     11      1.1  cgd  * 1. Redistributions of source code must retain the above copyright
     12      1.1  cgd  *    notice, this list of conditions and the following disclaimer.
     13      1.1  cgd  * 2. Redistributions in binary form must reproduce the above copyright
     14      1.1  cgd  *    notice, this list of conditions and the following disclaimer in the
     15      1.1  cgd  *    documentation and/or other materials provided with the distribution.
     16      1.1  cgd  * 3. All advertising materials mentioning features or use of this software
     17      1.1  cgd  *    must display the following acknowledgement:
     18      1.1  cgd  *	This product includes software developed by the University of
     19      1.1  cgd  *	California, Berkeley and its contributors.
     20      1.1  cgd  * 4. Neither the name of the University nor the names of its contributors
     21      1.1  cgd  *    may be used to endorse or promote products derived from this software
     22      1.1  cgd  *    without specific prior written permission.
     23      1.1  cgd  *
     24      1.1  cgd  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     25      1.1  cgd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     26      1.1  cgd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     27      1.1  cgd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     28      1.1  cgd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     29      1.1  cgd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     30      1.1  cgd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     31      1.1  cgd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     32      1.1  cgd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     33      1.1  cgd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     34      1.1  cgd  * SUCH DAMAGE.
     35      1.1  cgd  */
     36      1.1  cgd 
     37      1.1  cgd #ifndef lint
     38  1.1.1.2  cgd static char sccsid[] = "@(#)move.c	8.1 (Berkeley) 5/31/93";
     39      1.1  cgd #endif /* not lint */
     40      1.1  cgd 
     41      1.1  cgd /*
     42      1.1  cgd  * move.c
     43      1.1  cgd  *
     44      1.1  cgd  * This source herein may be modified and/or distributed by anybody who
     45      1.1  cgd  * so desires, with the following restrictions:
     46      1.1  cgd  *    1.)  No portion of this notice shall be removed.
     47      1.1  cgd  *    2.)  Credit shall not be taken for the creation of this source.
     48      1.1  cgd  *    3.)  This code is not to be traded, sold, or used for personal
     49      1.1  cgd  *         gain or profit.
     50      1.1  cgd  *
     51      1.1  cgd  */
     52      1.1  cgd 
     53      1.1  cgd #include "rogue.h"
     54      1.1  cgd 
     55      1.1  cgd short m_moves = 0;
     56      1.1  cgd boolean jump = 0;
     57      1.1  cgd char *you_can_move_again = "you can move again";
     58      1.1  cgd 
     59      1.1  cgd extern short cur_room, halluc, blind, levitate;
     60      1.1  cgd extern short cur_level, max_level;
     61      1.1  cgd extern short bear_trap, haste_self, confused;
     62      1.1  cgd extern short e_rings, regeneration, auto_search;
     63      1.1  cgd extern char hunger_str[];
     64      1.1  cgd extern boolean being_held, interrupted, r_teleport, passgo;
     65      1.1  cgd 
     66      1.1  cgd one_move_rogue(dirch, pickup)
     67      1.1  cgd short dirch, pickup;
     68      1.1  cgd {
     69      1.1  cgd 	short row, col;
     70      1.1  cgd 	object *obj;
     71      1.1  cgd 	char desc[DCOLS];
     72      1.1  cgd 	short n, status, d;
     73      1.1  cgd 
     74      1.1  cgd 	row = rogue.row;
     75      1.1  cgd 	col = rogue.col;
     76      1.1  cgd 
     77      1.1  cgd 	if (confused) {
     78      1.1  cgd 		dirch = gr_dir();
     79      1.1  cgd 	}
     80      1.1  cgd 	(void) is_direction(dirch, &d);
     81      1.1  cgd 	get_dir_rc(d, &row, &col, 1);
     82      1.1  cgd 
     83      1.1  cgd 	if (!can_move(rogue.row, rogue.col, row, col)) {
     84      1.1  cgd 		return(MOVE_FAILED);
     85      1.1  cgd 	}
     86      1.1  cgd 	if (being_held || bear_trap) {
     87      1.1  cgd 		if (!(dungeon[row][col] & MONSTER)) {
     88      1.1  cgd 			if (being_held) {
     89      1.1  cgd 				message("you are being held", 1);
     90      1.1  cgd 			} else {
     91      1.1  cgd 				message("you are still stuck in the bear trap", 0);
     92      1.1  cgd 				(void) reg_move();
     93      1.1  cgd 			}
     94      1.1  cgd 			return(MOVE_FAILED);
     95      1.1  cgd 		}
     96      1.1  cgd 	}
     97      1.1  cgd 	if (r_teleport) {
     98      1.1  cgd 		if (rand_percent(R_TELE_PERCENT)) {
     99      1.1  cgd 			tele();
    100      1.1  cgd 			return(STOPPED_ON_SOMETHING);
    101      1.1  cgd 		}
    102      1.1  cgd 	}
    103      1.1  cgd 	if (dungeon[row][col] & MONSTER) {
    104      1.1  cgd 		rogue_hit(object_at(&level_monsters, row, col), 0);
    105      1.1  cgd 		(void) reg_move();
    106      1.1  cgd 		return(MOVE_FAILED);
    107      1.1  cgd 	}
    108      1.1  cgd 	if (dungeon[row][col] & DOOR) {
    109      1.1  cgd 		if (cur_room == PASSAGE) {
    110      1.1  cgd 			cur_room = get_room_number(row, col);
    111      1.1  cgd 			light_up_room(cur_room);
    112      1.1  cgd 			wake_room(cur_room, 1, row, col);
    113      1.1  cgd 		} else {
    114      1.1  cgd 			light_passage(row, col);
    115      1.1  cgd 		}
    116      1.1  cgd 	} else if ((dungeon[rogue.row][rogue.col] & DOOR) &&
    117      1.1  cgd 		   (dungeon[row][col] & TUNNEL)) {
    118      1.1  cgd 		light_passage(row, col);
    119      1.1  cgd 		wake_room(cur_room, 0, rogue.row, rogue.col);
    120      1.1  cgd 		darken_room(cur_room);
    121      1.1  cgd 		cur_room = PASSAGE;
    122      1.1  cgd 	} else if (dungeon[row][col] & TUNNEL) {
    123      1.1  cgd 			light_passage(row, col);
    124      1.1  cgd 	}
    125      1.1  cgd 	mvaddch(rogue.row, rogue.col, get_dungeon_char(rogue.row, rogue.col));
    126      1.1  cgd 	mvaddch(row, col, rogue.fchar);
    127      1.1  cgd 
    128      1.1  cgd 	if (!jump) {
    129      1.1  cgd 		refresh();
    130      1.1  cgd 	}
    131      1.1  cgd 	rogue.row = row;
    132      1.1  cgd 	rogue.col = col;
    133      1.1  cgd 	if (dungeon[row][col] & OBJECT) {
    134      1.1  cgd 		if (levitate && pickup) {
    135      1.1  cgd 			return(STOPPED_ON_SOMETHING);
    136      1.1  cgd 		}
    137      1.1  cgd 		if (pickup && !levitate) {
    138      1.1  cgd 			if (obj = pick_up(row, col, &status)) {
    139      1.1  cgd 				get_desc(obj, desc);
    140      1.1  cgd 				if (obj->what_is == GOLD) {
    141      1.1  cgd 					free_object(obj);
    142      1.1  cgd 					goto NOT_IN_PACK;
    143      1.1  cgd 				}
    144      1.1  cgd 			} else if (!status) {
    145      1.1  cgd 				goto MVED;
    146      1.1  cgd 			} else {
    147      1.1  cgd 				goto MOVE_ON;
    148      1.1  cgd 			}
    149      1.1  cgd 		} else {
    150      1.1  cgd MOVE_ON:
    151      1.1  cgd 			obj = object_at(&level_objects, row, col);
    152      1.1  cgd 			(void) strcpy(desc, "moved onto ");
    153      1.1  cgd 			get_desc(obj, desc+11);
    154      1.1  cgd 			goto NOT_IN_PACK;
    155      1.1  cgd 		}
    156      1.1  cgd 		n = strlen(desc);
    157      1.1  cgd 		desc[n] = '(';
    158      1.1  cgd 		desc[n+1] = obj->ichar;
    159      1.1  cgd 		desc[n+2] = ')';
    160      1.1  cgd 		desc[n+3] = 0;
    161      1.1  cgd NOT_IN_PACK:
    162      1.1  cgd 		message(desc, 1);
    163      1.1  cgd 		(void) reg_move();
    164      1.1  cgd 		return(STOPPED_ON_SOMETHING);
    165      1.1  cgd 	}
    166      1.1  cgd 	if (dungeon[row][col] & (DOOR | STAIRS | TRAP)) {
    167      1.1  cgd 		if ((!levitate) && (dungeon[row][col] & TRAP)) {
    168      1.1  cgd 			trap_player(row, col);
    169      1.1  cgd 		}
    170      1.1  cgd 		(void) reg_move();
    171      1.1  cgd 		return(STOPPED_ON_SOMETHING);
    172      1.1  cgd 	}
    173      1.1  cgd MVED:	if (reg_move()) {			/* fainted from hunger */
    174      1.1  cgd 			return(STOPPED_ON_SOMETHING);
    175      1.1  cgd 	}
    176      1.1  cgd 	return((confused ? STOPPED_ON_SOMETHING : MOVED));
    177      1.1  cgd }
    178      1.1  cgd 
    179      1.1  cgd multiple_move_rogue(dirch)
    180      1.1  cgd short dirch;
    181      1.1  cgd {
    182      1.1  cgd 	short row, col;
    183      1.1  cgd 	short m;
    184      1.1  cgd 
    185      1.1  cgd 	switch(dirch) {
    186      1.1  cgd 	case '\010':
    187      1.1  cgd 	case '\012':
    188      1.1  cgd 	case '\013':
    189      1.1  cgd 	case '\014':
    190      1.1  cgd 	case '\031':
    191      1.1  cgd 	case '\025':
    192      1.1  cgd 	case '\016':
    193      1.1  cgd 	case '\002':
    194      1.1  cgd 		do {
    195      1.1  cgd 			row = rogue.row;
    196      1.1  cgd 			col = rogue.col;
    197      1.1  cgd 			if (((m = one_move_rogue((dirch + 96), 1)) == MOVE_FAILED) ||
    198      1.1  cgd 				(m == STOPPED_ON_SOMETHING) ||
    199      1.1  cgd 				interrupted) {
    200      1.1  cgd 				break;
    201      1.1  cgd 			}
    202      1.1  cgd 		} while (!next_to_something(row, col));
    203      1.1  cgd 		if (	(!interrupted) && passgo && (m == MOVE_FAILED) &&
    204      1.1  cgd 				(dungeon[rogue.row][rogue.col] & TUNNEL)) {
    205      1.1  cgd 			turn_passage(dirch + 96, 0);
    206      1.1  cgd 		}
    207      1.1  cgd 		break;
    208      1.1  cgd 	case 'H':
    209      1.1  cgd 	case 'J':
    210      1.1  cgd 	case 'K':
    211      1.1  cgd 	case 'L':
    212      1.1  cgd 	case 'B':
    213      1.1  cgd 	case 'Y':
    214      1.1  cgd 	case 'U':
    215      1.1  cgd 	case 'N':
    216      1.1  cgd 		while ((!interrupted) && (one_move_rogue((dirch + 32), 1) == MOVED)) ;
    217      1.1  cgd 
    218      1.1  cgd 		if (	(!interrupted) && passgo &&
    219      1.1  cgd 				(dungeon[rogue.row][rogue.col] & TUNNEL)) {
    220      1.1  cgd 			turn_passage(dirch + 32, 1);
    221      1.1  cgd 		}
    222      1.1  cgd 		break;
    223      1.1  cgd 	}
    224      1.1  cgd }
    225      1.1  cgd 
    226      1.1  cgd is_passable(row, col)
    227      1.1  cgd register row, col;
    228      1.1  cgd {
    229      1.1  cgd 	if ((row < MIN_ROW) || (row > (DROWS - 2)) || (col < 0) ||
    230      1.1  cgd 		(col > (DCOLS-1))) {
    231      1.1  cgd 		return(0);
    232      1.1  cgd 	}
    233      1.1  cgd 	if (dungeon[row][col] & HIDDEN) {
    234      1.1  cgd 		return((dungeon[row][col] & TRAP) ? 1 : 0);
    235      1.1  cgd 	}
    236      1.1  cgd 	return(dungeon[row][col] & (FLOOR | TUNNEL | DOOR | STAIRS | TRAP));
    237      1.1  cgd }
    238      1.1  cgd 
    239      1.1  cgd next_to_something(drow, dcol)
    240      1.1  cgd register drow, dcol;
    241      1.1  cgd {
    242      1.1  cgd 	short i, j, i_end, j_end, row, col;
    243      1.1  cgd 	short pass_count = 0;
    244      1.1  cgd 	unsigned short s;
    245      1.1  cgd 
    246      1.1  cgd 	if (confused) {
    247      1.1  cgd 		return(1);
    248      1.1  cgd 	}
    249      1.1  cgd 	if (blind) {
    250      1.1  cgd 		return(0);
    251      1.1  cgd 	}
    252      1.1  cgd 	i_end = (rogue.row < (DROWS-2)) ? 1 : 0;
    253      1.1  cgd 	j_end = (rogue.col < (DCOLS-1)) ? 1 : 0;
    254      1.1  cgd 
    255      1.1  cgd 	for (i = ((rogue.row > MIN_ROW) ? -1 : 0); i <= i_end; i++) {
    256      1.1  cgd 		for (j = ((rogue.col > 0) ? -1 : 0); j <= j_end; j++) {
    257      1.1  cgd 			if ((i == 0) && (j == 0)) {
    258      1.1  cgd 				continue;
    259      1.1  cgd 			}
    260      1.1  cgd 			if (((rogue.row+i) == drow) && ((rogue.col+j) == dcol)) {
    261      1.1  cgd 				continue;
    262      1.1  cgd 			}
    263      1.1  cgd 			row = rogue.row + i;
    264      1.1  cgd 			col = rogue.col + j;
    265      1.1  cgd 			s = dungeon[row][col];
    266      1.1  cgd 			if (s & HIDDEN) {
    267      1.1  cgd 				continue;
    268      1.1  cgd 			}
    269      1.1  cgd 			/* If the rogue used to be right, up, left, down, or right of
    270      1.1  cgd 			 * row,col, and now isn't, then don't stop */
    271      1.1  cgd 			if (s & (MONSTER | OBJECT | STAIRS)) {
    272      1.1  cgd 				if (((row == drow) || (col == dcol)) &&
    273      1.1  cgd 					(!((row == rogue.row) || (col == rogue.col)))) {
    274      1.1  cgd 					continue;
    275      1.1  cgd 				}
    276      1.1  cgd 				return(1);
    277      1.1  cgd 			}
    278      1.1  cgd 			if (s & TRAP) {
    279      1.1  cgd 				if (!(s & HIDDEN)) {
    280      1.1  cgd 					if (((row == drow) || (col == dcol)) &&
    281      1.1  cgd 						(!((row == rogue.row) || (col == rogue.col)))) {
    282      1.1  cgd 						continue;
    283      1.1  cgd 					}
    284      1.1  cgd 					return(1);
    285      1.1  cgd 				}
    286      1.1  cgd 			}
    287      1.1  cgd 			if ((((i - j) == 1) || ((i - j) == -1)) && (s & TUNNEL)) {
    288      1.1  cgd 				if (++pass_count > 1) {
    289      1.1  cgd 					return(1);
    290      1.1  cgd 				}
    291      1.1  cgd 			}
    292      1.1  cgd 			if ((s & DOOR) && ((i == 0) || (j == 0))) {
    293      1.1  cgd 					return(1);
    294      1.1  cgd 			}
    295      1.1  cgd 		}
    296      1.1  cgd 	}
    297      1.1  cgd 	return(0);
    298      1.1  cgd }
    299      1.1  cgd 
    300      1.1  cgd can_move(row1, col1, row2, col2)
    301      1.1  cgd {
    302      1.1  cgd 	if (!is_passable(row2, col2)) {
    303      1.1  cgd 		return(0);
    304      1.1  cgd 	}
    305      1.1  cgd 	if ((row1 != row2) && (col1 != col2)) {
    306      1.1  cgd 		if ((dungeon[row1][col1] & DOOR) || (dungeon[row2][col2] & DOOR)) {
    307      1.1  cgd 			return(0);
    308      1.1  cgd 		}
    309      1.1  cgd 		if ((!dungeon[row1][col2]) || (!dungeon[row2][col1])) {
    310      1.1  cgd 			return(0);
    311      1.1  cgd 		}
    312      1.1  cgd 	}
    313      1.1  cgd 	return(1);
    314      1.1  cgd }
    315      1.1  cgd 
    316      1.1  cgd move_onto()
    317      1.1  cgd {
    318      1.1  cgd 	short ch, d;
    319      1.1  cgd 	boolean first_miss = 1;
    320      1.1  cgd 
    321      1.1  cgd 	while (!is_direction(ch = rgetchar(), &d)) {
    322      1.1  cgd 		sound_bell();
    323      1.1  cgd 		if (first_miss) {
    324      1.1  cgd 			message("direction? ", 0);
    325      1.1  cgd 			first_miss = 0;
    326      1.1  cgd 		}
    327      1.1  cgd 	}
    328      1.1  cgd 	check_message();
    329      1.1  cgd 	if (ch != CANCEL) {
    330      1.1  cgd 		(void) one_move_rogue(ch, 0);
    331      1.1  cgd 	}
    332      1.1  cgd }
    333      1.1  cgd 
    334      1.1  cgd boolean
    335      1.1  cgd is_direction(c, d)
    336      1.1  cgd short c;
    337      1.1  cgd short *d;
    338      1.1  cgd {
    339      1.1  cgd 	switch(c) {
    340      1.1  cgd 	case 'h':
    341      1.1  cgd 		*d = LEFT;
    342      1.1  cgd 		break;
    343      1.1  cgd 	case 'j':
    344      1.1  cgd 		*d = DOWN;
    345      1.1  cgd 		break;
    346      1.1  cgd 	case 'k':
    347      1.1  cgd 		*d = UPWARD;
    348      1.1  cgd 		break;
    349      1.1  cgd 	case 'l':
    350      1.1  cgd 		*d = RIGHT;
    351      1.1  cgd 		break;
    352      1.1  cgd 	case 'b':
    353      1.1  cgd 		*d = DOWNLEFT;
    354      1.1  cgd 		break;
    355      1.1  cgd 	case 'y':
    356      1.1  cgd 		*d = UPLEFT;
    357      1.1  cgd 		break;
    358      1.1  cgd 	case 'u':
    359      1.1  cgd 		*d = UPRIGHT;
    360      1.1  cgd 		break;
    361      1.1  cgd 	case 'n':
    362      1.1  cgd 		*d = DOWNRIGHT;
    363      1.1  cgd 		break;
    364      1.1  cgd 	case CANCEL:
    365      1.1  cgd 		break;
    366      1.1  cgd 	default:
    367      1.1  cgd 		return(0);
    368      1.1  cgd 	}
    369      1.1  cgd 	return(1);
    370      1.1  cgd }
    371      1.1  cgd 
    372      1.1  cgd boolean
    373      1.1  cgd check_hunger(msg_only)
    374      1.1  cgd boolean msg_only;
    375      1.1  cgd {
    376      1.1  cgd 	register short i, n;
    377      1.1  cgd 	boolean fainted = 0;
    378      1.1  cgd 
    379      1.1  cgd 	if (rogue.moves_left == HUNGRY) {
    380      1.1  cgd 		(void) strcpy(hunger_str, "hungry");
    381      1.1  cgd 		message(hunger_str, 0);
    382      1.1  cgd 		print_stats(STAT_HUNGER);
    383      1.1  cgd 	}
    384      1.1  cgd 	if (rogue.moves_left == WEAK) {
    385      1.1  cgd 		(void) strcpy(hunger_str, "weak");
    386      1.1  cgd 		message(hunger_str, 1);
    387      1.1  cgd 		print_stats(STAT_HUNGER);
    388      1.1  cgd 	}
    389      1.1  cgd 	if (rogue.moves_left <= FAINT) {
    390      1.1  cgd 		if (rogue.moves_left == FAINT) {
    391      1.1  cgd 			(void) strcpy(hunger_str, "faint");
    392      1.1  cgd 			message(hunger_str, 1);
    393      1.1  cgd 			print_stats(STAT_HUNGER);
    394      1.1  cgd 		}
    395      1.1  cgd 		n = get_rand(0, (FAINT - rogue.moves_left));
    396      1.1  cgd 		if (n > 0) {
    397      1.1  cgd 			fainted = 1;
    398      1.1  cgd 			if (rand_percent(40)) {
    399      1.1  cgd 				rogue.moves_left++;
    400      1.1  cgd 			}
    401      1.1  cgd 			message("you faint", 1);
    402      1.1  cgd 			for (i = 0; i < n; i++) {
    403      1.1  cgd 				if (coin_toss()) {
    404      1.1  cgd 					mv_mons();
    405      1.1  cgd 				}
    406      1.1  cgd 			}
    407      1.1  cgd 			message(you_can_move_again, 1);
    408      1.1  cgd 		}
    409      1.1  cgd 	}
    410      1.1  cgd 	if (msg_only) {
    411      1.1  cgd 		return(fainted);
    412      1.1  cgd 	}
    413      1.1  cgd 	if (rogue.moves_left <= STARVE) {
    414      1.1  cgd 		killed_by((object *) 0, STARVATION);
    415      1.1  cgd 	}
    416      1.1  cgd 
    417      1.1  cgd 	switch(e_rings) {
    418      1.1  cgd 	/*case -2:
    419      1.1  cgd 		Subtract 0, i.e. do nothing.
    420      1.1  cgd 		break;*/
    421      1.1  cgd 	case -1:
    422      1.1  cgd 		rogue.moves_left -= (rogue.moves_left % 2);
    423      1.1  cgd 		break;
    424      1.1  cgd 	case 0:
    425      1.1  cgd 		rogue.moves_left--;
    426      1.1  cgd 		break;
    427      1.1  cgd 	case 1:
    428      1.1  cgd 		rogue.moves_left--;
    429      1.1  cgd 		(void) check_hunger(1);
    430      1.1  cgd 		rogue.moves_left -= (rogue.moves_left % 2);
    431      1.1  cgd 		break;
    432      1.1  cgd 	case 2:
    433      1.1  cgd 		rogue.moves_left--;
    434      1.1  cgd 		(void) check_hunger(1);
    435      1.1  cgd 		rogue.moves_left--;
    436      1.1  cgd 		break;
    437      1.1  cgd 	}
    438      1.1  cgd 	return(fainted);
    439      1.1  cgd }
    440      1.1  cgd 
    441      1.1  cgd boolean
    442      1.1  cgd reg_move()
    443      1.1  cgd {
    444      1.1  cgd 	boolean fainted;
    445      1.1  cgd 
    446      1.1  cgd 	if ((rogue.moves_left <= HUNGRY) || (cur_level >= max_level)) {
    447      1.1  cgd 		fainted = check_hunger(0);
    448      1.1  cgd 	} else {
    449      1.1  cgd 		fainted = 0;
    450      1.1  cgd 	}
    451      1.1  cgd 
    452      1.1  cgd 	mv_mons();
    453      1.1  cgd 
    454      1.1  cgd 	if (++m_moves >= 120) {
    455      1.1  cgd 		m_moves = 0;
    456      1.1  cgd 		wanderer();
    457      1.1  cgd 	}
    458      1.1  cgd 	if (halluc) {
    459      1.1  cgd 		if (!(--halluc)) {
    460      1.1  cgd 			unhallucinate();
    461      1.1  cgd 		} else {
    462      1.1  cgd 			hallucinate();
    463      1.1  cgd 		}
    464      1.1  cgd 	}
    465      1.1  cgd 	if (blind) {
    466      1.1  cgd 		if (!(--blind)) {
    467      1.1  cgd 			unblind();
    468      1.1  cgd 		}
    469      1.1  cgd 	}
    470      1.1  cgd 	if (confused) {
    471      1.1  cgd 		if (!(--confused)) {
    472      1.1  cgd 			unconfuse();
    473      1.1  cgd 		}
    474      1.1  cgd 	}
    475      1.1  cgd 	if (bear_trap) {
    476      1.1  cgd 		bear_trap--;
    477      1.1  cgd 	}
    478      1.1  cgd 	if (levitate) {
    479      1.1  cgd 		if (!(--levitate)) {
    480      1.1  cgd 			message("you float gently to the ground", 1);
    481      1.1  cgd 			if (dungeon[rogue.row][rogue.col] & TRAP) {
    482      1.1  cgd 				trap_player(rogue.row, rogue.col);
    483      1.1  cgd 			}
    484      1.1  cgd 		}
    485      1.1  cgd 	}
    486      1.1  cgd 	if (haste_self) {
    487      1.1  cgd 		if (!(--haste_self)) {
    488      1.1  cgd 			message("you feel yourself slowing down", 0);
    489      1.1  cgd 		}
    490      1.1  cgd 	}
    491      1.1  cgd 	heal();
    492      1.1  cgd 	if (auto_search > 0) {
    493      1.1  cgd 		search(auto_search, auto_search);
    494      1.1  cgd 	}
    495      1.1  cgd 	return(fainted);
    496      1.1  cgd }
    497      1.1  cgd 
    498      1.1  cgd rest(count)
    499      1.1  cgd {
    500      1.1  cgd 	int i;
    501      1.1  cgd 
    502      1.1  cgd 	interrupted = 0;
    503      1.1  cgd 
    504      1.1  cgd 	for (i = 0; i < count; i++) {
    505      1.1  cgd 		if (interrupted) {
    506      1.1  cgd 			break;
    507      1.1  cgd 		}
    508      1.1  cgd 		(void) reg_move();
    509      1.1  cgd 	}
    510      1.1  cgd }
    511      1.1  cgd 
    512      1.1  cgd gr_dir()
    513      1.1  cgd {
    514      1.1  cgd 	short d;
    515      1.1  cgd 
    516      1.1  cgd 	d = get_rand(1, 8);
    517      1.1  cgd 
    518      1.1  cgd 	switch(d) {
    519      1.1  cgd 		case 1:
    520      1.1  cgd 			d = 'j';
    521      1.1  cgd 			break;
    522      1.1  cgd 		case 2:
    523      1.1  cgd 			d = 'k';
    524      1.1  cgd 			break;
    525      1.1  cgd 		case 3:
    526      1.1  cgd 			d = 'l';
    527      1.1  cgd 			break;
    528      1.1  cgd 		case 4:
    529      1.1  cgd 			d = 'h';
    530      1.1  cgd 			break;
    531      1.1  cgd 		case 5:
    532      1.1  cgd 			d = 'y';
    533      1.1  cgd 			break;
    534      1.1  cgd 		case 6:
    535      1.1  cgd 			d = 'u';
    536      1.1  cgd 			break;
    537      1.1  cgd 		case 7:
    538      1.1  cgd 			d = 'b';
    539      1.1  cgd 			break;
    540      1.1  cgd 		case 8:
    541      1.1  cgd 			d = 'n';
    542      1.1  cgd 			break;
    543      1.1  cgd 	}
    544      1.1  cgd 	return(d);
    545      1.1  cgd }
    546      1.1  cgd 
    547      1.1  cgd heal()
    548      1.1  cgd {
    549      1.1  cgd 	static short heal_exp = -1, n, c = 0;
    550      1.1  cgd 	static boolean alt;
    551      1.1  cgd 
    552      1.1  cgd 	if (rogue.hp_current == rogue.hp_max) {
    553      1.1  cgd 		c = 0;
    554      1.1  cgd 		return;
    555      1.1  cgd 	}
    556      1.1  cgd 	if (rogue.exp != heal_exp) {
    557      1.1  cgd 		heal_exp = rogue.exp;
    558      1.1  cgd 
    559      1.1  cgd 		switch(heal_exp) {
    560      1.1  cgd 		case 1:
    561      1.1  cgd 			n = 20;
    562      1.1  cgd 			break;
    563      1.1  cgd 		case 2:
    564      1.1  cgd 			n = 18;
    565      1.1  cgd 			break;
    566      1.1  cgd 		case 3:
    567      1.1  cgd 			n = 17;
    568      1.1  cgd 			break;
    569      1.1  cgd 		case 4:
    570      1.1  cgd 			n = 14;
    571      1.1  cgd 			break;
    572      1.1  cgd 		case 5:
    573      1.1  cgd 			n = 13;
    574      1.1  cgd 			break;
    575      1.1  cgd 		case 6:
    576      1.1  cgd 			n = 10;
    577      1.1  cgd 			break;
    578      1.1  cgd 		case 7:
    579      1.1  cgd 			n = 9;
    580      1.1  cgd 			break;
    581      1.1  cgd 		case 8:
    582      1.1  cgd 			n = 8;
    583      1.1  cgd 			break;
    584      1.1  cgd 		case 9:
    585      1.1  cgd 			n = 7;
    586      1.1  cgd 			break;
    587      1.1  cgd 		case 10:
    588      1.1  cgd 			n = 4;
    589      1.1  cgd 			break;
    590      1.1  cgd 		case 11:
    591      1.1  cgd 			n = 3;
    592      1.1  cgd 			break;
    593      1.1  cgd 		case 12:
    594      1.1  cgd 		default:
    595      1.1  cgd 			n = 2;
    596      1.1  cgd 		}
    597      1.1  cgd 	}
    598      1.1  cgd 	if (++c >= n) {
    599      1.1  cgd 		c = 0;
    600      1.1  cgd 		rogue.hp_current++;
    601      1.1  cgd 		if (alt = !alt) {
    602      1.1  cgd 			rogue.hp_current++;
    603      1.1  cgd 		}
    604      1.1  cgd 		if ((rogue.hp_current += regeneration) > rogue.hp_max) {
    605      1.1  cgd 			rogue.hp_current = rogue.hp_max;
    606      1.1  cgd 		}
    607      1.1  cgd 		print_stats(STAT_HP);
    608      1.1  cgd 	}
    609      1.1  cgd }
    610      1.1  cgd 
    611      1.1  cgd static boolean
    612      1.1  cgd can_turn(nrow, ncol)
    613      1.1  cgd short nrow, ncol;
    614      1.1  cgd {
    615      1.1  cgd 	if ((dungeon[nrow][ncol] & TUNNEL) && is_passable(nrow, ncol)) {
    616      1.1  cgd 		return(1);
    617      1.1  cgd 	}
    618      1.1  cgd 	return(0);
    619      1.1  cgd }
    620      1.1  cgd 
    621      1.1  cgd turn_passage(dir, fast)
    622      1.1  cgd short dir;
    623      1.1  cgd boolean fast;
    624      1.1  cgd {
    625      1.1  cgd 	short crow = rogue.row, ccol = rogue.col, turns = 0;
    626      1.1  cgd 	short ndir;
    627      1.1  cgd 
    628      1.1  cgd 	if ((dir != 'h') && can_turn(crow, ccol + 1)) {
    629      1.1  cgd 		turns++;
    630      1.1  cgd 		ndir = 'l';
    631      1.1  cgd 	}
    632      1.1  cgd 	if ((dir != 'l') && can_turn(crow, ccol - 1)) {
    633      1.1  cgd 		turns++;
    634      1.1  cgd 		ndir = 'h';
    635      1.1  cgd 	}
    636      1.1  cgd 	if ((dir != 'k') && can_turn(crow + 1, ccol)) {
    637      1.1  cgd 		turns++;
    638      1.1  cgd 		ndir = 'j';
    639      1.1  cgd 	}
    640      1.1  cgd 	if ((dir != 'j') && can_turn(crow - 1, ccol)) {
    641      1.1  cgd 		turns++;
    642      1.1  cgd 		ndir = 'k';
    643      1.1  cgd 	}
    644      1.1  cgd 	if (turns == 1) {
    645      1.1  cgd 		multiple_move_rogue(ndir - (fast ? 32 : 96));
    646      1.1  cgd 	}
    647      1.1  cgd }
    648