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