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