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