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