Updated to libg++ 2.4
[unix-history] / games / rogue / level.c
CommitLineData
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
38static 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
57short cur_level = 0;
58short max_level = 1;
59short cur_room;
60char *new_level_message = 0;
61short party_room = NO_ROOM;
62short r_de;
63
64long 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
88short random_rooms[MAXROOMS] = {3, 7, 5, 2, 0, 6, 1, 4, 8};
89
90extern boolean being_held, wizard, detect_monster;
91extern boolean see_invisible;
92extern short bear_trap, levitate, extra_hp, less_hp, cur_room;
93
94make_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
191make_room(rn, r1, r2, r3)
192short 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 }
277B:
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 }
293END:
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
300connect_rooms(room1, room2)
301short 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
347clear_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
373put_door(rm, dir, row, col)
374room *rm;
375short dir;
376short *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
410draw_simple_passage(row1, col1, row2, col2, dir)
411short 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
451same_row(room1, room2)
452{
453 return((room1 / 3) == (room2 / 3));
454}
455
456same_col(room1, room2)
457{
458 return((room1 % 3) == (room2 % 3));
459}
460
461add_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
492fill_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
512fill_it(rn, do_rec_de)
513int rn;
514boolean 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
573recursive_deadend(rn, offsets, srow, scol)
574short rn;
575short *offsets;
576short 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
608boolean
609mask_room(rn, row, col, mask)
610short rn;
611short *row, *col;
612unsigned 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
628make_maze(r, c, tr, br, lc, rc)
629short 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
693hide_boxed_passage(row1, col1, row2, col2, n)
694short 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
728put_player(nr)
729short 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
760drop_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
776check_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
798add_exp(e, promotion)
799int e;
800boolean 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
829get_exp_level(e)
830long 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
842hp_raise()
843{
844 int hp;
845
846 hp = (wizard ? 10 : get_rand(3, 10));
847 return(hp);
848}
849
850show_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
869mix_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}