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