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