Home | History | Annotate | Line # | Download | only in rogue
level.c revision 1.1
      1 /*
      2  * Copyright (c) 1988 The Regents of the University of California.
      3  * All rights reserved.
      4  *
      5  * This code is derived from software contributed to Berkeley by
      6  * Timothy C. Stoehr.
      7  *
      8  * Redistribution and use in source and binary forms, with or without
      9  * modification, are permitted provided that the following conditions
     10  * are met:
     11  * 1. Redistributions of source code must retain the above copyright
     12  *    notice, this list of conditions and the following disclaimer.
     13  * 2. Redistributions in binary form must reproduce the above copyright
     14  *    notice, this list of conditions and the following disclaimer in the
     15  *    documentation and/or other materials provided with the distribution.
     16  * 3. All advertising materials mentioning features or use of this software
     17  *    must display the following acknowledgement:
     18  *	This product includes software developed by the University of
     19  *	California, Berkeley and its contributors.
     20  * 4. Neither the name of the University nor the names of its contributors
     21  *    may be used to endorse or promote products derived from this software
     22  *    without specific prior written permission.
     23  *
     24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     34  * SUCH DAMAGE.
     35  */
     36 
     37 #ifndef lint
     38 static char sccsid[] = "@(#)level.c	5.3 (Berkeley) 6/1/90";
     39 #endif /* not lint */
     40 
     41 /*
     42  * level.c
     43  *
     44  * This source herein may be modified and/or distributed by anybody who
     45  * so desires, with the following restrictions:
     46  *    1.)  No portion of this notice shall be removed.
     47  *    2.)  Credit shall not be taken for the creation of this source.
     48  *    3.)  This code is not to be traded, sold, or used for personal
     49  *         gain or profit.
     50  *
     51  */
     52 
     53 #include "rogue.h"
     54 
     55 #define swap(x,y) {t = x; x = y; y = t;}
     56 
     57 short cur_level = 0;
     58 short max_level = 1;
     59 short cur_room;
     60 char *new_level_message = 0;
     61 short party_room = NO_ROOM;
     62 short r_de;
     63 
     64 long level_points[MAX_EXP_LEVEL] = {
     65 		  10L,
     66 		  20L,
     67 		  40L,
     68 		  80L,
     69 		 160L,
     70 		 320L,
     71 		 640L,
     72 		1300L,
     73 		2600L,
     74 		5200L,
     75 	   10000L,
     76 	   20000L,
     77 	   40000L,
     78 	   80000L,
     79 	  160000L,
     80 	  320000L,
     81 	 1000000L,
     82 	 3333333L,
     83 	 6666666L,
     84 	  MAX_EXP,
     85 	99900000L
     86 };
     87 
     88 short random_rooms[MAXROOMS] = {3, 7, 5, 2, 0, 6, 1, 4, 8};
     89 
     90 extern boolean being_held, wizard, detect_monster;
     91 extern boolean see_invisible;
     92 extern short bear_trap, levitate, extra_hp, less_hp, cur_room;
     93 
     94 make_level()
     95 {
     96 	short i, j;
     97 	short must_1, must_2, must_3;
     98 	boolean big_room;
     99 
    100 	if (cur_level < LAST_DUNGEON) {
    101 		cur_level++;
    102 	}
    103 	if (cur_level > max_level) {
    104 		max_level = cur_level;
    105 	}
    106 	must_1 = get_rand(0, 5);
    107 
    108 	switch(must_1) {
    109 	case 0:
    110 		must_1 = 0;
    111 		must_2 = 1;
    112 		must_3 = 2;
    113 		break;
    114 	case 1:
    115 		must_1 = 3;
    116 		must_2 = 4;
    117 		must_3 = 5;
    118 		break;
    119 	case 2:
    120 		must_1 = 6;
    121 		must_2 = 7;
    122 		must_3 = 8;
    123 		break;
    124 	case 3:
    125 		must_1 = 0;
    126 		must_2 = 3;
    127 		must_3 = 6;
    128 		break;
    129 	case 4:
    130 		must_1 = 1;
    131 		must_2 = 4;
    132 		must_3 = 7;
    133 		break;
    134 	case 5:
    135 		must_1 = 2;
    136 		must_2 = 5;
    137 		must_3 = 8;
    138 		break;
    139 	}
    140 	if (rand_percent(8)) {
    141 		party_room = 0;
    142 	}
    143 	big_room = ((party_room != NO_ROOM) && rand_percent(1));
    144 	if (big_room) {
    145 		make_room(BIG_ROOM, 0, 0, 0);
    146 	} else {
    147 		for (i = 0; i < MAXROOMS; i++) {
    148 			make_room(i, must_1, must_2, must_3);
    149 		}
    150 	}
    151 	if (!big_room) {
    152 		add_mazes();
    153 
    154 		mix_random_rooms();
    155 
    156 		for (j = 0; j < MAXROOMS; j++) {
    157 
    158 			i = random_rooms[j];
    159 
    160 			if (i < (MAXROOMS-1)) {
    161 				(void) connect_rooms(i, i+1);
    162 			}
    163 			if (i < (MAXROOMS-3)) {
    164 				(void) connect_rooms(i, i+3);
    165 			}
    166 			if (i < (MAXROOMS-2)) {
    167 				if (rooms[i+1].is_room & R_NOTHING) {
    168 					if (connect_rooms(i, i+2)) {
    169 						rooms[i+1].is_room = R_CROSS;
    170 					}
    171 				}
    172 			}
    173 			if (i < (MAXROOMS-6)) {
    174 				if (rooms[i+3].is_room & R_NOTHING) {
    175 					if (connect_rooms(i, i+6)) {
    176 						rooms[i+3].is_room = R_CROSS;
    177 					}
    178 				}
    179 			}
    180 			if (is_all_connected()) {
    181 				break;
    182 			}
    183 		}
    184 		fill_out_level();
    185 	}
    186 	if (!has_amulet() && (cur_level >= AMULET_LEVEL)) {
    187 		put_amulet();
    188 	}
    189 }
    190 
    191 make_room(rn, r1, r2, r3)
    192 short rn, r1, r2, r3;
    193 {
    194 	short left_col, right_col, top_row, bottom_row;
    195 	short width, height;
    196 	short row_offset, col_offset;
    197 	short i, j, ch;
    198 
    199 	switch(rn) {
    200 	case 0:
    201 		left_col = 0;
    202 		right_col = COL1-1;
    203 		top_row = MIN_ROW;
    204 		bottom_row = ROW1-1;
    205 		break;
    206 	case 1:
    207 		left_col = COL1+1;
    208 		right_col = COL2-1;
    209 		top_row = MIN_ROW;
    210 		bottom_row = ROW1-1;
    211 		break;
    212 	case 2:
    213 		left_col = COL2+1;
    214 		right_col = DCOLS-1;
    215 		top_row = MIN_ROW;
    216 		bottom_row = ROW1-1;
    217 		break;
    218 	case 3:
    219 		left_col = 0;
    220 		right_col = COL1-1;
    221 		top_row = ROW1+1;
    222 		bottom_row = ROW2-1;
    223 		break;
    224 	case 4:
    225 		left_col = COL1+1;
    226 		right_col = COL2-1;
    227 		top_row = ROW1+1;
    228 		bottom_row = ROW2-1;
    229 		break;
    230 	case 5:
    231 		left_col = COL2+1;
    232 		right_col = DCOLS-1;
    233 		top_row = ROW1+1;
    234 		bottom_row = ROW2-1;
    235 		break;
    236 	case 6:
    237 		left_col = 0;
    238 		right_col = COL1-1;
    239 		top_row = ROW2+1;
    240 		bottom_row = DROWS - 2;
    241 		break;
    242 	case 7:
    243 		left_col = COL1+1;
    244 		right_col = COL2-1;
    245 		top_row = ROW2+1;
    246 		bottom_row = DROWS - 2;
    247 		break;
    248 	case 8:
    249 		left_col = COL2+1;
    250 		right_col = DCOLS-1;
    251 		top_row = ROW2+1;
    252 		bottom_row = DROWS - 2;
    253 		break;
    254 	case BIG_ROOM:
    255 		top_row = get_rand(MIN_ROW, MIN_ROW+5);
    256 		bottom_row = get_rand(DROWS-7, DROWS-2);
    257 		left_col = get_rand(0, 10);;
    258 		right_col = get_rand(DCOLS-11, DCOLS-1);
    259 		rn = 0;
    260 		goto B;
    261 	}
    262 	height = get_rand(4, (bottom_row - top_row + 1));
    263 	width = get_rand(7, (right_col - left_col - 2));
    264 
    265 	row_offset = get_rand(0, ((bottom_row - top_row) - height + 1));
    266 	col_offset = get_rand(0, ((right_col - left_col) - width + 1));
    267 
    268 	top_row += row_offset;
    269 	bottom_row = top_row + height - 1;
    270 
    271 	left_col += col_offset;
    272 	right_col = left_col + width - 1;
    273 
    274 	if ((rn != r1) && (rn != r2) && (rn != r3) && rand_percent(40)) {
    275 		goto END;
    276 	}
    277 B:
    278 	rooms[rn].is_room = R_ROOM;
    279 
    280 	for (i = top_row; i <= bottom_row; i++) {
    281 		for (j = left_col; j <= right_col; j++) {
    282 			if ((i == top_row) || (i == bottom_row)) {
    283 				ch = HORWALL;
    284 			} else if (	((i != top_row) && (i != bottom_row)) &&
    285 						((j == left_col) || (j == right_col))) {
    286 				ch = VERTWALL;
    287 			} else {
    288 				ch = FLOOR;
    289 			}
    290 			dungeon[i][j] = ch;
    291 		}
    292 	}
    293 END:
    294 	rooms[rn].top_row = top_row;
    295 	rooms[rn].bottom_row = bottom_row;
    296 	rooms[rn].left_col = left_col;
    297 	rooms[rn].right_col = right_col;
    298 }
    299 
    300 connect_rooms(room1, room2)
    301 short room1, room2;
    302 {
    303 	short row1, col1, row2, col2, dir;
    304 
    305 	if ((!(rooms[room1].is_room & (R_ROOM | R_MAZE))) ||
    306 		(!(rooms[room2].is_room & (R_ROOM | R_MAZE)))) {
    307 		return(0);
    308 	}
    309 	if (same_row(room1, room2) &&
    310 		(rooms[room1].left_col > rooms[room2].right_col)) {
    311 		put_door(&rooms[room1], LEFT, &row1, &col1);
    312 		put_door(&rooms[room2], RIGHT, &row2, &col2);
    313 		dir = LEFT;
    314 	} else if (same_row(room1, room2) &&
    315 		(rooms[room2].left_col > rooms[room1].right_col)) {
    316 		put_door(&rooms[room1], RIGHT, &row1, &col1);
    317 		put_door(&rooms[room2], LEFT, &row2, &col2);
    318 		dir = RIGHT;
    319 	} else if (same_col(room1, room2) &&
    320 		(rooms[room1].top_row > rooms[room2].bottom_row)) {
    321 		put_door(&rooms[room1], UPWARD, &row1, &col1);
    322 		put_door(&rooms[room2], DOWN, &row2, &col2);
    323 		dir = UPWARD;
    324 	} else if (same_col(room1, room2) &&
    325 		(rooms[room2].top_row > rooms[room1].bottom_row)) {
    326 		put_door(&rooms[room1], DOWN, &row1, &col1);
    327 		put_door(&rooms[room2], UPWARD, &row2, &col2);
    328 		dir = DOWN;
    329 	} else {
    330 		return(0);
    331 	}
    332 
    333 	do {
    334 		draw_simple_passage(row1, col1, row2, col2, dir);
    335 	} while (rand_percent(4));
    336 
    337 	rooms[room1].doors[dir/2].oth_room = room2;
    338 	rooms[room1].doors[dir/2].oth_row = row2;
    339 	rooms[room1].doors[dir/2].oth_col = col2;
    340 
    341 	rooms[room2].doors[(((dir+4)%DIRS)/2)].oth_room = room1;
    342 	rooms[room2].doors[(((dir+4)%DIRS)/2)].oth_row = row1;
    343 	rooms[room2].doors[(((dir+4)%DIRS)/2)].oth_col = col1;
    344 	return(1);
    345 }
    346 
    347 clear_level()
    348 {
    349 	short i, j;
    350 
    351 	for (i = 0; i < MAXROOMS; i++) {
    352 		rooms[i].is_room = R_NOTHING;
    353 		for (j = 0; j < 4; j++) {
    354 			rooms[i].doors[j].oth_room = NO_ROOM;
    355 		}
    356 	}
    357 
    358 	for (i = 0; i < MAX_TRAPS; i++) {
    359 		traps[i].trap_type = NO_TRAP;
    360 	}
    361 	for (i = 0; i < DROWS; i++) {
    362 		for (j = 0; j < DCOLS; j++) {
    363 			dungeon[i][j] = NOTHING;
    364 		}
    365 	}
    366 	detect_monster = see_invisible = 0;
    367 	being_held = bear_trap = 0;
    368 	party_room = NO_ROOM;
    369 	rogue.row = rogue.col = -1;
    370 	clear();
    371 }
    372 
    373 put_door(rm, dir, row, col)
    374 room *rm;
    375 short dir;
    376 short *row, *col;
    377 {
    378 	short wall_width;
    379 
    380 	wall_width = (rm->is_room & R_MAZE) ? 0 : 1;
    381 
    382 	switch(dir) {
    383 	case UPWARD:
    384 	case DOWN:
    385 		*row = ((dir == UPWARD) ? rm->top_row : rm->bottom_row);
    386 		do {
    387 			*col = get_rand(rm->left_col+wall_width,
    388 				rm->right_col-wall_width);
    389 		} while (!(dungeon[*row][*col] & (HORWALL | TUNNEL)));
    390 		break;
    391 	case RIGHT:
    392 	case LEFT:
    393 		*col = (dir == LEFT) ? rm->left_col : rm->right_col;
    394 		do {
    395 			*row = get_rand(rm->top_row+wall_width,
    396 				rm->bottom_row-wall_width);
    397 		} while (!(dungeon[*row][*col] & (VERTWALL | TUNNEL)));
    398 		break;
    399 	}
    400 	if (rm->is_room & R_ROOM) {
    401 		dungeon[*row][*col] = DOOR;
    402 	}
    403 	if ((cur_level > 2) && rand_percent(HIDE_PERCENT)) {
    404 		dungeon[*row][*col] |= HIDDEN;
    405 	}
    406 	rm->doors[dir/2].door_row = *row;
    407 	rm->doors[dir/2].door_col = *col;
    408 }
    409 
    410 draw_simple_passage(row1, col1, row2, col2, dir)
    411 short row1, col1, row2, col2, dir;
    412 {
    413 	short i, middle, t;
    414 
    415 	if ((dir == LEFT) || (dir == RIGHT)) {
    416 		if (col1 > col2) {
    417 			swap(row1, row2);
    418 			swap(col1, col2);
    419 		}
    420 		middle = get_rand(col1+1, col2-1);
    421 		for (i = col1+1; i != middle; i++) {
    422 			dungeon[row1][i] = TUNNEL;
    423 		}
    424 		for (i = row1; i != row2; i += (row1 > row2) ? -1 : 1) {
    425 			dungeon[i][middle] = TUNNEL;
    426 		}
    427 		for (i = middle; i != col2; i++) {
    428 			dungeon[row2][i] = TUNNEL;
    429 		}
    430 	} else {
    431 		if (row1 > row2) {
    432 			swap(row1, row2);
    433 			swap(col1, col2);
    434 		}
    435 		middle = get_rand(row1+1, row2-1);
    436 		for (i = row1+1; i != middle; i++) {
    437 			dungeon[i][col1] = TUNNEL;
    438 		}
    439 		for (i = col1; i != col2; i += (col1 > col2) ? -1 : 1) {
    440 			dungeon[middle][i] = TUNNEL;
    441 		}
    442 		for (i = middle; i != row2; i++) {
    443 			dungeon[i][col2] = TUNNEL;
    444 		}
    445 	}
    446 	if (rand_percent(HIDE_PERCENT)) {
    447 		hide_boxed_passage(row1, col1, row2, col2, 1);
    448 	}
    449 }
    450 
    451 same_row(room1, room2)
    452 {
    453 	return((room1 / 3) == (room2 / 3));
    454 }
    455 
    456 same_col(room1, room2)
    457 {
    458 	return((room1 % 3) == (room2 % 3));
    459 }
    460 
    461 add_mazes()
    462 {
    463 	short i, j;
    464 	short start;
    465 	short maze_percent;
    466 
    467 	if (cur_level > 1) {
    468 		start = get_rand(0, (MAXROOMS-1));
    469 		maze_percent = (cur_level * 5) / 4;
    470 
    471 		if (cur_level > 15) {
    472 			maze_percent += cur_level;
    473 		}
    474 		for (i = 0; i < MAXROOMS; i++) {
    475 			j = ((start + i) % MAXROOMS);
    476 			if (rooms[j].is_room & R_NOTHING) {
    477 				if (rand_percent(maze_percent)) {
    478 				rooms[j].is_room = R_MAZE;
    479 				make_maze(get_rand(rooms[j].top_row+1, rooms[j].bottom_row-1),
    480 					get_rand(rooms[j].left_col+1, rooms[j].right_col-1),
    481 					rooms[j].top_row, rooms[j].bottom_row,
    482 					rooms[j].left_col, rooms[j].right_col);
    483 				hide_boxed_passage(rooms[j].top_row, rooms[j].left_col,
    484 					rooms[j].bottom_row, rooms[j].right_col,
    485 					get_rand(0, 2));
    486 				}
    487 			}
    488 		}
    489 	}
    490 }
    491 
    492 fill_out_level()
    493 {
    494 	short i, rn;
    495 
    496 	mix_random_rooms();
    497 
    498 	r_de = NO_ROOM;
    499 
    500 	for (i = 0; i < MAXROOMS; i++) {
    501 		rn = random_rooms[i];
    502 		if ((rooms[rn].is_room & R_NOTHING) ||
    503 			((rooms[rn].is_room & R_CROSS) && coin_toss())) {
    504 			fill_it(rn, 1);
    505 		}
    506 	}
    507 	if (r_de != NO_ROOM) {
    508 		fill_it(r_de, 0);
    509 	}
    510 }
    511 
    512 fill_it(rn, do_rec_de)
    513 int rn;
    514 boolean do_rec_de;
    515 {
    516 	short i, tunnel_dir, door_dir, drow, dcol;
    517 	short target_room, rooms_found = 0;
    518 	short srow, scol, t;
    519 	static short offsets[4] = {-1, 1, 3, -3};
    520 	boolean did_this = 0;
    521 
    522 	for (i = 0; i < 10; i++) {
    523 		srow = get_rand(0, 3);
    524 		scol = get_rand(0, 3);
    525 		t = offsets[srow];
    526 		offsets[srow] = offsets[scol];
    527 		offsets[scol] = t;
    528 	}
    529 	for (i = 0; i < 4; i++) {
    530 
    531 		target_room = rn + offsets[i];
    532 
    533 		if (((target_room < 0) || (target_room >= MAXROOMS)) ||
    534 			(!(same_row(rn,target_room) || same_col(rn,target_room))) ||
    535 			(!(rooms[target_room].is_room & (R_ROOM | R_MAZE)))) {
    536 			continue;
    537 		}
    538 		if (same_row(rn, target_room)) {
    539 			tunnel_dir = (rooms[rn].left_col < rooms[target_room].left_col) ?
    540 				RIGHT : LEFT;
    541 		} else {
    542 			tunnel_dir = (rooms[rn].top_row < rooms[target_room].top_row) ?
    543 				DOWN : UPWARD;
    544 		}
    545 		door_dir = ((tunnel_dir + 4) % DIRS);
    546 		if (rooms[target_room].doors[door_dir/2].oth_room != NO_ROOM) {
    547 			continue;
    548 		}
    549 		if (((!do_rec_de) || did_this) ||
    550 			(!mask_room(rn, &srow, &scol, TUNNEL))) {
    551 			srow = (rooms[rn].top_row + rooms[rn].bottom_row) / 2;
    552 			scol = (rooms[rn].left_col + rooms[rn].right_col) / 2;
    553 		}
    554 		put_door(&rooms[target_room], door_dir, &drow, &dcol);
    555 		rooms_found++;
    556 		draw_simple_passage(srow, scol, drow, dcol, tunnel_dir);
    557 		rooms[rn].is_room = R_DEADEND;
    558 		dungeon[srow][scol] = TUNNEL;
    559 
    560 		if ((i < 3) && (!did_this)) {
    561 			did_this = 1;
    562 			if (coin_toss()) {
    563 				continue;
    564 			}
    565 		}
    566 		if ((rooms_found < 2) && do_rec_de) {
    567 			recursive_deadend(rn, offsets, srow, scol);
    568 		}
    569 		break;
    570 	}
    571 }
    572 
    573 recursive_deadend(rn, offsets, srow, scol)
    574 short rn;
    575 short *offsets;
    576 short srow, scol;
    577 {
    578 	short i, de;
    579 	short drow, dcol, tunnel_dir;
    580 
    581 	rooms[rn].is_room = R_DEADEND;
    582 	dungeon[srow][scol] = TUNNEL;
    583 
    584 	for (i = 0; i < 4; i++) {
    585 		de = rn + offsets[i];
    586 		if (((de < 0) || (de >= MAXROOMS)) ||
    587 			(!(same_row(rn, de) || same_col(rn, de)))) {
    588 			continue;
    589 		}
    590 		if (!(rooms[de].is_room & R_NOTHING)) {
    591 			continue;
    592 		}
    593 		drow = (rooms[de].top_row + rooms[de].bottom_row) / 2;
    594 		dcol = (rooms[de].left_col + rooms[de].right_col) / 2;
    595 		if (same_row(rn, de)) {
    596 			tunnel_dir = (rooms[rn].left_col < rooms[de].left_col) ?
    597 				RIGHT : LEFT;
    598 		} else {
    599 			tunnel_dir = (rooms[rn].top_row < rooms[de].top_row) ?
    600 				DOWN : UPWARD;
    601 		}
    602 		draw_simple_passage(srow, scol, drow, dcol, tunnel_dir);
    603 		r_de = de;
    604 		recursive_deadend(de, offsets, drow, dcol);
    605 	}
    606 }
    607 
    608 boolean
    609 mask_room(rn, row, col, mask)
    610 short rn;
    611 short *row, *col;
    612 unsigned short mask;
    613 {
    614 	short i, j;
    615 
    616 	for (i = rooms[rn].top_row; i <= rooms[rn].bottom_row; i++) {
    617 		for (j = rooms[rn].left_col; j <= rooms[rn].right_col; j++) {
    618 			if (dungeon[i][j] & mask) {
    619 				*row = i;
    620 				*col = j;
    621 				return(1);
    622 			}
    623 		}
    624 	}
    625 	return(0);
    626 }
    627 
    628 make_maze(r, c, tr, br, lc, rc)
    629 short r, c, tr, br, lc, rc;
    630 {
    631 	char dirs[4];
    632 	short i, t;
    633 
    634 	dirs[0] = UPWARD;
    635 	dirs[1] = DOWN;
    636 	dirs[2] = LEFT;
    637 	dirs[3] = RIGHT;
    638 
    639 	dungeon[r][c] = TUNNEL;
    640 
    641 	if (rand_percent(20)) {
    642 		for (i = 0; i < 10; i++) {
    643 			short t1, t2;
    644 
    645 			t1 = get_rand(0, 3);
    646 			t2 = get_rand(0, 3);
    647 
    648 			swap(dirs[t1], dirs[t2]);
    649 		}
    650 	}
    651 	for (i = 0; i < 4; i++) {
    652 		switch(dirs[i]) {
    653 		case UPWARD:
    654 			if (((r-1) >= tr) &&
    655 				(dungeon[r-1][c] != TUNNEL) &&
    656 				(dungeon[r-1][c-1] != TUNNEL) &&
    657 				(dungeon[r-1][c+1] != TUNNEL) &&
    658 				(dungeon[r-2][c] != TUNNEL)) {
    659 				make_maze((r-1), c, tr, br, lc, rc);
    660 			}
    661 			break;
    662 		case DOWN:
    663 			if (((r+1) <= br) &&
    664 				(dungeon[r+1][c] != TUNNEL) &&
    665 				(dungeon[r+1][c-1] != TUNNEL) &&
    666 				(dungeon[r+1][c+1] != TUNNEL) &&
    667 				(dungeon[r+2][c] != TUNNEL)) {
    668 				make_maze((r+1), c, tr, br, lc, rc);
    669 			}
    670 			break;
    671 		case LEFT:
    672 			if (((c-1) >= lc) &&
    673 				(dungeon[r][c-1] != TUNNEL) &&
    674 				(dungeon[r-1][c-1] != TUNNEL) &&
    675 				(dungeon[r+1][c-1] != TUNNEL) &&
    676 				(dungeon[r][c-2] != TUNNEL)) {
    677 				make_maze(r, (c-1), tr, br, lc, rc);
    678 			}
    679 			break;
    680 		case RIGHT:
    681 			if (((c+1) <= rc) &&
    682 				(dungeon[r][c+1] != TUNNEL) &&
    683 				(dungeon[r-1][c+1] != TUNNEL) &&
    684 				(dungeon[r+1][c+1] != TUNNEL) &&
    685 				(dungeon[r][c+2] != TUNNEL)) {
    686 				make_maze(r, (c+1), tr, br, lc, rc);
    687 			}
    688 			break;
    689 		}
    690 	}
    691 }
    692 
    693 hide_boxed_passage(row1, col1, row2, col2, n)
    694 short row1, col1, row2, col2, n;
    695 {
    696 	short i, j, t;
    697 	short row, col, row_cut, col_cut;
    698 	short h, w;
    699 
    700 	if (cur_level > 2) {
    701 		if (row1 > row2) {
    702 			swap(row1, row2);
    703 		}
    704 		if (col1 > col2) {
    705 			swap(col1, col2);
    706 		}
    707 		h = row2 - row1;
    708 		w = col2 - col1;
    709 
    710 		if ((w >= 5) || (h >= 5)) {
    711 			row_cut = ((h >= 2) ? 1 : 0);
    712 			col_cut = ((w >= 2) ? 1 : 0);
    713 
    714 			for (i = 0; i < n; i++) {
    715 				for (j = 0; j < 10; j++) {
    716 					row = get_rand(row1 + row_cut, row2 - row_cut);
    717 					col = get_rand(col1 + col_cut, col2 - col_cut);
    718 					if (dungeon[row][col] == TUNNEL) {
    719 						dungeon[row][col] |= HIDDEN;
    720 						break;
    721 					}
    722 				}
    723 			}
    724 		}
    725 	}
    726 }
    727 
    728 put_player(nr)
    729 short nr;		/* try not to put in this room */
    730 {
    731 	short rn = nr, misses;
    732 	short row, col;
    733 
    734 	for (misses = 0; ((misses < 2) && (rn == nr)); misses++) {
    735 		gr_row_col(&row, &col, (FLOOR | TUNNEL | OBJECT | STAIRS));
    736 		rn = get_room_number(row, col);
    737 	}
    738 	rogue.row = row;
    739 	rogue.col = col;
    740 
    741 	if (dungeon[rogue.row][rogue.col] & TUNNEL) {
    742 		cur_room = PASSAGE;
    743 	} else {
    744 		cur_room = rn;
    745 	}
    746 	if (cur_room != PASSAGE) {
    747 		light_up_room(cur_room);
    748 	} else {
    749 		light_passage(rogue.row, rogue.col);
    750 	}
    751 	rn = get_room_number(rogue.row, rogue.col);
    752 	wake_room(rn, 1, rogue.row, rogue.col);
    753 	if (new_level_message) {
    754 		message(new_level_message, 0);
    755 		new_level_message = 0;
    756 	}
    757 	mvaddch(rogue.row, rogue.col, rogue.fchar);
    758 }
    759 
    760 drop_check()
    761 {
    762 	if (wizard) {
    763 		return(1);
    764 	}
    765 	if (dungeon[rogue.row][rogue.col] & STAIRS) {
    766 		if (levitate) {
    767 			message("you're floating in the air!", 0);
    768 			return(0);
    769 		}
    770 		return(1);
    771 	}
    772 	message("I see no way down", 0);
    773 	return(0);
    774 }
    775 
    776 check_up()
    777 {
    778 	if (!wizard) {
    779 		if (!(dungeon[rogue.row][rogue.col] & STAIRS)) {
    780 			message("I see no way up", 0);
    781 			return(0);
    782 		}
    783 		if (!has_amulet()) {
    784 			message("your way is magically blocked", 0);
    785 			return(0);
    786 		}
    787 	}
    788 	new_level_message = "you feel a wrenching sensation in your gut";
    789 	if (cur_level == 1) {
    790 		win();
    791 	} else {
    792 		cur_level -= 2;
    793 		return(1);
    794 	}
    795 	return(0);
    796 }
    797 
    798 add_exp(e, promotion)
    799 int e;
    800 boolean promotion;
    801 {
    802 	char mbuf[40];
    803 	short new_exp;
    804 	short i, hp;
    805 
    806 	rogue.exp_points += e;
    807 
    808 	if (rogue.exp_points >= level_points[rogue.exp-1]) {
    809 		new_exp = get_exp_level(rogue.exp_points);
    810 		if (rogue.exp_points > MAX_EXP) {
    811 			rogue.exp_points = MAX_EXP + 1;
    812 		}
    813 		for (i = rogue.exp+1; i <= new_exp; i++) {
    814 			sprintf(mbuf, "welcome to level %d", i);
    815 			message(mbuf, 0);
    816 			if (promotion) {
    817 				hp = hp_raise();
    818 				rogue.hp_current += hp;
    819 				rogue.hp_max += hp;
    820 			}
    821 			rogue.exp = i;
    822 			print_stats(STAT_HP | STAT_EXP);
    823 		}
    824 	} else {
    825 		print_stats(STAT_EXP);
    826 	}
    827 }
    828 
    829 get_exp_level(e)
    830 long e;
    831 {
    832 	short i;
    833 
    834 	for (i = 0; i < (MAX_EXP_LEVEL - 1); i++) {
    835 		if (level_points[i] > e) {
    836 			break;
    837 		}
    838 	}
    839 	return(i+1);
    840 }
    841 
    842 hp_raise()
    843 {
    844 	int hp;
    845 
    846 	hp = (wizard ? 10 : get_rand(3, 10));
    847 	return(hp);
    848 }
    849 
    850 show_average_hp()
    851 {
    852 	char mbuf[80];
    853 	float real_average;
    854 	float effective_average;
    855 
    856 	if (rogue.exp == 1) {
    857 		real_average = effective_average = 0.00;
    858 	} else {
    859 		real_average = (float)
    860 			((rogue.hp_max - extra_hp - INIT_HP) + less_hp) / (rogue.exp - 1);
    861 		effective_average = (float) (rogue.hp_max - INIT_HP) / (rogue.exp - 1);
    862 
    863 	}
    864 	sprintf(mbuf, "R-Hp: %.2f, E-Hp: %.2f (!: %d, V: %d)", real_average,
    865 		effective_average, extra_hp, less_hp);
    866 	message(mbuf, 0);
    867 }
    868 
    869 mix_random_rooms()
    870 {
    871 	short i, t;
    872 	short x, y;
    873 
    874 	for (i = 0; i < (3 * MAXROOMS); i++) {
    875 		do {
    876 			x = get_rand(0, (MAXROOMS-1));
    877 			y = get_rand(0, (MAXROOMS-1));
    878 		} while (x == y);
    879 		swap(random_rooms[x], random_rooms[y]);
    880 	}
    881 }
    882