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