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