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