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