games: Massive style(9) cleanup commit. Reduces differences to NetBSD.
[dragonfly.git] / games / rogue / level.c
blob089557c37e74d450a2e34658c4d47bacd4cc5def
1 /*-
2 * Copyright (c) 1988, 1993
3 * The Regents of the University of California. All rights reserved.
5 * This code is derived from software contributed to Berkeley by
6 * Timothy C. Stoehr.
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. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
32 * @(#)level.c 8.1 (Berkeley) 5/31/93
33 * $FreeBSD: src/games/rogue/level.c,v 1.3 1999/11/30 03:49:23 billf Exp $
34 * $DragonFly: src/games/rogue/level.c,v 1.4 2006/09/02 19:31:07 pavalos Exp $
38 * level.c
40 * This source herein may be modified and/or distributed by anybody who
41 * so desires, with the following restrictions:
42 * 1.) No portion of this notice shall be removed.
43 * 2.) Credit shall not be taken for the creation of this source.
44 * 3.) This code is not to be traded, sold, or used for personal
45 * gain or profit.
49 #include "rogue.h"
51 #define swap(x,y) {t = x; x = y; y = t;}
53 static void add_mazes(void);
54 static boolean connect_rooms(short, short);
55 static void draw_simple_passage(short, short, short, short, short);
56 static void fill_it(int, boolean);
57 static void fill_out_level(void);
58 static short get_exp_level(long);
59 static void hide_boxed_passage(short, short, short, short, short);
60 static void make_maze(short, short, short, short, short, short);
61 static void make_room(short, short, short, short);
62 static boolean mask_room(short, short *, short *, unsigned short);
63 static void mix_random_rooms(void);
64 static void put_door(room *, short, short *, short *);
65 static void recursive_deadend(short, const short *, short, short);
66 static boolean same_col(short, short);
67 static boolean same_row(short, short);
69 short cur_level = 0;
70 short max_level = 1;
71 short cur_room;
72 const char *new_level_message = NULL;
73 short party_room = NO_ROOM;
74 short r_de;
76 const long level_points[MAX_EXP_LEVEL] = {
77 10L,
78 20L,
79 40L,
80 80L,
81 160L,
82 320L,
83 640L,
84 1300L,
85 2600L,
86 5200L,
87 10000L,
88 20000L,
89 40000L,
90 80000L,
91 160000L,
92 320000L,
93 1000000L,
94 3333333L,
95 6666666L,
96 MAX_EXP,
97 99900000L
100 short random_rooms[MAXROOMS] = {3, 7, 5, 2, 0, 6, 1, 4, 8};
102 extern boolean being_held, wizard, detect_monster;
103 extern boolean see_invisible;
104 extern short bear_trap, levitate, extra_hp, less_hp;
106 void
107 make_level(void)
109 short i, j;
110 short must_1, must_2 = 0, must_3 = 0;
111 boolean big_room;
113 if (cur_level < LAST_DUNGEON) {
114 cur_level++;
116 if (cur_level > max_level) {
117 max_level = cur_level;
119 must_1 = get_rand(0, 5);
121 switch(must_1) {
122 case 0:
123 must_1 = 0;
124 must_2 = 1;
125 must_3 = 2;
126 break;
127 case 1:
128 must_1 = 3;
129 must_2 = 4;
130 must_3 = 5;
131 break;
132 case 2:
133 must_1 = 6;
134 must_2 = 7;
135 must_3 = 8;
136 break;
137 case 3:
138 must_1 = 0;
139 must_2 = 3;
140 must_3 = 6;
141 break;
142 case 4:
143 must_1 = 1;
144 must_2 = 4;
145 must_3 = 7;
146 break;
147 case 5:
148 must_1 = 2;
149 must_2 = 5;
150 must_3 = 8;
151 break;
153 if (rand_percent(8)) {
154 party_room = 0;
156 big_room = ((party_room != NO_ROOM) && rand_percent(1));
157 if (big_room) {
158 make_room(BIG_ROOM, 0, 0, 0);
159 } else {
160 for (i = 0; i < MAXROOMS; i++) {
161 make_room(i, must_1, must_2, must_3);
164 if (!big_room) {
165 add_mazes();
167 mix_random_rooms();
169 for (j = 0; j < MAXROOMS; j++) {
171 i = random_rooms[j];
173 if (i < (MAXROOMS-1)) {
174 connect_rooms(i, i+1);
176 if (i < (MAXROOMS-3)) {
177 connect_rooms(i, i+3);
179 if (i < (MAXROOMS-2)) {
180 if (rooms[i+1].is_room & R_NOTHING) {
181 if (connect_rooms(i, i+2)) {
182 rooms[i+1].is_room = R_CROSS;
186 if (i < (MAXROOMS-6)) {
187 if (rooms[i+3].is_room & R_NOTHING) {
188 if (connect_rooms(i, i+6)) {
189 rooms[i+3].is_room = R_CROSS;
193 if (is_all_connected()) {
194 break;
197 fill_out_level();
199 if (!has_amulet() && (cur_level >= AMULET_LEVEL)) {
200 put_amulet();
204 static void
205 make_room(short rn, short r1, short r2, short r3)
207 short left_col, right_col, top_row, bottom_row;
208 short width, height;
209 short row_offset, col_offset;
210 short i, j, ch;
212 left_col = right_col = top_row = bottom_row = 0;
214 switch(rn) {
215 case 0:
216 left_col = 0;
217 right_col = COL1-1;
218 top_row = MIN_ROW;
219 bottom_row = ROW1-1;
220 break;
221 case 1:
222 left_col = COL1+1;
223 right_col = COL2-1;
224 top_row = MIN_ROW;
225 bottom_row = ROW1-1;
226 break;
227 case 2:
228 left_col = COL2+1;
229 right_col = DCOLS-1;
230 top_row = MIN_ROW;
231 bottom_row = ROW1-1;
232 break;
233 case 3:
234 left_col = 0;
235 right_col = COL1-1;
236 top_row = ROW1+1;
237 bottom_row = ROW2-1;
238 break;
239 case 4:
240 left_col = COL1+1;
241 right_col = COL2-1;
242 top_row = ROW1+1;
243 bottom_row = ROW2-1;
244 break;
245 case 5:
246 left_col = COL2+1;
247 right_col = DCOLS-1;
248 top_row = ROW1+1;
249 bottom_row = ROW2-1;
250 break;
251 case 6:
252 left_col = 0;
253 right_col = COL1-1;
254 top_row = ROW2+1;
255 bottom_row = DROWS - 2;
256 break;
257 case 7:
258 left_col = COL1+1;
259 right_col = COL2-1;
260 top_row = ROW2+1;
261 bottom_row = DROWS - 2;
262 break;
263 case 8:
264 left_col = COL2+1;
265 right_col = DCOLS-1;
266 top_row = ROW2+1;
267 bottom_row = DROWS - 2;
268 break;
269 case BIG_ROOM:
270 top_row = get_rand(MIN_ROW, MIN_ROW+5);
271 bottom_row = get_rand(DROWS-7, DROWS-2);
272 left_col = get_rand(0, 10);
273 right_col = get_rand(DCOLS-11, DCOLS-1);
274 rn = 0;
275 goto B;
277 height = get_rand(4, (bottom_row - top_row + 1));
278 width = get_rand(7, (right_col - left_col - 2));
280 row_offset = get_rand(0, ((bottom_row - top_row) - height + 1));
281 col_offset = get_rand(0, ((right_col - left_col) - width + 1));
283 top_row += row_offset;
284 bottom_row = top_row + height - 1;
286 left_col += col_offset;
287 right_col = left_col + width - 1;
289 if ((rn != r1) && (rn != r2) && (rn != r3) && rand_percent(40)) {
290 goto END;
293 rooms[rn].is_room = R_ROOM;
295 for (i = top_row; i <= bottom_row; i++) {
296 for (j = left_col; j <= right_col; j++) {
297 if ((i == top_row) || (i == bottom_row)) {
298 ch = HORWALL;
299 } else if ( ((i != top_row) && (i != bottom_row)) &&
300 ((j == left_col) || (j == right_col))) {
301 ch = VERTWALL;
302 } else {
303 ch = FLOOR;
305 dungeon[i][j] = ch;
308 END:
309 rooms[rn].top_row = top_row;
310 rooms[rn].bottom_row = bottom_row;
311 rooms[rn].left_col = left_col;
312 rooms[rn].right_col = right_col;
315 static boolean
316 connect_rooms(short room1, short room2)
318 short row1, col1, row2, col2, dir;
320 if ((!(rooms[room1].is_room & (R_ROOM | R_MAZE))) ||
321 (!(rooms[room2].is_room & (R_ROOM | R_MAZE)))) {
322 return(0);
324 if (same_row(room1, room2) &&
325 (rooms[room1].left_col > rooms[room2].right_col)) {
326 put_door(&rooms[room1], LEFT, &row1, &col1);
327 put_door(&rooms[room2], RIGHT, &row2, &col2);
328 dir = LEFT;
329 } else if (same_row(room1, room2) &&
330 (rooms[room2].left_col > rooms[room1].right_col)) {
331 put_door(&rooms[room1], RIGHT, &row1, &col1);
332 put_door(&rooms[room2], LEFT, &row2, &col2);
333 dir = RIGHT;
334 } else if (same_col(room1, room2) &&
335 (rooms[room1].top_row > rooms[room2].bottom_row)) {
336 put_door(&rooms[room1], UPWARD, &row1, &col1);
337 put_door(&rooms[room2], DOWN, &row2, &col2);
338 dir = UPWARD;
339 } else if (same_col(room1, room2) &&
340 (rooms[room2].top_row > rooms[room1].bottom_row)) {
341 put_door(&rooms[room1], DOWN, &row1, &col1);
342 put_door(&rooms[room2], UPWARD, &row2, &col2);
343 dir = DOWN;
344 } else {
345 return(0);
348 do {
349 draw_simple_passage(row1, col1, row2, col2, dir);
350 } while (rand_percent(4));
352 rooms[room1].doors[dir/2].oth_room = room2;
353 rooms[room1].doors[dir/2].oth_row = row2;
354 rooms[room1].doors[dir/2].oth_col = col2;
356 rooms[room2].doors[(((dir+4)%DIRS)/2)].oth_room = room1;
357 rooms[room2].doors[(((dir+4)%DIRS)/2)].oth_row = row1;
358 rooms[room2].doors[(((dir+4)%DIRS)/2)].oth_col = col1;
359 return(1);
362 void
363 clear_level(void)
365 short i, j;
367 for (i = 0; i < MAXROOMS; i++) {
368 rooms[i].is_room = R_NOTHING;
369 for (j = 0; j < 4; j++) {
370 rooms[i].doors[j].oth_room = NO_ROOM;
374 for (i = 0; i < MAX_TRAPS; i++) {
375 traps[i].trap_type = NO_TRAP;
377 for (i = 0; i < DROWS; i++) {
378 for (j = 0; j < DCOLS; j++) {
379 dungeon[i][j] = NOTHING;
382 detect_monster = see_invisible = 0;
383 bear_trap = being_held = 0;
384 party_room = NO_ROOM;
385 rogue.row = rogue.col = -1;
386 clear();
389 static void
390 put_door(room *rm, short dir, short *row, short *col)
392 short wall_width;
394 wall_width = (rm->is_room & R_MAZE) ? 0 : 1;
396 switch(dir) {
397 case UPWARD:
398 case DOWN:
399 *row = ((dir == UPWARD) ? rm->top_row : rm->bottom_row);
400 do {
401 *col = get_rand(rm->left_col+wall_width,
402 rm->right_col-wall_width);
403 } while (!(dungeon[*row][*col] & (HORWALL | TUNNEL)));
404 break;
405 case RIGHT:
406 case LEFT:
407 *col = (dir == LEFT) ? rm->left_col : rm->right_col;
408 do {
409 *row = get_rand(rm->top_row+wall_width,
410 rm->bottom_row-wall_width);
411 } while (!(dungeon[*row][*col] & (VERTWALL | TUNNEL)));
412 break;
414 if (rm->is_room & R_ROOM) {
415 dungeon[*row][*col] = DOOR;
417 if ((cur_level > 2) && rand_percent(HIDE_PERCENT)) {
418 dungeon[*row][*col] |= HIDDEN;
420 rm->doors[dir/2].door_row = *row;
421 rm->doors[dir/2].door_col = *col;
424 static void
425 draw_simple_passage(short row1, short col1, short row2, short col2, short dir)
427 short i, middle, t;
429 if ((dir == LEFT) || (dir == RIGHT)) {
430 if (col1 > col2) {
431 swap(row1, row2);
432 swap(col1, col2);
434 middle = get_rand(col1+1, col2-1);
435 for (i = col1+1; i != middle; i++) {
436 dungeon[row1][i] = TUNNEL;
438 for (i = row1; i != row2; i += (row1 > row2) ? -1 : 1) {
439 dungeon[i][middle] = TUNNEL;
441 for (i = middle; i != col2; i++) {
442 dungeon[row2][i] = TUNNEL;
444 } else {
445 if (row1 > row2) {
446 swap(row1, row2);
447 swap(col1, col2);
449 middle = get_rand(row1+1, row2-1);
450 for (i = row1+1; i != middle; i++) {
451 dungeon[i][col1] = TUNNEL;
453 for (i = col1; i != col2; i += (col1 > col2) ? -1 : 1) {
454 dungeon[middle][i] = TUNNEL;
456 for (i = middle; i != row2; i++) {
457 dungeon[i][col2] = TUNNEL;
460 if (rand_percent(HIDE_PERCENT)) {
461 hide_boxed_passage(row1, col1, row2, col2, 1);
465 static boolean
466 same_row(short room1, short room2)
468 return((room1 / 3) == (room2 / 3));
471 static boolean
472 same_col(short room1, short room2)
474 return((room1 % 3) == (room2 % 3));
477 static void
478 add_mazes(void)
480 short i, j;
481 short start;
482 short maze_percent;
484 if (cur_level > 1) {
485 start = get_rand(0, (MAXROOMS-1));
486 maze_percent = (cur_level * 5) / 4;
488 if (cur_level > 15) {
489 maze_percent += cur_level;
491 for (i = 0; i < MAXROOMS; i++) {
492 j = ((start + i) % MAXROOMS);
493 if (rooms[j].is_room & R_NOTHING) {
494 if (rand_percent(maze_percent)) {
495 rooms[j].is_room = R_MAZE;
496 make_maze(get_rand(rooms[j].top_row+1, rooms[j].bottom_row-1),
497 get_rand(rooms[j].left_col+1, rooms[j].right_col-1),
498 rooms[j].top_row, rooms[j].bottom_row,
499 rooms[j].left_col, rooms[j].right_col);
500 hide_boxed_passage(rooms[j].top_row, rooms[j].left_col,
501 rooms[j].bottom_row, rooms[j].right_col,
502 get_rand(0, 2));
509 static void
510 fill_out_level(void)
512 short i, rn;
514 mix_random_rooms();
516 r_de = NO_ROOM;
518 for (i = 0; i < MAXROOMS; i++) {
519 rn = random_rooms[i];
520 if ((rooms[rn].is_room & R_NOTHING) ||
521 ((rooms[rn].is_room & R_CROSS) && coin_toss())) {
522 fill_it(rn, 1);
525 if (r_de != NO_ROOM) {
526 fill_it(r_de, 0);
530 static void
531 fill_it(int rn, boolean do_rec_de)
533 short i, tunnel_dir, door_dir, drow, dcol;
534 short target_room, rooms_found = 0;
535 short srow, scol, t;
536 static short offsets[4] = {-1, 1, 3, -3};
537 boolean did_this = 0;
539 for (i = 0; i < 10; i++) {
540 srow = get_rand(0, 3);
541 scol = get_rand(0, 3);
542 t = offsets[srow];
543 offsets[srow] = offsets[scol];
544 offsets[scol] = t;
546 for (i = 0; i < 4; i++) {
548 target_room = rn + offsets[i];
550 if (((target_room < 0) || (target_room >= MAXROOMS)) ||
551 (!(same_row(rn,target_room) || same_col(rn,target_room))) ||
552 (!(rooms[target_room].is_room & (R_ROOM | R_MAZE)))) {
553 continue;
555 if (same_row(rn, target_room)) {
556 tunnel_dir = (rooms[rn].left_col < rooms[target_room].left_col) ?
557 RIGHT : LEFT;
558 } else {
559 tunnel_dir = (rooms[rn].top_row < rooms[target_room].top_row) ?
560 DOWN : UPWARD;
562 door_dir = ((tunnel_dir + 4) % DIRS);
563 if (rooms[target_room].doors[door_dir/2].oth_room != NO_ROOM) {
564 continue;
566 if (((!do_rec_de) || did_this) ||
567 (!mask_room(rn, &srow, &scol, TUNNEL))) {
568 srow = (rooms[rn].top_row + rooms[rn].bottom_row) / 2;
569 scol = (rooms[rn].left_col + rooms[rn].right_col) / 2;
571 put_door(&rooms[target_room], door_dir, &drow, &dcol);
572 rooms_found++;
573 draw_simple_passage(srow, scol, drow, dcol, tunnel_dir);
574 rooms[rn].is_room = R_DEADEND;
575 dungeon[srow][scol] = TUNNEL;
577 if ((i < 3) && (!did_this)) {
578 did_this = 1;
579 if (coin_toss()) {
580 continue;
583 if ((rooms_found < 2) && do_rec_de) {
584 recursive_deadend(rn, offsets, srow, scol);
586 break;
590 static void
591 recursive_deadend(short rn, const short *offsets, short srow, short scol)
593 short i, de;
594 short drow, dcol, tunnel_dir;
596 rooms[rn].is_room = R_DEADEND;
597 dungeon[srow][scol] = TUNNEL;
599 for (i = 0; i < 4; i++) {
600 de = rn + offsets[i];
601 if (((de < 0) || (de >= MAXROOMS)) ||
602 (!(same_row(rn, de) || same_col(rn, de)))) {
603 continue;
605 if (!(rooms[de].is_room & R_NOTHING)) {
606 continue;
608 drow = (rooms[de].top_row + rooms[de].bottom_row) / 2;
609 dcol = (rooms[de].left_col + rooms[de].right_col) / 2;
610 if (same_row(rn, de)) {
611 tunnel_dir = (rooms[rn].left_col < rooms[de].left_col) ?
612 RIGHT : LEFT;
613 } else {
614 tunnel_dir = (rooms[rn].top_row < rooms[de].top_row) ?
615 DOWN : UPWARD;
617 draw_simple_passage(srow, scol, drow, dcol, tunnel_dir);
618 r_de = de;
619 recursive_deadend(de, offsets, drow, dcol);
623 static boolean
624 mask_room(short rn, short *row, short *col, unsigned short mask)
626 short i, j;
628 for (i = rooms[rn].top_row; i <= rooms[rn].bottom_row; i++) {
629 for (j = rooms[rn].left_col; j <= rooms[rn].right_col; j++) {
630 if (dungeon[i][j] & mask) {
631 *row = i;
632 *col = j;
633 return(1);
637 return(0);
640 static void
641 make_maze(short r, short c, short tr, short br, short lc, short rc)
643 char dirs[4];
644 short i, t;
646 dirs[0] = UPWARD;
647 dirs[1] = DOWN;
648 dirs[2] = LEFT;
649 dirs[3] = RIGHT;
651 dungeon[r][c] = TUNNEL;
653 if (rand_percent(20)) {
654 for (i = 0; i < 10; i++) {
655 short t1, t2;
657 t1 = get_rand(0, 3);
658 t2 = get_rand(0, 3);
660 swap(dirs[t1], dirs[t2]);
663 for (i = 0; i < 4; i++) {
664 switch(dirs[i]) {
665 case UPWARD:
666 if (((r-1) >= tr) &&
667 (dungeon[r-1][c] != TUNNEL) &&
668 (dungeon[r-1][c-1] != TUNNEL) &&
669 (dungeon[r-1][c+1] != TUNNEL) &&
670 (dungeon[r-2][c] != TUNNEL)) {
671 make_maze((r-1), c, tr, br, lc, rc);
673 break;
674 case DOWN:
675 if (((r+1) <= br) &&
676 (dungeon[r+1][c] != TUNNEL) &&
677 (dungeon[r+1][c-1] != TUNNEL) &&
678 (dungeon[r+1][c+1] != TUNNEL) &&
679 (dungeon[r+2][c] != TUNNEL)) {
680 make_maze((r+1), c, tr, br, lc, rc);
682 break;
683 case LEFT:
684 if (((c-1) >= lc) &&
685 (dungeon[r][c-1] != TUNNEL) &&
686 (dungeon[r-1][c-1] != TUNNEL) &&
687 (dungeon[r+1][c-1] != TUNNEL) &&
688 (dungeon[r][c-2] != TUNNEL)) {
689 make_maze(r, (c-1), tr, br, lc, rc);
691 break;
692 case RIGHT:
693 if (((c+1) <= rc) &&
694 (dungeon[r][c+1] != TUNNEL) &&
695 (dungeon[r-1][c+1] != TUNNEL) &&
696 (dungeon[r+1][c+1] != TUNNEL) &&
697 (dungeon[r][c+2] != TUNNEL)) {
698 make_maze(r, (c+1), tr, br, lc, rc);
700 break;
705 static void
706 hide_boxed_passage(short row1, short col1, short row2, short col2, short n)
708 short i, j, t;
709 short row, col, row_cut, col_cut;
710 short h, w;
712 if (cur_level > 2) {
713 if (row1 > row2) {
714 swap(row1, row2);
716 if (col1 > col2) {
717 swap(col1, col2);
719 h = row2 - row1;
720 w = col2 - col1;
722 if ((w >= 5) || (h >= 5)) {
723 row_cut = ((h >= 2) ? 1 : 0);
724 col_cut = ((w >= 2) ? 1 : 0);
726 for (i = 0; i < n; i++) {
727 for (j = 0; j < 10; j++) {
728 row = get_rand(row1 + row_cut, row2 - row_cut);
729 col = get_rand(col1 + col_cut, col2 - col_cut);
730 if (dungeon[row][col] == TUNNEL) {
731 dungeon[row][col] |= HIDDEN;
732 break;
740 void
741 put_player(short nr) /* try not to put in this room */
743 short rn = nr, misses;
744 short row, col;
746 for (misses = 0; ((misses < 2) && (rn == nr)); misses++) {
747 gr_row_col(&row, &col, (FLOOR | TUNNEL | OBJECT | STAIRS));
748 rn = get_room_number(row, col);
750 rogue.row = row;
751 rogue.col = col;
753 if (dungeon[rogue.row][rogue.col] & TUNNEL) {
754 cur_room = PASSAGE;
755 } else {
756 cur_room = rn;
758 if (cur_room != PASSAGE) {
759 light_up_room(cur_room);
760 } else {
761 light_passage(rogue.row, rogue.col);
763 rn = get_room_number(rogue.row, rogue.col);
764 wake_room(rn, 1, rogue.row, rogue.col);
765 if (new_level_message) {
766 message(new_level_message, 0);
767 new_level_message = NULL;
769 mvaddch(rogue.row, rogue.col, rogue.fchar);
772 boolean
773 drop_check(void)
775 if (wizard) {
776 return(1);
778 if (dungeon[rogue.row][rogue.col] & STAIRS) {
779 if (levitate) {
780 message("you're floating in the air!", 0);
781 return(0);
783 return(1);
785 message("I see no way down", 0);
786 return(0);
789 boolean
790 check_up(void)
792 if (!wizard) {
793 if (!(dungeon[rogue.row][rogue.col] & STAIRS)) {
794 message("I see no way up", 0);
795 return(0);
797 if (!has_amulet()) {
798 message("your way is magically blocked", 0);
799 return(0);
802 new_level_message = "you feel a wrenching sensation in your gut";
803 if (cur_level == 1) {
804 win();
805 } else {
806 cur_level -= 2;
807 return(1);
809 return(0);
812 void
813 add_exp(int e, boolean promotion)
815 char mbuf[40];
816 short new_exp;
817 short i, hp;
819 rogue.exp_points += e;
821 if (rogue.exp_points >= level_points[rogue.exp-1]) {
822 new_exp = get_exp_level(rogue.exp_points);
823 if (rogue.exp_points > MAX_EXP) {
824 rogue.exp_points = MAX_EXP + 1;
826 for (i = rogue.exp+1; i <= new_exp; i++) {
827 sprintf(mbuf, "welcome to level %d", i);
828 message(mbuf, 0);
829 if (promotion) {
830 hp = hp_raise();
831 rogue.hp_current += hp;
832 rogue.hp_max += hp;
834 rogue.exp = i;
835 print_stats(STAT_HP | STAT_EXP);
837 } else {
838 print_stats(STAT_EXP);
842 static short
843 get_exp_level(long e)
845 short i;
847 for (i = 0; i < (MAX_EXP_LEVEL - 1); i++) {
848 if (level_points[i] > e) {
849 break;
852 return(i+1);
856 hp_raise(void)
858 int hp;
860 hp = (wizard ? 10 : get_rand(3, 10));
861 return(hp);
864 void
865 show_average_hp(void)
867 char mbuf[80];
868 float real_average;
869 float effective_average;
871 if (rogue.exp == 1) {
872 real_average = effective_average = 0.00;
873 } else {
874 real_average = (float)
875 ((rogue.hp_max - extra_hp - INIT_HP) + less_hp) / (rogue.exp - 1);
876 effective_average = (float)(rogue.hp_max - INIT_HP) / (rogue.exp - 1);
879 sprintf(mbuf, "R-Hp: %.2f, E-Hp: %.2f (!: %d, V: %d)", real_average,
880 effective_average, extra_hp, less_hp);
881 message(mbuf, 0);
884 static void
885 mix_random_rooms(void)
887 short i, t;
888 short x, y;
890 for (i = 0; i < (3 * MAXROOMS); i++) {
891 do {
892 x = get_rand(0, (MAXROOMS-1));
893 y = get_rand(0, (MAXROOMS-1));
894 } while (x == y);
895 swap(random_rooms[x], random_rooms[y]);