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