xref: /csrg-svn/games/rogue/level.c (revision 36704)
132689Sbostic /*
2*36704Sbostic  * Copyright (c) 1988 The Regents of the University of California.
3*36704Sbostic  * All rights reserved.
4*36704Sbostic  *
5*36704Sbostic  * This code is derived from software contributed to Berkeley by
6*36704Sbostic  * Timothy C. Stoehr.
7*36704Sbostic  *
8*36704Sbostic  * Redistribution and use in source and binary forms are permitted
9*36704Sbostic  * provided that the above copyright notice and this paragraph are
10*36704Sbostic  * duplicated in all such forms and that any documentation,
11*36704Sbostic  * advertising materials, and other materials related to such
12*36704Sbostic  * distribution and use acknowledge that the software was developed
13*36704Sbostic  * by the University of California, Berkeley.  The name of the
14*36704Sbostic  * University may not be used to endorse or promote products derived
15*36704Sbostic  * from this software without specific prior written permission.
16*36704Sbostic  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
17*36704Sbostic  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
18*36704Sbostic  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19*36704Sbostic  */
20*36704Sbostic 
21*36704Sbostic #ifndef lint
22*36704Sbostic static char sccsid[] = "@(#)level.c	5.2 (Berkeley) 02/07/89";
23*36704Sbostic #endif /* not lint */
24*36704Sbostic 
25*36704Sbostic /*
2632689Sbostic  * level.c
2732689Sbostic  *
2832689Sbostic  * This source herein may be modified and/or distributed by anybody who
2932689Sbostic  * so desires, with the following restrictions:
3032689Sbostic  *    1.)  No portion of this notice shall be removed.
3132689Sbostic  *    2.)  Credit shall not be taken for the creation of this source.
3232689Sbostic  *    3.)  This code is not to be traded, sold, or used for personal
3332689Sbostic  *         gain or profit.
3432689Sbostic  *
3532689Sbostic  */
3632689Sbostic 
3732689Sbostic #include "rogue.h"
3832689Sbostic 
3932689Sbostic #define swap(x,y) {t = x; x = y; y = t;}
4032689Sbostic 
4132689Sbostic short cur_level = 0;
4232689Sbostic short max_level = 1;
4332689Sbostic short cur_room;
4432689Sbostic char *new_level_message = 0;
4532689Sbostic short party_room = NO_ROOM;
4632689Sbostic short r_de;
4732689Sbostic 
4832689Sbostic long level_points[MAX_EXP_LEVEL] = {
4932689Sbostic 		  10L,
5032689Sbostic 		  20L,
5132689Sbostic 		  40L,
5232689Sbostic 		  80L,
5332689Sbostic 		 160L,
5432689Sbostic 		 320L,
5532689Sbostic 		 640L,
5632689Sbostic 		1300L,
5732689Sbostic 		2600L,
5832689Sbostic 		5200L,
5932689Sbostic 	   10000L,
6032689Sbostic 	   20000L,
6132689Sbostic 	   40000L,
6232689Sbostic 	   80000L,
6332689Sbostic 	  160000L,
6432689Sbostic 	  320000L,
6532689Sbostic 	 1000000L,
6632689Sbostic 	 3333333L,
6732689Sbostic 	 6666666L,
6832689Sbostic 	  MAX_EXP,
6932689Sbostic 	99900000L
7032689Sbostic };
7132689Sbostic 
7232689Sbostic short random_rooms[MAXROOMS] = {3, 7, 5, 2, 0, 6, 1, 4, 8};
7332689Sbostic 
7432689Sbostic extern boolean being_held, wizard, detect_monster;
7532689Sbostic extern boolean see_invisible;
7632689Sbostic extern short bear_trap, levitate, extra_hp, less_hp, cur_room;
7732689Sbostic 
7832689Sbostic make_level()
7932689Sbostic {
8032689Sbostic 	short i, j;
8132689Sbostic 	short must_1, must_2, must_3;
8232689Sbostic 	boolean big_room;
8332689Sbostic 
8432689Sbostic 	if (cur_level < LAST_DUNGEON) {
8532689Sbostic 		cur_level++;
8632689Sbostic 	}
8732689Sbostic 	if (cur_level > max_level) {
8832689Sbostic 		max_level = cur_level;
8932689Sbostic 	}
9032689Sbostic 	must_1 = get_rand(0, 5);
9132689Sbostic 
9232689Sbostic 	switch(must_1) {
9332689Sbostic 	case 0:
9432689Sbostic 		must_1 = 0;
9532689Sbostic 		must_2 = 1;
9632689Sbostic 		must_3 = 2;
9732689Sbostic 		break;
9832689Sbostic 	case 1:
9932689Sbostic 		must_1 = 3;
10032689Sbostic 		must_2 = 4;
10132689Sbostic 		must_3 = 5;
10232689Sbostic 		break;
10332689Sbostic 	case 2:
10432689Sbostic 		must_1 = 6;
10532689Sbostic 		must_2 = 7;
10632689Sbostic 		must_3 = 8;
10732689Sbostic 		break;
10832689Sbostic 	case 3:
10932689Sbostic 		must_1 = 0;
11032689Sbostic 		must_2 = 3;
11132689Sbostic 		must_3 = 6;
11232689Sbostic 		break;
11332689Sbostic 	case 4:
11432689Sbostic 		must_1 = 1;
11532689Sbostic 		must_2 = 4;
11632689Sbostic 		must_3 = 7;
11732689Sbostic 		break;
11832689Sbostic 	case 5:
11932689Sbostic 		must_1 = 2;
12032689Sbostic 		must_2 = 5;
12132689Sbostic 		must_3 = 8;
12232689Sbostic 		break;
12332689Sbostic 	}
12432689Sbostic 	if (rand_percent(8)) {
12532689Sbostic 		party_room = 0;
12632689Sbostic 	}
12732689Sbostic 	big_room = ((party_room != NO_ROOM) && rand_percent(1));
12832689Sbostic 	if (big_room) {
12932689Sbostic 		make_room(BIG_ROOM, 0, 0, 0);
13032689Sbostic 	} else {
13132689Sbostic 		for (i = 0; i < MAXROOMS; i++) {
13232689Sbostic 			make_room(i, must_1, must_2, must_3);
13332689Sbostic 		}
13432689Sbostic 	}
13532689Sbostic 	if (!big_room) {
13632689Sbostic 		add_mazes();
13732689Sbostic 
13832689Sbostic 		mix_random_rooms();
13932689Sbostic 
14032689Sbostic 		for (j = 0; j < MAXROOMS; j++) {
14132689Sbostic 
14232689Sbostic 			i = random_rooms[j];
14332689Sbostic 
14432689Sbostic 			if (i < (MAXROOMS-1)) {
14532689Sbostic 				(void) connect_rooms(i, i+1);
14632689Sbostic 			}
14732689Sbostic 			if (i < (MAXROOMS-3)) {
14832689Sbostic 				(void) connect_rooms(i, i+3);
14932689Sbostic 			}
15032689Sbostic 			if (i < (MAXROOMS-2)) {
15132689Sbostic 				if (rooms[i+1].is_room & R_NOTHING) {
15232689Sbostic 					if (connect_rooms(i, i+2)) {
15332689Sbostic 						rooms[i+1].is_room = R_CROSS;
15432689Sbostic 					}
15532689Sbostic 				}
15632689Sbostic 			}
15732689Sbostic 			if (i < (MAXROOMS-6)) {
15832689Sbostic 				if (rooms[i+3].is_room & R_NOTHING) {
15932689Sbostic 					if (connect_rooms(i, i+6)) {
16032689Sbostic 						rooms[i+3].is_room = R_CROSS;
16132689Sbostic 					}
16232689Sbostic 				}
16332689Sbostic 			}
16432689Sbostic 			if (is_all_connected()) {
16532689Sbostic 				break;
16632689Sbostic 			}
16732689Sbostic 		}
16832689Sbostic 		fill_out_level();
16932689Sbostic 	}
17032689Sbostic 	if (!has_amulet() && (cur_level >= AMULET_LEVEL)) {
17132689Sbostic 		put_amulet();
17232689Sbostic 	}
17332689Sbostic }
17432689Sbostic 
17532689Sbostic make_room(rn, r1, r2, r3)
17632689Sbostic short rn, r1, r2, r3;
17732689Sbostic {
17832689Sbostic 	short left_col, right_col, top_row, bottom_row;
17932689Sbostic 	short width, height;
18032689Sbostic 	short row_offset, col_offset;
18132689Sbostic 	short i, j, ch;
18232689Sbostic 
18332689Sbostic 	switch(rn) {
18432689Sbostic 	case 0:
18532689Sbostic 		left_col = 0;
18632689Sbostic 		right_col = COL1-1;
18732689Sbostic 		top_row = MIN_ROW;
18832689Sbostic 		bottom_row = ROW1-1;
18932689Sbostic 		break;
19032689Sbostic 	case 1:
19132689Sbostic 		left_col = COL1+1;
19232689Sbostic 		right_col = COL2-1;
19332689Sbostic 		top_row = MIN_ROW;
19432689Sbostic 		bottom_row = ROW1-1;
19532689Sbostic 		break;
19632689Sbostic 	case 2:
19732689Sbostic 		left_col = COL2+1;
19832689Sbostic 		right_col = DCOLS-1;
19932689Sbostic 		top_row = MIN_ROW;
20032689Sbostic 		bottom_row = ROW1-1;
20132689Sbostic 		break;
20232689Sbostic 	case 3:
20332689Sbostic 		left_col = 0;
20432689Sbostic 		right_col = COL1-1;
20532689Sbostic 		top_row = ROW1+1;
20632689Sbostic 		bottom_row = ROW2-1;
20732689Sbostic 		break;
20832689Sbostic 	case 4:
20932689Sbostic 		left_col = COL1+1;
21032689Sbostic 		right_col = COL2-1;
21132689Sbostic 		top_row = ROW1+1;
21232689Sbostic 		bottom_row = ROW2-1;
21332689Sbostic 		break;
21432689Sbostic 	case 5:
21532689Sbostic 		left_col = COL2+1;
21632689Sbostic 		right_col = DCOLS-1;
21732689Sbostic 		top_row = ROW1+1;
21832689Sbostic 		bottom_row = ROW2-1;
21932689Sbostic 		break;
22032689Sbostic 	case 6:
22132689Sbostic 		left_col = 0;
22232689Sbostic 		right_col = COL1-1;
22332689Sbostic 		top_row = ROW2+1;
22432689Sbostic 		bottom_row = DROWS - 2;
22532689Sbostic 		break;
22632689Sbostic 	case 7:
22732689Sbostic 		left_col = COL1+1;
22832689Sbostic 		right_col = COL2-1;
22932689Sbostic 		top_row = ROW2+1;
23032689Sbostic 		bottom_row = DROWS - 2;
23132689Sbostic 		break;
23232689Sbostic 	case 8:
23332689Sbostic 		left_col = COL2+1;
23432689Sbostic 		right_col = DCOLS-1;
23532689Sbostic 		top_row = ROW2+1;
23632689Sbostic 		bottom_row = DROWS - 2;
23732689Sbostic 		break;
23832689Sbostic 	case BIG_ROOM:
23932689Sbostic 		top_row = get_rand(MIN_ROW, MIN_ROW+5);
24032689Sbostic 		bottom_row = get_rand(DROWS-7, DROWS-2);
24132689Sbostic 		left_col = get_rand(0, 10);;
24232689Sbostic 		right_col = get_rand(DCOLS-11, DCOLS-1);
24332689Sbostic 		rn = 0;
24432689Sbostic 		goto B;
24532689Sbostic 	}
24632689Sbostic 	height = get_rand(4, (bottom_row - top_row + 1));
24732689Sbostic 	width = get_rand(7, (right_col - left_col - 2));
24832689Sbostic 
24932689Sbostic 	row_offset = get_rand(0, ((bottom_row - top_row) - height + 1));
25032689Sbostic 	col_offset = get_rand(0, ((right_col - left_col) - width + 1));
25132689Sbostic 
25232689Sbostic 	top_row += row_offset;
25332689Sbostic 	bottom_row = top_row + height - 1;
25432689Sbostic 
25532689Sbostic 	left_col += col_offset;
25632689Sbostic 	right_col = left_col + width - 1;
25732689Sbostic 
25832689Sbostic 	if ((rn != r1) && (rn != r2) && (rn != r3) && rand_percent(40)) {
25932689Sbostic 		goto END;
26032689Sbostic 	}
26132689Sbostic B:
26232689Sbostic 	rooms[rn].is_room = R_ROOM;
26332689Sbostic 
26432689Sbostic 	for (i = top_row; i <= bottom_row; i++) {
26532689Sbostic 		for (j = left_col; j <= right_col; j++) {
26632689Sbostic 			if ((i == top_row) || (i == bottom_row)) {
26732689Sbostic 				ch = HORWALL;
26832689Sbostic 			} else if (	((i != top_row) && (i != bottom_row)) &&
26932689Sbostic 						((j == left_col) || (j == right_col))) {
27032689Sbostic 				ch = VERTWALL;
27132689Sbostic 			} else {
27232689Sbostic 				ch = FLOOR;
27332689Sbostic 			}
27432689Sbostic 			dungeon[i][j] = ch;
27532689Sbostic 		}
27632689Sbostic 	}
27732689Sbostic END:
27832689Sbostic 	rooms[rn].top_row = top_row;
27932689Sbostic 	rooms[rn].bottom_row = bottom_row;
28032689Sbostic 	rooms[rn].left_col = left_col;
28132689Sbostic 	rooms[rn].right_col = right_col;
28232689Sbostic }
28332689Sbostic 
28432689Sbostic connect_rooms(room1, room2)
28532689Sbostic short room1, room2;
28632689Sbostic {
28732689Sbostic 	short row1, col1, row2, col2, dir;
28832689Sbostic 
28932689Sbostic 	if ((!(rooms[room1].is_room & (R_ROOM | R_MAZE))) ||
29032689Sbostic 		(!(rooms[room2].is_room & (R_ROOM | R_MAZE)))) {
29132689Sbostic 		return(0);
29232689Sbostic 	}
29332689Sbostic 	if (same_row(room1, room2) &&
29432689Sbostic 		(rooms[room1].left_col > rooms[room2].right_col)) {
29532689Sbostic 		put_door(&rooms[room1], LEFT, &row1, &col1);
29632689Sbostic 		put_door(&rooms[room2], RIGHT, &row2, &col2);
29732689Sbostic 		dir = LEFT;
29832689Sbostic 	} else if (same_row(room1, room2) &&
29932689Sbostic 		(rooms[room2].left_col > rooms[room1].right_col)) {
30032689Sbostic 		put_door(&rooms[room1], RIGHT, &row1, &col1);
30132689Sbostic 		put_door(&rooms[room2], LEFT, &row2, &col2);
30232689Sbostic 		dir = RIGHT;
30332689Sbostic 	} else if (same_col(room1, room2) &&
30432689Sbostic 		(rooms[room1].top_row > rooms[room2].bottom_row)) {
30532689Sbostic 		put_door(&rooms[room1], UPWARD, &row1, &col1);
30632689Sbostic 		put_door(&rooms[room2], DOWN, &row2, &col2);
30732689Sbostic 		dir = UPWARD;
30832689Sbostic 	} else if (same_col(room1, room2) &&
30932689Sbostic 		(rooms[room2].top_row > rooms[room1].bottom_row)) {
31032689Sbostic 		put_door(&rooms[room1], DOWN, &row1, &col1);
31132689Sbostic 		put_door(&rooms[room2], UPWARD, &row2, &col2);
31232689Sbostic 		dir = DOWN;
31332689Sbostic 	} else {
31432689Sbostic 		return(0);
31532689Sbostic 	}
31632689Sbostic 
31732689Sbostic 	do {
31832689Sbostic 		draw_simple_passage(row1, col1, row2, col2, dir);
31932689Sbostic 	} while (rand_percent(4));
32032689Sbostic 
32132689Sbostic 	rooms[room1].doors[dir/2].oth_room = room2;
32232689Sbostic 	rooms[room1].doors[dir/2].oth_row = row2;
32332689Sbostic 	rooms[room1].doors[dir/2].oth_col = col2;
32432689Sbostic 
32532689Sbostic 	rooms[room2].doors[(((dir+4)%DIRS)/2)].oth_room = room1;
32632689Sbostic 	rooms[room2].doors[(((dir+4)%DIRS)/2)].oth_row = row1;
32732689Sbostic 	rooms[room2].doors[(((dir+4)%DIRS)/2)].oth_col = col1;
32832689Sbostic 	return(1);
32932689Sbostic }
33032689Sbostic 
33132689Sbostic clear_level()
33232689Sbostic {
33332689Sbostic 	short i, j;
33432689Sbostic 
33532689Sbostic 	for (i = 0; i < MAXROOMS; i++) {
33632689Sbostic 		rooms[i].is_room = R_NOTHING;
33732689Sbostic 		for (j = 0; j < 4; j++) {
33832689Sbostic 			rooms[i].doors[j].oth_room = NO_ROOM;
33932689Sbostic 		}
34032689Sbostic 	}
34132689Sbostic 
34232689Sbostic 	for (i = 0; i < MAX_TRAPS; i++) {
34332689Sbostic 		traps[i].trap_type = NO_TRAP;
34432689Sbostic 	}
34532689Sbostic 	for (i = 0; i < DROWS; i++) {
34632689Sbostic 		for (j = 0; j < DCOLS; j++) {
34732689Sbostic 			dungeon[i][j] = NOTHING;
34832689Sbostic 		}
34932689Sbostic 	}
35032689Sbostic 	detect_monster = see_invisible = 0;
35132689Sbostic 	being_held = bear_trap = 0;
35232689Sbostic 	party_room = NO_ROOM;
35332689Sbostic 	rogue.row = rogue.col = -1;
35432689Sbostic 	clear();
35532689Sbostic }
35632689Sbostic 
35732689Sbostic put_door(rm, dir, row, col)
35832689Sbostic room *rm;
35932689Sbostic short dir;
36032689Sbostic short *row, *col;
36132689Sbostic {
36232689Sbostic 	short wall_width;
36332689Sbostic 
36432689Sbostic 	wall_width = (rm->is_room & R_MAZE) ? 0 : 1;
36532689Sbostic 
36632689Sbostic 	switch(dir) {
36732689Sbostic 	case UPWARD:
36832689Sbostic 	case DOWN:
36932689Sbostic 		*row = ((dir == UPWARD) ? rm->top_row : rm->bottom_row);
37032689Sbostic 		do {
37132689Sbostic 			*col = get_rand(rm->left_col+wall_width,
37232689Sbostic 				rm->right_col-wall_width);
37332689Sbostic 		} while (!(dungeon[*row][*col] & (HORWALL | TUNNEL)));
37432689Sbostic 		break;
37532689Sbostic 	case RIGHT:
37632689Sbostic 	case LEFT:
37732689Sbostic 		*col = (dir == LEFT) ? rm->left_col : rm->right_col;
37832689Sbostic 		do {
37932689Sbostic 			*row = get_rand(rm->top_row+wall_width,
38032689Sbostic 				rm->bottom_row-wall_width);
38132689Sbostic 		} while (!(dungeon[*row][*col] & (VERTWALL | TUNNEL)));
38232689Sbostic 		break;
38332689Sbostic 	}
38432689Sbostic 	if (rm->is_room & R_ROOM) {
38532689Sbostic 		dungeon[*row][*col] = DOOR;
38632689Sbostic 	}
38732689Sbostic 	if ((cur_level > 2) && rand_percent(HIDE_PERCENT)) {
38832689Sbostic 		dungeon[*row][*col] |= HIDDEN;
38932689Sbostic 	}
39032689Sbostic 	rm->doors[dir/2].door_row = *row;
39132689Sbostic 	rm->doors[dir/2].door_col = *col;
39232689Sbostic }
39332689Sbostic 
39432689Sbostic draw_simple_passage(row1, col1, row2, col2, dir)
39532689Sbostic short row1, col1, row2, col2, dir;
39632689Sbostic {
39732689Sbostic 	short i, middle, t;
39832689Sbostic 
39932689Sbostic 	if ((dir == LEFT) || (dir == RIGHT)) {
40032689Sbostic 		if (col1 > col2) {
40132689Sbostic 			swap(row1, row2);
40232689Sbostic 			swap(col1, col2);
40332689Sbostic 		}
40432689Sbostic 		middle = get_rand(col1+1, col2-1);
40532689Sbostic 		for (i = col1+1; i != middle; i++) {
40632689Sbostic 			dungeon[row1][i] = TUNNEL;
40732689Sbostic 		}
40832689Sbostic 		for (i = row1; i != row2; i += (row1 > row2) ? -1 : 1) {
40932689Sbostic 			dungeon[i][middle] = TUNNEL;
41032689Sbostic 		}
41132689Sbostic 		for (i = middle; i != col2; i++) {
41232689Sbostic 			dungeon[row2][i] = TUNNEL;
41332689Sbostic 		}
41432689Sbostic 	} else {
41532689Sbostic 		if (row1 > row2) {
41632689Sbostic 			swap(row1, row2);
41732689Sbostic 			swap(col1, col2);
41832689Sbostic 		}
41932689Sbostic 		middle = get_rand(row1+1, row2-1);
42032689Sbostic 		for (i = row1+1; i != middle; i++) {
42132689Sbostic 			dungeon[i][col1] = TUNNEL;
42232689Sbostic 		}
42332689Sbostic 		for (i = col1; i != col2; i += (col1 > col2) ? -1 : 1) {
42432689Sbostic 			dungeon[middle][i] = TUNNEL;
42532689Sbostic 		}
42632689Sbostic 		for (i = middle; i != row2; i++) {
42732689Sbostic 			dungeon[i][col2] = TUNNEL;
42832689Sbostic 		}
42932689Sbostic 	}
43032689Sbostic 	if (rand_percent(HIDE_PERCENT)) {
43132689Sbostic 		hide_boxed_passage(row1, col1, row2, col2, 1);
43232689Sbostic 	}
43332689Sbostic }
43432689Sbostic 
43532689Sbostic same_row(room1, room2)
43632689Sbostic {
43732689Sbostic 	return((room1 / 3) == (room2 / 3));
43832689Sbostic }
43932689Sbostic 
44032689Sbostic same_col(room1, room2)
44132689Sbostic {
44232689Sbostic 	return((room1 % 3) == (room2 % 3));
44332689Sbostic }
44432689Sbostic 
44532689Sbostic add_mazes()
44632689Sbostic {
44732689Sbostic 	short i, j;
44832689Sbostic 	short start;
44932689Sbostic 	short maze_percent;
45032689Sbostic 
45132689Sbostic 	if (cur_level > 1) {
45232689Sbostic 		start = get_rand(0, (MAXROOMS-1));
45332689Sbostic 		maze_percent = (cur_level * 5) / 4;
45432689Sbostic 
45532689Sbostic 		if (cur_level > 15) {
45632689Sbostic 			maze_percent += cur_level;
45732689Sbostic 		}
45832689Sbostic 		for (i = 0; i < MAXROOMS; i++) {
45932689Sbostic 			j = ((start + i) % MAXROOMS);
46032689Sbostic 			if (rooms[j].is_room & R_NOTHING) {
46132689Sbostic 				if (rand_percent(maze_percent)) {
46232689Sbostic 				rooms[j].is_room = R_MAZE;
46332689Sbostic 				make_maze(get_rand(rooms[j].top_row+1, rooms[j].bottom_row-1),
46432689Sbostic 					get_rand(rooms[j].left_col+1, rooms[j].right_col-1),
46532689Sbostic 					rooms[j].top_row, rooms[j].bottom_row,
46632689Sbostic 					rooms[j].left_col, rooms[j].right_col);
46732689Sbostic 				hide_boxed_passage(rooms[j].top_row, rooms[j].left_col,
46832689Sbostic 					rooms[j].bottom_row, rooms[j].right_col,
46932689Sbostic 					get_rand(0, 2));
47032689Sbostic 				}
47132689Sbostic 			}
47232689Sbostic 		}
47332689Sbostic 	}
47432689Sbostic }
47532689Sbostic 
47632689Sbostic fill_out_level()
47732689Sbostic {
47832689Sbostic 	short i, rn;
47932689Sbostic 
48032689Sbostic 	mix_random_rooms();
48132689Sbostic 
48232689Sbostic 	r_de = NO_ROOM;
48332689Sbostic 
48432689Sbostic 	for (i = 0; i < MAXROOMS; i++) {
48532689Sbostic 		rn = random_rooms[i];
48632689Sbostic 		if ((rooms[rn].is_room & R_NOTHING) ||
48732689Sbostic 			((rooms[rn].is_room & R_CROSS) && coin_toss())) {
48832689Sbostic 			fill_it(rn, 1);
48932689Sbostic 		}
49032689Sbostic 	}
49132689Sbostic 	if (r_de != NO_ROOM) {
49232689Sbostic 		fill_it(r_de, 0);
49332689Sbostic 	}
49432689Sbostic }
49532689Sbostic 
49632689Sbostic fill_it(rn, do_rec_de)
49732689Sbostic int rn;
49832689Sbostic boolean do_rec_de;
49932689Sbostic {
50032689Sbostic 	short i, tunnel_dir, door_dir, drow, dcol;
50132689Sbostic 	short target_room, rooms_found = 0;
50232689Sbostic 	short srow, scol, t;
50332689Sbostic 	static short offsets[4] = {-1, 1, 3, -3};
50432689Sbostic 	boolean did_this = 0;
50532689Sbostic 
50632689Sbostic 	for (i = 0; i < 10; i++) {
50732689Sbostic 		srow = get_rand(0, 3);
50832689Sbostic 		scol = get_rand(0, 3);
50932689Sbostic 		t = offsets[srow];
51032689Sbostic 		offsets[srow] = offsets[scol];
51132689Sbostic 		offsets[scol] = t;
51232689Sbostic 	}
51332689Sbostic 	for (i = 0; i < 4; i++) {
51432689Sbostic 
51532689Sbostic 		target_room = rn + offsets[i];
51632689Sbostic 
51732689Sbostic 		if (((target_room < 0) || (target_room >= MAXROOMS)) ||
51832689Sbostic 			(!(same_row(rn,target_room) || same_col(rn,target_room))) ||
51932689Sbostic 			(!(rooms[target_room].is_room & (R_ROOM | R_MAZE)))) {
52032689Sbostic 			continue;
52132689Sbostic 		}
52232689Sbostic 		if (same_row(rn, target_room)) {
52332689Sbostic 			tunnel_dir = (rooms[rn].left_col < rooms[target_room].left_col) ?
52432689Sbostic 				RIGHT : LEFT;
52532689Sbostic 		} else {
52632689Sbostic 			tunnel_dir = (rooms[rn].top_row < rooms[target_room].top_row) ?
52732689Sbostic 				DOWN : UPWARD;
52832689Sbostic 		}
52932689Sbostic 		door_dir = ((tunnel_dir + 4) % DIRS);
53032689Sbostic 		if (rooms[target_room].doors[door_dir/2].oth_room != NO_ROOM) {
53132689Sbostic 			continue;
53232689Sbostic 		}
53332689Sbostic 		if (((!do_rec_de) || did_this) ||
53432689Sbostic 			(!mask_room(rn, &srow, &scol, TUNNEL))) {
53532689Sbostic 			srow = (rooms[rn].top_row + rooms[rn].bottom_row) / 2;
53632689Sbostic 			scol = (rooms[rn].left_col + rooms[rn].right_col) / 2;
53732689Sbostic 		}
53832689Sbostic 		put_door(&rooms[target_room], door_dir, &drow, &dcol);
53932689Sbostic 		rooms_found++;
54032689Sbostic 		draw_simple_passage(srow, scol, drow, dcol, tunnel_dir);
54132689Sbostic 		rooms[rn].is_room = R_DEADEND;
54232689Sbostic 		dungeon[srow][scol] = TUNNEL;
54332689Sbostic 
54432689Sbostic 		if ((i < 3) && (!did_this)) {
54532689Sbostic 			did_this = 1;
54632689Sbostic 			if (coin_toss()) {
54732689Sbostic 				continue;
54832689Sbostic 			}
54932689Sbostic 		}
55032689Sbostic 		if ((rooms_found < 2) && do_rec_de) {
55132689Sbostic 			recursive_deadend(rn, offsets, srow, scol);
55232689Sbostic 		}
55332689Sbostic 		break;
55432689Sbostic 	}
55532689Sbostic }
55632689Sbostic 
55732689Sbostic recursive_deadend(rn, offsets, srow, scol)
55832689Sbostic short rn;
55932689Sbostic short *offsets;
56032689Sbostic short srow, scol;
56132689Sbostic {
56232689Sbostic 	short i, de;
56332689Sbostic 	short drow, dcol, tunnel_dir;
56432689Sbostic 
56532689Sbostic 	rooms[rn].is_room = R_DEADEND;
56632689Sbostic 	dungeon[srow][scol] = TUNNEL;
56732689Sbostic 
56832689Sbostic 	for (i = 0; i < 4; i++) {
56932689Sbostic 		de = rn + offsets[i];
57032689Sbostic 		if (((de < 0) || (de >= MAXROOMS)) ||
57132689Sbostic 			(!(same_row(rn, de) || same_col(rn, de)))) {
57232689Sbostic 			continue;
57332689Sbostic 		}
57432689Sbostic 		if (!(rooms[de].is_room & R_NOTHING)) {
57532689Sbostic 			continue;
57632689Sbostic 		}
57732689Sbostic 		drow = (rooms[de].top_row + rooms[de].bottom_row) / 2;
57832689Sbostic 		dcol = (rooms[de].left_col + rooms[de].right_col) / 2;
57932689Sbostic 		if (same_row(rn, de)) {
58032689Sbostic 			tunnel_dir = (rooms[rn].left_col < rooms[de].left_col) ?
58132689Sbostic 				RIGHT : LEFT;
58232689Sbostic 		} else {
58332689Sbostic 			tunnel_dir = (rooms[rn].top_row < rooms[de].top_row) ?
58432689Sbostic 				DOWN : UPWARD;
58532689Sbostic 		}
58632689Sbostic 		draw_simple_passage(srow, scol, drow, dcol, tunnel_dir);
58732689Sbostic 		r_de = de;
58832689Sbostic 		recursive_deadend(de, offsets, drow, dcol);
58932689Sbostic 	}
59032689Sbostic }
59132689Sbostic 
59232689Sbostic boolean
59332689Sbostic mask_room(rn, row, col, mask)
59432689Sbostic short rn;
59532689Sbostic short *row, *col;
59632689Sbostic unsigned short mask;
59732689Sbostic {
59832689Sbostic 	short i, j;
59932689Sbostic 
60032689Sbostic 	for (i = rooms[rn].top_row; i <= rooms[rn].bottom_row; i++) {
60132689Sbostic 		for (j = rooms[rn].left_col; j <= rooms[rn].right_col; j++) {
60232689Sbostic 			if (dungeon[i][j] & mask) {
60332689Sbostic 				*row = i;
60432689Sbostic 				*col = j;
60532689Sbostic 				return(1);
60632689Sbostic 			}
60732689Sbostic 		}
60832689Sbostic 	}
60932689Sbostic 	return(0);
61032689Sbostic }
61132689Sbostic 
61232689Sbostic make_maze(r, c, tr, br, lc, rc)
61332689Sbostic short r, c, tr, br, lc, rc;
61432689Sbostic {
61532689Sbostic 	char dirs[4];
61632689Sbostic 	short i, t;
61732689Sbostic 
61832689Sbostic 	dirs[0] = UPWARD;
61932689Sbostic 	dirs[1] = DOWN;
62032689Sbostic 	dirs[2] = LEFT;
62132689Sbostic 	dirs[3] = RIGHT;
62232689Sbostic 
62332689Sbostic 	dungeon[r][c] = TUNNEL;
62432689Sbostic 
62532689Sbostic 	if (rand_percent(20)) {
62632689Sbostic 		for (i = 0; i < 10; i++) {
62732689Sbostic 			short t1, t2;
62832689Sbostic 
62932689Sbostic 			t1 = get_rand(0, 3);
63032689Sbostic 			t2 = get_rand(0, 3);
63132689Sbostic 
63232689Sbostic 			swap(dirs[t1], dirs[t2]);
63332689Sbostic 		}
63432689Sbostic 	}
63532689Sbostic 	for (i = 0; i < 4; i++) {
63632689Sbostic 		switch(dirs[i]) {
63732689Sbostic 		case UPWARD:
63832689Sbostic 			if (((r-1) >= tr) &&
63932689Sbostic 				(dungeon[r-1][c] != TUNNEL) &&
64032689Sbostic 				(dungeon[r-1][c-1] != TUNNEL) &&
64132689Sbostic 				(dungeon[r-1][c+1] != TUNNEL) &&
64232689Sbostic 				(dungeon[r-2][c] != TUNNEL)) {
64332689Sbostic 				make_maze((r-1), c, tr, br, lc, rc);
64432689Sbostic 			}
64532689Sbostic 			break;
64632689Sbostic 		case DOWN:
64732689Sbostic 			if (((r+1) <= br) &&
64832689Sbostic 				(dungeon[r+1][c] != TUNNEL) &&
64932689Sbostic 				(dungeon[r+1][c-1] != TUNNEL) &&
65032689Sbostic 				(dungeon[r+1][c+1] != TUNNEL) &&
65132689Sbostic 				(dungeon[r+2][c] != TUNNEL)) {
65232689Sbostic 				make_maze((r+1), c, tr, br, lc, rc);
65332689Sbostic 			}
65432689Sbostic 			break;
65532689Sbostic 		case LEFT:
65632689Sbostic 			if (((c-1) >= lc) &&
65732689Sbostic 				(dungeon[r][c-1] != TUNNEL) &&
65832689Sbostic 				(dungeon[r-1][c-1] != TUNNEL) &&
65932689Sbostic 				(dungeon[r+1][c-1] != TUNNEL) &&
66032689Sbostic 				(dungeon[r][c-2] != TUNNEL)) {
66132689Sbostic 				make_maze(r, (c-1), tr, br, lc, rc);
66232689Sbostic 			}
66332689Sbostic 			break;
66432689Sbostic 		case RIGHT:
66532689Sbostic 			if (((c+1) <= rc) &&
66632689Sbostic 				(dungeon[r][c+1] != TUNNEL) &&
66732689Sbostic 				(dungeon[r-1][c+1] != TUNNEL) &&
66832689Sbostic 				(dungeon[r+1][c+1] != TUNNEL) &&
66932689Sbostic 				(dungeon[r][c+2] != TUNNEL)) {
67032689Sbostic 				make_maze(r, (c+1), tr, br, lc, rc);
67132689Sbostic 			}
67232689Sbostic 			break;
67332689Sbostic 		}
67432689Sbostic 	}
67532689Sbostic }
67632689Sbostic 
67732689Sbostic hide_boxed_passage(row1, col1, row2, col2, n)
67832689Sbostic short row1, col1, row2, col2, n;
67932689Sbostic {
68032689Sbostic 	short i, j, t;
68132689Sbostic 	short row, col, row_cut, col_cut;
68232689Sbostic 	short h, w;
68332689Sbostic 
68432689Sbostic 	if (cur_level > 2) {
68532689Sbostic 		if (row1 > row2) {
68632689Sbostic 			swap(row1, row2);
68732689Sbostic 		}
68832689Sbostic 		if (col1 > col2) {
68932689Sbostic 			swap(col1, col2);
69032689Sbostic 		}
69132689Sbostic 		h = row2 - row1;
69232689Sbostic 		w = col2 - col1;
69332689Sbostic 
69432689Sbostic 		if ((w >= 5) || (h >= 5)) {
69532689Sbostic 			row_cut = ((h >= 2) ? 1 : 0);
69632689Sbostic 			col_cut = ((w >= 2) ? 1 : 0);
69732689Sbostic 
69832689Sbostic 			for (i = 0; i < n; i++) {
69932689Sbostic 				for (j = 0; j < 10; j++) {
70032689Sbostic 					row = get_rand(row1 + row_cut, row2 - row_cut);
70132689Sbostic 					col = get_rand(col1 + col_cut, col2 - col_cut);
70232689Sbostic 					if (dungeon[row][col] == TUNNEL) {
70332689Sbostic 						dungeon[row][col] |= HIDDEN;
70432689Sbostic 						break;
70532689Sbostic 					}
70632689Sbostic 				}
70732689Sbostic 			}
70832689Sbostic 		}
70932689Sbostic 	}
71032689Sbostic }
71132689Sbostic 
71232689Sbostic put_player(nr)
71332689Sbostic short nr;		/* try not to put in this room */
71432689Sbostic {
71532689Sbostic 	short rn = nr, misses;
71632689Sbostic 	short row, col;
71732689Sbostic 
71832689Sbostic 	for (misses = 0; ((misses < 2) && (rn == nr)); misses++) {
71932689Sbostic 		gr_row_col(&row, &col, (FLOOR | TUNNEL | OBJECT | STAIRS));
72032689Sbostic 		rn = get_room_number(row, col);
72132689Sbostic 	}
72232689Sbostic 	rogue.row = row;
72332689Sbostic 	rogue.col = col;
72432689Sbostic 
72532689Sbostic 	if (dungeon[rogue.row][rogue.col] & TUNNEL) {
72632689Sbostic 		cur_room = PASSAGE;
72732689Sbostic 	} else {
72832689Sbostic 		cur_room = rn;
72932689Sbostic 	}
73032689Sbostic 	if (cur_room != PASSAGE) {
73132689Sbostic 		light_up_room(cur_room);
73232689Sbostic 	} else {
73332689Sbostic 		light_passage(rogue.row, rogue.col);
73432689Sbostic 	}
73532689Sbostic 	rn = get_room_number(rogue.row, rogue.col);
73632689Sbostic 	wake_room(rn, 1, rogue.row, rogue.col);
73732689Sbostic 	if (new_level_message) {
73832689Sbostic 		message(new_level_message, 0);
73932689Sbostic 		new_level_message = 0;
74032689Sbostic 	}
74132689Sbostic 	mvaddch(rogue.row, rogue.col, rogue.fchar);
74232689Sbostic }
74332689Sbostic 
74432689Sbostic drop_check()
74532689Sbostic {
74632689Sbostic 	if (wizard) {
74732689Sbostic 		return(1);
74832689Sbostic 	}
74932689Sbostic 	if (dungeon[rogue.row][rogue.col] & STAIRS) {
75032689Sbostic 		if (levitate) {
75132689Sbostic 			message("you're floating in the air!", 0);
75232689Sbostic 			return(0);
75332689Sbostic 		}
75432689Sbostic 		return(1);
75532689Sbostic 	}
75632689Sbostic 	message("I see no way down", 0);
75732689Sbostic 	return(0);
75832689Sbostic }
75932689Sbostic 
76032689Sbostic check_up()
76132689Sbostic {
76232689Sbostic 	if (!wizard) {
76332689Sbostic 		if (!(dungeon[rogue.row][rogue.col] & STAIRS)) {
76432689Sbostic 			message("I see no way up", 0);
76532689Sbostic 			return(0);
76632689Sbostic 		}
76732689Sbostic 		if (!has_amulet()) {
76832689Sbostic 			message("your way is magically blocked", 0);
76932689Sbostic 			return(0);
77032689Sbostic 		}
77132689Sbostic 	}
77232689Sbostic 	new_level_message = "you feel a wrenching sensation in your gut";
77332689Sbostic 	if (cur_level == 1) {
77432689Sbostic 		win();
77532689Sbostic 	} else {
77632689Sbostic 		cur_level -= 2;
77732689Sbostic 		return(1);
77832689Sbostic 	}
77932689Sbostic 	return(0);
78032689Sbostic }
78132689Sbostic 
78232689Sbostic add_exp(e, promotion)
78332689Sbostic int e;
78432689Sbostic boolean promotion;
78532689Sbostic {
78632689Sbostic 	char mbuf[40];
78732689Sbostic 	short new_exp;
78832689Sbostic 	short i, hp;
78932689Sbostic 
79032689Sbostic 	rogue.exp_points += e;
79132689Sbostic 
79232689Sbostic 	if (rogue.exp_points >= level_points[rogue.exp-1]) {
79332689Sbostic 		new_exp = get_exp_level(rogue.exp_points);
79432689Sbostic 		if (rogue.exp_points > MAX_EXP) {
79532689Sbostic 			rogue.exp_points = MAX_EXP + 1;
79632689Sbostic 		}
79732689Sbostic 		for (i = rogue.exp+1; i <= new_exp; i++) {
79832689Sbostic 			sprintf(mbuf, "welcome to level %d", i);
79932689Sbostic 			message(mbuf, 0);
80032689Sbostic 			if (promotion) {
80132689Sbostic 				hp = hp_raise();
80232689Sbostic 				rogue.hp_current += hp;
80332689Sbostic 				rogue.hp_max += hp;
80432689Sbostic 			}
80532689Sbostic 			rogue.exp = i;
80632689Sbostic 			print_stats(STAT_HP | STAT_EXP);
80732689Sbostic 		}
80832689Sbostic 	} else {
80932689Sbostic 		print_stats(STAT_EXP);
81032689Sbostic 	}
81132689Sbostic }
81232689Sbostic 
81332689Sbostic get_exp_level(e)
81432689Sbostic long e;
81532689Sbostic {
81632689Sbostic 	short i;
81732689Sbostic 
81832689Sbostic 	for (i = 0; i < (MAX_EXP_LEVEL - 1); i++) {
81932689Sbostic 		if (level_points[i] > e) {
82032689Sbostic 			break;
82132689Sbostic 		}
82232689Sbostic 	}
82332689Sbostic 	return(i+1);
82432689Sbostic }
82532689Sbostic 
82632689Sbostic hp_raise()
82732689Sbostic {
82832689Sbostic 	int hp;
82932689Sbostic 
83032689Sbostic 	hp = (wizard ? 10 : get_rand(3, 10));
83132689Sbostic 	return(hp);
83232689Sbostic }
83332689Sbostic 
83432689Sbostic show_average_hp()
83532689Sbostic {
83632689Sbostic 	char mbuf[80];
83732689Sbostic 	float real_average;
83832689Sbostic 	float effective_average;
83932689Sbostic 
84032689Sbostic 	if (rogue.exp == 1) {
84132689Sbostic 		real_average = effective_average = 0.00;
84232689Sbostic 	} else {
84332689Sbostic 		real_average = (float)
84432689Sbostic 			((rogue.hp_max - extra_hp - INIT_HP) + less_hp) / (rogue.exp - 1);
84532689Sbostic 		effective_average = (float) (rogue.hp_max - INIT_HP) / (rogue.exp - 1);
84632689Sbostic 
84732689Sbostic 	}
84832689Sbostic 	sprintf(mbuf, "R-Hp: %.2f, E-Hp: %.2f (!: %d, V: %d)", real_average,
84932689Sbostic 		effective_average, extra_hp, less_hp);
85032689Sbostic 	message(mbuf, 0);
85132689Sbostic }
85232689Sbostic 
85332689Sbostic mix_random_rooms()
85432689Sbostic {
85532689Sbostic 	short i, t;
85632689Sbostic 	short x, y;
85732689Sbostic 
85832689Sbostic 	for (i = 0; i < (3 * MAXROOMS); i++) {
85932689Sbostic 		do {
86032689Sbostic 			x = get_rand(0, (MAXROOMS-1));
86132689Sbostic 			y = get_rand(0, (MAXROOMS-1));
86232689Sbostic 		} while (x == y);
86332689Sbostic 		swap(random_rooms[x], random_rooms[y]);
86432689Sbostic 	}
86532689Sbostic }
866