132689Sbostic /*
2*60842Sbostic * Copyright (c) 1988, 1993
3*60842Sbostic * The Regents of the University of California. All rights reserved.
436704Sbostic *
536704Sbostic * This code is derived from software contributed to Berkeley by
636704Sbostic * Timothy C. Stoehr.
736704Sbostic *
842594Sbostic * %sccs.include.redist.c%
936704Sbostic */
1036704Sbostic
1136704Sbostic #ifndef lint
12*60842Sbostic static char sccsid[] = "@(#)level.c 8.1 (Berkeley) 05/31/93";
1336704Sbostic #endif /* not lint */
1436704Sbostic
1536704Sbostic /*
1632689Sbostic * level.c
1732689Sbostic *
1832689Sbostic * This source herein may be modified and/or distributed by anybody who
1932689Sbostic * so desires, with the following restrictions:
2032689Sbostic * 1.) No portion of this notice shall be removed.
2132689Sbostic * 2.) Credit shall not be taken for the creation of this source.
2232689Sbostic * 3.) This code is not to be traded, sold, or used for personal
2332689Sbostic * gain or profit.
2432689Sbostic *
2532689Sbostic */
2632689Sbostic
2732689Sbostic #include "rogue.h"
2832689Sbostic
2932689Sbostic #define swap(x,y) {t = x; x = y; y = t;}
3032689Sbostic
3132689Sbostic short cur_level = 0;
3232689Sbostic short max_level = 1;
3332689Sbostic short cur_room;
3432689Sbostic char *new_level_message = 0;
3532689Sbostic short party_room = NO_ROOM;
3632689Sbostic short r_de;
3732689Sbostic
3832689Sbostic long level_points[MAX_EXP_LEVEL] = {
3932689Sbostic 10L,
4032689Sbostic 20L,
4132689Sbostic 40L,
4232689Sbostic 80L,
4332689Sbostic 160L,
4432689Sbostic 320L,
4532689Sbostic 640L,
4632689Sbostic 1300L,
4732689Sbostic 2600L,
4832689Sbostic 5200L,
4932689Sbostic 10000L,
5032689Sbostic 20000L,
5132689Sbostic 40000L,
5232689Sbostic 80000L,
5332689Sbostic 160000L,
5432689Sbostic 320000L,
5532689Sbostic 1000000L,
5632689Sbostic 3333333L,
5732689Sbostic 6666666L,
5832689Sbostic MAX_EXP,
5932689Sbostic 99900000L
6032689Sbostic };
6132689Sbostic
6232689Sbostic short random_rooms[MAXROOMS] = {3, 7, 5, 2, 0, 6, 1, 4, 8};
6332689Sbostic
6432689Sbostic extern boolean being_held, wizard, detect_monster;
6532689Sbostic extern boolean see_invisible;
6632689Sbostic extern short bear_trap, levitate, extra_hp, less_hp, cur_room;
6732689Sbostic
make_level()6832689Sbostic make_level()
6932689Sbostic {
7032689Sbostic short i, j;
7132689Sbostic short must_1, must_2, must_3;
7232689Sbostic boolean big_room;
7332689Sbostic
7432689Sbostic if (cur_level < LAST_DUNGEON) {
7532689Sbostic cur_level++;
7632689Sbostic }
7732689Sbostic if (cur_level > max_level) {
7832689Sbostic max_level = cur_level;
7932689Sbostic }
8032689Sbostic must_1 = get_rand(0, 5);
8132689Sbostic
8232689Sbostic switch(must_1) {
8332689Sbostic case 0:
8432689Sbostic must_1 = 0;
8532689Sbostic must_2 = 1;
8632689Sbostic must_3 = 2;
8732689Sbostic break;
8832689Sbostic case 1:
8932689Sbostic must_1 = 3;
9032689Sbostic must_2 = 4;
9132689Sbostic must_3 = 5;
9232689Sbostic break;
9332689Sbostic case 2:
9432689Sbostic must_1 = 6;
9532689Sbostic must_2 = 7;
9632689Sbostic must_3 = 8;
9732689Sbostic break;
9832689Sbostic case 3:
9932689Sbostic must_1 = 0;
10032689Sbostic must_2 = 3;
10132689Sbostic must_3 = 6;
10232689Sbostic break;
10332689Sbostic case 4:
10432689Sbostic must_1 = 1;
10532689Sbostic must_2 = 4;
10632689Sbostic must_3 = 7;
10732689Sbostic break;
10832689Sbostic case 5:
10932689Sbostic must_1 = 2;
11032689Sbostic must_2 = 5;
11132689Sbostic must_3 = 8;
11232689Sbostic break;
11332689Sbostic }
11432689Sbostic if (rand_percent(8)) {
11532689Sbostic party_room = 0;
11632689Sbostic }
11732689Sbostic big_room = ((party_room != NO_ROOM) && rand_percent(1));
11832689Sbostic if (big_room) {
11932689Sbostic make_room(BIG_ROOM, 0, 0, 0);
12032689Sbostic } else {
12132689Sbostic for (i = 0; i < MAXROOMS; i++) {
12232689Sbostic make_room(i, must_1, must_2, must_3);
12332689Sbostic }
12432689Sbostic }
12532689Sbostic if (!big_room) {
12632689Sbostic add_mazes();
12732689Sbostic
12832689Sbostic mix_random_rooms();
12932689Sbostic
13032689Sbostic for (j = 0; j < MAXROOMS; j++) {
13132689Sbostic
13232689Sbostic i = random_rooms[j];
13332689Sbostic
13432689Sbostic if (i < (MAXROOMS-1)) {
13532689Sbostic (void) connect_rooms(i, i+1);
13632689Sbostic }
13732689Sbostic if (i < (MAXROOMS-3)) {
13832689Sbostic (void) connect_rooms(i, i+3);
13932689Sbostic }
14032689Sbostic if (i < (MAXROOMS-2)) {
14132689Sbostic if (rooms[i+1].is_room & R_NOTHING) {
14232689Sbostic if (connect_rooms(i, i+2)) {
14332689Sbostic rooms[i+1].is_room = R_CROSS;
14432689Sbostic }
14532689Sbostic }
14632689Sbostic }
14732689Sbostic if (i < (MAXROOMS-6)) {
14832689Sbostic if (rooms[i+3].is_room & R_NOTHING) {
14932689Sbostic if (connect_rooms(i, i+6)) {
15032689Sbostic rooms[i+3].is_room = R_CROSS;
15132689Sbostic }
15232689Sbostic }
15332689Sbostic }
15432689Sbostic if (is_all_connected()) {
15532689Sbostic break;
15632689Sbostic }
15732689Sbostic }
15832689Sbostic fill_out_level();
15932689Sbostic }
16032689Sbostic if (!has_amulet() && (cur_level >= AMULET_LEVEL)) {
16132689Sbostic put_amulet();
16232689Sbostic }
16332689Sbostic }
16432689Sbostic
make_room(rn,r1,r2,r3)16532689Sbostic make_room(rn, r1, r2, r3)
16632689Sbostic short rn, r1, r2, r3;
16732689Sbostic {
16832689Sbostic short left_col, right_col, top_row, bottom_row;
16932689Sbostic short width, height;
17032689Sbostic short row_offset, col_offset;
17132689Sbostic short i, j, ch;
17232689Sbostic
17332689Sbostic switch(rn) {
17432689Sbostic case 0:
17532689Sbostic left_col = 0;
17632689Sbostic right_col = COL1-1;
17732689Sbostic top_row = MIN_ROW;
17832689Sbostic bottom_row = ROW1-1;
17932689Sbostic break;
18032689Sbostic case 1:
18132689Sbostic left_col = COL1+1;
18232689Sbostic right_col = COL2-1;
18332689Sbostic top_row = MIN_ROW;
18432689Sbostic bottom_row = ROW1-1;
18532689Sbostic break;
18632689Sbostic case 2:
18732689Sbostic left_col = COL2+1;
18832689Sbostic right_col = DCOLS-1;
18932689Sbostic top_row = MIN_ROW;
19032689Sbostic bottom_row = ROW1-1;
19132689Sbostic break;
19232689Sbostic case 3:
19332689Sbostic left_col = 0;
19432689Sbostic right_col = COL1-1;
19532689Sbostic top_row = ROW1+1;
19632689Sbostic bottom_row = ROW2-1;
19732689Sbostic break;
19832689Sbostic case 4:
19932689Sbostic left_col = COL1+1;
20032689Sbostic right_col = COL2-1;
20132689Sbostic top_row = ROW1+1;
20232689Sbostic bottom_row = ROW2-1;
20332689Sbostic break;
20432689Sbostic case 5:
20532689Sbostic left_col = COL2+1;
20632689Sbostic right_col = DCOLS-1;
20732689Sbostic top_row = ROW1+1;
20832689Sbostic bottom_row = ROW2-1;
20932689Sbostic break;
21032689Sbostic case 6:
21132689Sbostic left_col = 0;
21232689Sbostic right_col = COL1-1;
21332689Sbostic top_row = ROW2+1;
21432689Sbostic bottom_row = DROWS - 2;
21532689Sbostic break;
21632689Sbostic case 7:
21732689Sbostic left_col = COL1+1;
21832689Sbostic right_col = COL2-1;
21932689Sbostic top_row = ROW2+1;
22032689Sbostic bottom_row = DROWS - 2;
22132689Sbostic break;
22232689Sbostic case 8:
22332689Sbostic left_col = COL2+1;
22432689Sbostic right_col = DCOLS-1;
22532689Sbostic top_row = ROW2+1;
22632689Sbostic bottom_row = DROWS - 2;
22732689Sbostic break;
22832689Sbostic case BIG_ROOM:
22932689Sbostic top_row = get_rand(MIN_ROW, MIN_ROW+5);
23032689Sbostic bottom_row = get_rand(DROWS-7, DROWS-2);
23132689Sbostic left_col = get_rand(0, 10);;
23232689Sbostic right_col = get_rand(DCOLS-11, DCOLS-1);
23332689Sbostic rn = 0;
23432689Sbostic goto B;
23532689Sbostic }
23632689Sbostic height = get_rand(4, (bottom_row - top_row + 1));
23732689Sbostic width = get_rand(7, (right_col - left_col - 2));
23832689Sbostic
23932689Sbostic row_offset = get_rand(0, ((bottom_row - top_row) - height + 1));
24032689Sbostic col_offset = get_rand(0, ((right_col - left_col) - width + 1));
24132689Sbostic
24232689Sbostic top_row += row_offset;
24332689Sbostic bottom_row = top_row + height - 1;
24432689Sbostic
24532689Sbostic left_col += col_offset;
24632689Sbostic right_col = left_col + width - 1;
24732689Sbostic
24832689Sbostic if ((rn != r1) && (rn != r2) && (rn != r3) && rand_percent(40)) {
24932689Sbostic goto END;
25032689Sbostic }
25132689Sbostic B:
25232689Sbostic rooms[rn].is_room = R_ROOM;
25332689Sbostic
25432689Sbostic for (i = top_row; i <= bottom_row; i++) {
25532689Sbostic for (j = left_col; j <= right_col; j++) {
25632689Sbostic if ((i == top_row) || (i == bottom_row)) {
25732689Sbostic ch = HORWALL;
25832689Sbostic } else if ( ((i != top_row) && (i != bottom_row)) &&
25932689Sbostic ((j == left_col) || (j == right_col))) {
26032689Sbostic ch = VERTWALL;
26132689Sbostic } else {
26232689Sbostic ch = FLOOR;
26332689Sbostic }
26432689Sbostic dungeon[i][j] = ch;
26532689Sbostic }
26632689Sbostic }
26732689Sbostic END:
26832689Sbostic rooms[rn].top_row = top_row;
26932689Sbostic rooms[rn].bottom_row = bottom_row;
27032689Sbostic rooms[rn].left_col = left_col;
27132689Sbostic rooms[rn].right_col = right_col;
27232689Sbostic }
27332689Sbostic
connect_rooms(room1,room2)27432689Sbostic connect_rooms(room1, room2)
27532689Sbostic short room1, room2;
27632689Sbostic {
27732689Sbostic short row1, col1, row2, col2, dir;
27832689Sbostic
27932689Sbostic if ((!(rooms[room1].is_room & (R_ROOM | R_MAZE))) ||
28032689Sbostic (!(rooms[room2].is_room & (R_ROOM | R_MAZE)))) {
28132689Sbostic return(0);
28232689Sbostic }
28332689Sbostic if (same_row(room1, room2) &&
28432689Sbostic (rooms[room1].left_col > rooms[room2].right_col)) {
28532689Sbostic put_door(&rooms[room1], LEFT, &row1, &col1);
28632689Sbostic put_door(&rooms[room2], RIGHT, &row2, &col2);
28732689Sbostic dir = LEFT;
28832689Sbostic } else if (same_row(room1, room2) &&
28932689Sbostic (rooms[room2].left_col > rooms[room1].right_col)) {
29032689Sbostic put_door(&rooms[room1], RIGHT, &row1, &col1);
29132689Sbostic put_door(&rooms[room2], LEFT, &row2, &col2);
29232689Sbostic dir = RIGHT;
29332689Sbostic } else if (same_col(room1, room2) &&
29432689Sbostic (rooms[room1].top_row > rooms[room2].bottom_row)) {
29532689Sbostic put_door(&rooms[room1], UPWARD, &row1, &col1);
29632689Sbostic put_door(&rooms[room2], DOWN, &row2, &col2);
29732689Sbostic dir = UPWARD;
29832689Sbostic } else if (same_col(room1, room2) &&
29932689Sbostic (rooms[room2].top_row > rooms[room1].bottom_row)) {
30032689Sbostic put_door(&rooms[room1], DOWN, &row1, &col1);
30132689Sbostic put_door(&rooms[room2], UPWARD, &row2, &col2);
30232689Sbostic dir = DOWN;
30332689Sbostic } else {
30432689Sbostic return(0);
30532689Sbostic }
30632689Sbostic
30732689Sbostic do {
30832689Sbostic draw_simple_passage(row1, col1, row2, col2, dir);
30932689Sbostic } while (rand_percent(4));
31032689Sbostic
31132689Sbostic rooms[room1].doors[dir/2].oth_room = room2;
31232689Sbostic rooms[room1].doors[dir/2].oth_row = row2;
31332689Sbostic rooms[room1].doors[dir/2].oth_col = col2;
31432689Sbostic
31532689Sbostic rooms[room2].doors[(((dir+4)%DIRS)/2)].oth_room = room1;
31632689Sbostic rooms[room2].doors[(((dir+4)%DIRS)/2)].oth_row = row1;
31732689Sbostic rooms[room2].doors[(((dir+4)%DIRS)/2)].oth_col = col1;
31832689Sbostic return(1);
31932689Sbostic }
32032689Sbostic
clear_level()32132689Sbostic clear_level()
32232689Sbostic {
32332689Sbostic short i, j;
32432689Sbostic
32532689Sbostic for (i = 0; i < MAXROOMS; i++) {
32632689Sbostic rooms[i].is_room = R_NOTHING;
32732689Sbostic for (j = 0; j < 4; j++) {
32832689Sbostic rooms[i].doors[j].oth_room = NO_ROOM;
32932689Sbostic }
33032689Sbostic }
33132689Sbostic
33232689Sbostic for (i = 0; i < MAX_TRAPS; i++) {
33332689Sbostic traps[i].trap_type = NO_TRAP;
33432689Sbostic }
33532689Sbostic for (i = 0; i < DROWS; i++) {
33632689Sbostic for (j = 0; j < DCOLS; j++) {
33732689Sbostic dungeon[i][j] = NOTHING;
33832689Sbostic }
33932689Sbostic }
34032689Sbostic detect_monster = see_invisible = 0;
34132689Sbostic being_held = bear_trap = 0;
34232689Sbostic party_room = NO_ROOM;
34332689Sbostic rogue.row = rogue.col = -1;
34432689Sbostic clear();
34532689Sbostic }
34632689Sbostic
put_door(rm,dir,row,col)34732689Sbostic put_door(rm, dir, row, col)
34832689Sbostic room *rm;
34932689Sbostic short dir;
35032689Sbostic short *row, *col;
35132689Sbostic {
35232689Sbostic short wall_width;
35332689Sbostic
35432689Sbostic wall_width = (rm->is_room & R_MAZE) ? 0 : 1;
35532689Sbostic
35632689Sbostic switch(dir) {
35732689Sbostic case UPWARD:
35832689Sbostic case DOWN:
35932689Sbostic *row = ((dir == UPWARD) ? rm->top_row : rm->bottom_row);
36032689Sbostic do {
36132689Sbostic *col = get_rand(rm->left_col+wall_width,
36232689Sbostic rm->right_col-wall_width);
36332689Sbostic } while (!(dungeon[*row][*col] & (HORWALL | TUNNEL)));
36432689Sbostic break;
36532689Sbostic case RIGHT:
36632689Sbostic case LEFT:
36732689Sbostic *col = (dir == LEFT) ? rm->left_col : rm->right_col;
36832689Sbostic do {
36932689Sbostic *row = get_rand(rm->top_row+wall_width,
37032689Sbostic rm->bottom_row-wall_width);
37132689Sbostic } while (!(dungeon[*row][*col] & (VERTWALL | TUNNEL)));
37232689Sbostic break;
37332689Sbostic }
37432689Sbostic if (rm->is_room & R_ROOM) {
37532689Sbostic dungeon[*row][*col] = DOOR;
37632689Sbostic }
37732689Sbostic if ((cur_level > 2) && rand_percent(HIDE_PERCENT)) {
37832689Sbostic dungeon[*row][*col] |= HIDDEN;
37932689Sbostic }
38032689Sbostic rm->doors[dir/2].door_row = *row;
38132689Sbostic rm->doors[dir/2].door_col = *col;
38232689Sbostic }
38332689Sbostic
draw_simple_passage(row1,col1,row2,col2,dir)38432689Sbostic draw_simple_passage(row1, col1, row2, col2, dir)
38532689Sbostic short row1, col1, row2, col2, dir;
38632689Sbostic {
38732689Sbostic short i, middle, t;
38832689Sbostic
38932689Sbostic if ((dir == LEFT) || (dir == RIGHT)) {
39032689Sbostic if (col1 > col2) {
39132689Sbostic swap(row1, row2);
39232689Sbostic swap(col1, col2);
39332689Sbostic }
39432689Sbostic middle = get_rand(col1+1, col2-1);
39532689Sbostic for (i = col1+1; i != middle; i++) {
39632689Sbostic dungeon[row1][i] = TUNNEL;
39732689Sbostic }
39832689Sbostic for (i = row1; i != row2; i += (row1 > row2) ? -1 : 1) {
39932689Sbostic dungeon[i][middle] = TUNNEL;
40032689Sbostic }
40132689Sbostic for (i = middle; i != col2; i++) {
40232689Sbostic dungeon[row2][i] = TUNNEL;
40332689Sbostic }
40432689Sbostic } else {
40532689Sbostic if (row1 > row2) {
40632689Sbostic swap(row1, row2);
40732689Sbostic swap(col1, col2);
40832689Sbostic }
40932689Sbostic middle = get_rand(row1+1, row2-1);
41032689Sbostic for (i = row1+1; i != middle; i++) {
41132689Sbostic dungeon[i][col1] = TUNNEL;
41232689Sbostic }
41332689Sbostic for (i = col1; i != col2; i += (col1 > col2) ? -1 : 1) {
41432689Sbostic dungeon[middle][i] = TUNNEL;
41532689Sbostic }
41632689Sbostic for (i = middle; i != row2; i++) {
41732689Sbostic dungeon[i][col2] = TUNNEL;
41832689Sbostic }
41932689Sbostic }
42032689Sbostic if (rand_percent(HIDE_PERCENT)) {
42132689Sbostic hide_boxed_passage(row1, col1, row2, col2, 1);
42232689Sbostic }
42332689Sbostic }
42432689Sbostic
same_row(room1,room2)42532689Sbostic same_row(room1, room2)
42632689Sbostic {
42732689Sbostic return((room1 / 3) == (room2 / 3));
42832689Sbostic }
42932689Sbostic
same_col(room1,room2)43032689Sbostic same_col(room1, room2)
43132689Sbostic {
43232689Sbostic return((room1 % 3) == (room2 % 3));
43332689Sbostic }
43432689Sbostic
add_mazes()43532689Sbostic add_mazes()
43632689Sbostic {
43732689Sbostic short i, j;
43832689Sbostic short start;
43932689Sbostic short maze_percent;
44032689Sbostic
44132689Sbostic if (cur_level > 1) {
44232689Sbostic start = get_rand(0, (MAXROOMS-1));
44332689Sbostic maze_percent = (cur_level * 5) / 4;
44432689Sbostic
44532689Sbostic if (cur_level > 15) {
44632689Sbostic maze_percent += cur_level;
44732689Sbostic }
44832689Sbostic for (i = 0; i < MAXROOMS; i++) {
44932689Sbostic j = ((start + i) % MAXROOMS);
45032689Sbostic if (rooms[j].is_room & R_NOTHING) {
45132689Sbostic if (rand_percent(maze_percent)) {
45232689Sbostic rooms[j].is_room = R_MAZE;
45332689Sbostic make_maze(get_rand(rooms[j].top_row+1, rooms[j].bottom_row-1),
45432689Sbostic get_rand(rooms[j].left_col+1, rooms[j].right_col-1),
45532689Sbostic rooms[j].top_row, rooms[j].bottom_row,
45632689Sbostic rooms[j].left_col, rooms[j].right_col);
45732689Sbostic hide_boxed_passage(rooms[j].top_row, rooms[j].left_col,
45832689Sbostic rooms[j].bottom_row, rooms[j].right_col,
45932689Sbostic get_rand(0, 2));
46032689Sbostic }
46132689Sbostic }
46232689Sbostic }
46332689Sbostic }
46432689Sbostic }
46532689Sbostic
fill_out_level()46632689Sbostic fill_out_level()
46732689Sbostic {
46832689Sbostic short i, rn;
46932689Sbostic
47032689Sbostic mix_random_rooms();
47132689Sbostic
47232689Sbostic r_de = NO_ROOM;
47332689Sbostic
47432689Sbostic for (i = 0; i < MAXROOMS; i++) {
47532689Sbostic rn = random_rooms[i];
47632689Sbostic if ((rooms[rn].is_room & R_NOTHING) ||
47732689Sbostic ((rooms[rn].is_room & R_CROSS) && coin_toss())) {
47832689Sbostic fill_it(rn, 1);
47932689Sbostic }
48032689Sbostic }
48132689Sbostic if (r_de != NO_ROOM) {
48232689Sbostic fill_it(r_de, 0);
48332689Sbostic }
48432689Sbostic }
48532689Sbostic
fill_it(rn,do_rec_de)48632689Sbostic fill_it(rn, do_rec_de)
48732689Sbostic int rn;
48832689Sbostic boolean do_rec_de;
48932689Sbostic {
49032689Sbostic short i, tunnel_dir, door_dir, drow, dcol;
49132689Sbostic short target_room, rooms_found = 0;
49232689Sbostic short srow, scol, t;
49332689Sbostic static short offsets[4] = {-1, 1, 3, -3};
49432689Sbostic boolean did_this = 0;
49532689Sbostic
49632689Sbostic for (i = 0; i < 10; i++) {
49732689Sbostic srow = get_rand(0, 3);
49832689Sbostic scol = get_rand(0, 3);
49932689Sbostic t = offsets[srow];
50032689Sbostic offsets[srow] = offsets[scol];
50132689Sbostic offsets[scol] = t;
50232689Sbostic }
50332689Sbostic for (i = 0; i < 4; i++) {
50432689Sbostic
50532689Sbostic target_room = rn + offsets[i];
50632689Sbostic
50732689Sbostic if (((target_room < 0) || (target_room >= MAXROOMS)) ||
50832689Sbostic (!(same_row(rn,target_room) || same_col(rn,target_room))) ||
50932689Sbostic (!(rooms[target_room].is_room & (R_ROOM | R_MAZE)))) {
51032689Sbostic continue;
51132689Sbostic }
51232689Sbostic if (same_row(rn, target_room)) {
51332689Sbostic tunnel_dir = (rooms[rn].left_col < rooms[target_room].left_col) ?
51432689Sbostic RIGHT : LEFT;
51532689Sbostic } else {
51632689Sbostic tunnel_dir = (rooms[rn].top_row < rooms[target_room].top_row) ?
51732689Sbostic DOWN : UPWARD;
51832689Sbostic }
51932689Sbostic door_dir = ((tunnel_dir + 4) % DIRS);
52032689Sbostic if (rooms[target_room].doors[door_dir/2].oth_room != NO_ROOM) {
52132689Sbostic continue;
52232689Sbostic }
52332689Sbostic if (((!do_rec_de) || did_this) ||
52432689Sbostic (!mask_room(rn, &srow, &scol, TUNNEL))) {
52532689Sbostic srow = (rooms[rn].top_row + rooms[rn].bottom_row) / 2;
52632689Sbostic scol = (rooms[rn].left_col + rooms[rn].right_col) / 2;
52732689Sbostic }
52832689Sbostic put_door(&rooms[target_room], door_dir, &drow, &dcol);
52932689Sbostic rooms_found++;
53032689Sbostic draw_simple_passage(srow, scol, drow, dcol, tunnel_dir);
53132689Sbostic rooms[rn].is_room = R_DEADEND;
53232689Sbostic dungeon[srow][scol] = TUNNEL;
53332689Sbostic
53432689Sbostic if ((i < 3) && (!did_this)) {
53532689Sbostic did_this = 1;
53632689Sbostic if (coin_toss()) {
53732689Sbostic continue;
53832689Sbostic }
53932689Sbostic }
54032689Sbostic if ((rooms_found < 2) && do_rec_de) {
54132689Sbostic recursive_deadend(rn, offsets, srow, scol);
54232689Sbostic }
54332689Sbostic break;
54432689Sbostic }
54532689Sbostic }
54632689Sbostic
recursive_deadend(rn,offsets,srow,scol)54732689Sbostic recursive_deadend(rn, offsets, srow, scol)
54832689Sbostic short rn;
54932689Sbostic short *offsets;
55032689Sbostic short srow, scol;
55132689Sbostic {
55232689Sbostic short i, de;
55332689Sbostic short drow, dcol, tunnel_dir;
55432689Sbostic
55532689Sbostic rooms[rn].is_room = R_DEADEND;
55632689Sbostic dungeon[srow][scol] = TUNNEL;
55732689Sbostic
55832689Sbostic for (i = 0; i < 4; i++) {
55932689Sbostic de = rn + offsets[i];
56032689Sbostic if (((de < 0) || (de >= MAXROOMS)) ||
56132689Sbostic (!(same_row(rn, de) || same_col(rn, de)))) {
56232689Sbostic continue;
56332689Sbostic }
56432689Sbostic if (!(rooms[de].is_room & R_NOTHING)) {
56532689Sbostic continue;
56632689Sbostic }
56732689Sbostic drow = (rooms[de].top_row + rooms[de].bottom_row) / 2;
56832689Sbostic dcol = (rooms[de].left_col + rooms[de].right_col) / 2;
56932689Sbostic if (same_row(rn, de)) {
57032689Sbostic tunnel_dir = (rooms[rn].left_col < rooms[de].left_col) ?
57132689Sbostic RIGHT : LEFT;
57232689Sbostic } else {
57332689Sbostic tunnel_dir = (rooms[rn].top_row < rooms[de].top_row) ?
57432689Sbostic DOWN : UPWARD;
57532689Sbostic }
57632689Sbostic draw_simple_passage(srow, scol, drow, dcol, tunnel_dir);
57732689Sbostic r_de = de;
57832689Sbostic recursive_deadend(de, offsets, drow, dcol);
57932689Sbostic }
58032689Sbostic }
58132689Sbostic
58232689Sbostic boolean
mask_room(rn,row,col,mask)58332689Sbostic mask_room(rn, row, col, mask)
58432689Sbostic short rn;
58532689Sbostic short *row, *col;
58632689Sbostic unsigned short mask;
58732689Sbostic {
58832689Sbostic short i, j;
58932689Sbostic
59032689Sbostic for (i = rooms[rn].top_row; i <= rooms[rn].bottom_row; i++) {
59132689Sbostic for (j = rooms[rn].left_col; j <= rooms[rn].right_col; j++) {
59232689Sbostic if (dungeon[i][j] & mask) {
59332689Sbostic *row = i;
59432689Sbostic *col = j;
59532689Sbostic return(1);
59632689Sbostic }
59732689Sbostic }
59832689Sbostic }
59932689Sbostic return(0);
60032689Sbostic }
60132689Sbostic
make_maze(r,c,tr,br,lc,rc)60232689Sbostic make_maze(r, c, tr, br, lc, rc)
60332689Sbostic short r, c, tr, br, lc, rc;
60432689Sbostic {
60532689Sbostic char dirs[4];
60632689Sbostic short i, t;
60732689Sbostic
60832689Sbostic dirs[0] = UPWARD;
60932689Sbostic dirs[1] = DOWN;
61032689Sbostic dirs[2] = LEFT;
61132689Sbostic dirs[3] = RIGHT;
61232689Sbostic
61332689Sbostic dungeon[r][c] = TUNNEL;
61432689Sbostic
61532689Sbostic if (rand_percent(20)) {
61632689Sbostic for (i = 0; i < 10; i++) {
61732689Sbostic short t1, t2;
61832689Sbostic
61932689Sbostic t1 = get_rand(0, 3);
62032689Sbostic t2 = get_rand(0, 3);
62132689Sbostic
62232689Sbostic swap(dirs[t1], dirs[t2]);
62332689Sbostic }
62432689Sbostic }
62532689Sbostic for (i = 0; i < 4; i++) {
62632689Sbostic switch(dirs[i]) {
62732689Sbostic case UPWARD:
62832689Sbostic if (((r-1) >= tr) &&
62932689Sbostic (dungeon[r-1][c] != TUNNEL) &&
63032689Sbostic (dungeon[r-1][c-1] != TUNNEL) &&
63132689Sbostic (dungeon[r-1][c+1] != TUNNEL) &&
63232689Sbostic (dungeon[r-2][c] != TUNNEL)) {
63332689Sbostic make_maze((r-1), c, tr, br, lc, rc);
63432689Sbostic }
63532689Sbostic break;
63632689Sbostic case DOWN:
63732689Sbostic if (((r+1) <= br) &&
63832689Sbostic (dungeon[r+1][c] != TUNNEL) &&
63932689Sbostic (dungeon[r+1][c-1] != TUNNEL) &&
64032689Sbostic (dungeon[r+1][c+1] != TUNNEL) &&
64132689Sbostic (dungeon[r+2][c] != TUNNEL)) {
64232689Sbostic make_maze((r+1), c, tr, br, lc, rc);
64332689Sbostic }
64432689Sbostic break;
64532689Sbostic case LEFT:
64632689Sbostic if (((c-1) >= lc) &&
64732689Sbostic (dungeon[r][c-1] != TUNNEL) &&
64832689Sbostic (dungeon[r-1][c-1] != TUNNEL) &&
64932689Sbostic (dungeon[r+1][c-1] != TUNNEL) &&
65032689Sbostic (dungeon[r][c-2] != TUNNEL)) {
65132689Sbostic make_maze(r, (c-1), tr, br, lc, rc);
65232689Sbostic }
65332689Sbostic break;
65432689Sbostic case RIGHT:
65532689Sbostic if (((c+1) <= rc) &&
65632689Sbostic (dungeon[r][c+1] != TUNNEL) &&
65732689Sbostic (dungeon[r-1][c+1] != TUNNEL) &&
65832689Sbostic (dungeon[r+1][c+1] != TUNNEL) &&
65932689Sbostic (dungeon[r][c+2] != TUNNEL)) {
66032689Sbostic make_maze(r, (c+1), tr, br, lc, rc);
66132689Sbostic }
66232689Sbostic break;
66332689Sbostic }
66432689Sbostic }
66532689Sbostic }
66632689Sbostic
hide_boxed_passage(row1,col1,row2,col2,n)66732689Sbostic hide_boxed_passage(row1, col1, row2, col2, n)
66832689Sbostic short row1, col1, row2, col2, n;
66932689Sbostic {
67032689Sbostic short i, j, t;
67132689Sbostic short row, col, row_cut, col_cut;
67232689Sbostic short h, w;
67332689Sbostic
67432689Sbostic if (cur_level > 2) {
67532689Sbostic if (row1 > row2) {
67632689Sbostic swap(row1, row2);
67732689Sbostic }
67832689Sbostic if (col1 > col2) {
67932689Sbostic swap(col1, col2);
68032689Sbostic }
68132689Sbostic h = row2 - row1;
68232689Sbostic w = col2 - col1;
68332689Sbostic
68432689Sbostic if ((w >= 5) || (h >= 5)) {
68532689Sbostic row_cut = ((h >= 2) ? 1 : 0);
68632689Sbostic col_cut = ((w >= 2) ? 1 : 0);
68732689Sbostic
68832689Sbostic for (i = 0; i < n; i++) {
68932689Sbostic for (j = 0; j < 10; j++) {
69032689Sbostic row = get_rand(row1 + row_cut, row2 - row_cut);
69132689Sbostic col = get_rand(col1 + col_cut, col2 - col_cut);
69232689Sbostic if (dungeon[row][col] == TUNNEL) {
69332689Sbostic dungeon[row][col] |= HIDDEN;
69432689Sbostic break;
69532689Sbostic }
69632689Sbostic }
69732689Sbostic }
69832689Sbostic }
69932689Sbostic }
70032689Sbostic }
70132689Sbostic
put_player(nr)70232689Sbostic put_player(nr)
70332689Sbostic short nr; /* try not to put in this room */
70432689Sbostic {
70532689Sbostic short rn = nr, misses;
70632689Sbostic short row, col;
70732689Sbostic
70832689Sbostic for (misses = 0; ((misses < 2) && (rn == nr)); misses++) {
70932689Sbostic gr_row_col(&row, &col, (FLOOR | TUNNEL | OBJECT | STAIRS));
71032689Sbostic rn = get_room_number(row, col);
71132689Sbostic }
71232689Sbostic rogue.row = row;
71332689Sbostic rogue.col = col;
71432689Sbostic
71532689Sbostic if (dungeon[rogue.row][rogue.col] & TUNNEL) {
71632689Sbostic cur_room = PASSAGE;
71732689Sbostic } else {
71832689Sbostic cur_room = rn;
71932689Sbostic }
72032689Sbostic if (cur_room != PASSAGE) {
72132689Sbostic light_up_room(cur_room);
72232689Sbostic } else {
72332689Sbostic light_passage(rogue.row, rogue.col);
72432689Sbostic }
72532689Sbostic rn = get_room_number(rogue.row, rogue.col);
72632689Sbostic wake_room(rn, 1, rogue.row, rogue.col);
72732689Sbostic if (new_level_message) {
72832689Sbostic message(new_level_message, 0);
72932689Sbostic new_level_message = 0;
73032689Sbostic }
73132689Sbostic mvaddch(rogue.row, rogue.col, rogue.fchar);
73232689Sbostic }
73332689Sbostic
drop_check()73432689Sbostic drop_check()
73532689Sbostic {
73632689Sbostic if (wizard) {
73732689Sbostic return(1);
73832689Sbostic }
73932689Sbostic if (dungeon[rogue.row][rogue.col] & STAIRS) {
74032689Sbostic if (levitate) {
74132689Sbostic message("you're floating in the air!", 0);
74232689Sbostic return(0);
74332689Sbostic }
74432689Sbostic return(1);
74532689Sbostic }
74632689Sbostic message("I see no way down", 0);
74732689Sbostic return(0);
74832689Sbostic }
74932689Sbostic
check_up()75032689Sbostic check_up()
75132689Sbostic {
75232689Sbostic if (!wizard) {
75332689Sbostic if (!(dungeon[rogue.row][rogue.col] & STAIRS)) {
75432689Sbostic message("I see no way up", 0);
75532689Sbostic return(0);
75632689Sbostic }
75732689Sbostic if (!has_amulet()) {
75832689Sbostic message("your way is magically blocked", 0);
75932689Sbostic return(0);
76032689Sbostic }
76132689Sbostic }
76232689Sbostic new_level_message = "you feel a wrenching sensation in your gut";
76332689Sbostic if (cur_level == 1) {
76432689Sbostic win();
76532689Sbostic } else {
76632689Sbostic cur_level -= 2;
76732689Sbostic return(1);
76832689Sbostic }
76932689Sbostic return(0);
77032689Sbostic }
77132689Sbostic
add_exp(e,promotion)77232689Sbostic add_exp(e, promotion)
77332689Sbostic int e;
77432689Sbostic boolean promotion;
77532689Sbostic {
77632689Sbostic char mbuf[40];
77732689Sbostic short new_exp;
77832689Sbostic short i, hp;
77932689Sbostic
78032689Sbostic rogue.exp_points += e;
78132689Sbostic
78232689Sbostic if (rogue.exp_points >= level_points[rogue.exp-1]) {
78332689Sbostic new_exp = get_exp_level(rogue.exp_points);
78432689Sbostic if (rogue.exp_points > MAX_EXP) {
78532689Sbostic rogue.exp_points = MAX_EXP + 1;
78632689Sbostic }
78732689Sbostic for (i = rogue.exp+1; i <= new_exp; i++) {
78832689Sbostic sprintf(mbuf, "welcome to level %d", i);
78932689Sbostic message(mbuf, 0);
79032689Sbostic if (promotion) {
79132689Sbostic hp = hp_raise();
79232689Sbostic rogue.hp_current += hp;
79332689Sbostic rogue.hp_max += hp;
79432689Sbostic }
79532689Sbostic rogue.exp = i;
79632689Sbostic print_stats(STAT_HP | STAT_EXP);
79732689Sbostic }
79832689Sbostic } else {
79932689Sbostic print_stats(STAT_EXP);
80032689Sbostic }
80132689Sbostic }
80232689Sbostic
get_exp_level(e)80332689Sbostic get_exp_level(e)
80432689Sbostic long e;
80532689Sbostic {
80632689Sbostic short i;
80732689Sbostic
80832689Sbostic for (i = 0; i < (MAX_EXP_LEVEL - 1); i++) {
80932689Sbostic if (level_points[i] > e) {
81032689Sbostic break;
81132689Sbostic }
81232689Sbostic }
81332689Sbostic return(i+1);
81432689Sbostic }
81532689Sbostic
hp_raise()81632689Sbostic hp_raise()
81732689Sbostic {
81832689Sbostic int hp;
81932689Sbostic
82032689Sbostic hp = (wizard ? 10 : get_rand(3, 10));
82132689Sbostic return(hp);
82232689Sbostic }
82332689Sbostic
show_average_hp()82432689Sbostic show_average_hp()
82532689Sbostic {
82632689Sbostic char mbuf[80];
82732689Sbostic float real_average;
82832689Sbostic float effective_average;
82932689Sbostic
83032689Sbostic if (rogue.exp == 1) {
83132689Sbostic real_average = effective_average = 0.00;
83232689Sbostic } else {
83332689Sbostic real_average = (float)
83432689Sbostic ((rogue.hp_max - extra_hp - INIT_HP) + less_hp) / (rogue.exp - 1);
83532689Sbostic effective_average = (float) (rogue.hp_max - INIT_HP) / (rogue.exp - 1);
83632689Sbostic
83732689Sbostic }
83832689Sbostic sprintf(mbuf, "R-Hp: %.2f, E-Hp: %.2f (!: %d, V: %d)", real_average,
83932689Sbostic effective_average, extra_hp, less_hp);
84032689Sbostic message(mbuf, 0);
84132689Sbostic }
84232689Sbostic
mix_random_rooms()84332689Sbostic mix_random_rooms()
84432689Sbostic {
84532689Sbostic short i, t;
84632689Sbostic short x, y;
84732689Sbostic
84832689Sbostic for (i = 0; i < (3 * MAXROOMS); i++) {
84932689Sbostic do {
85032689Sbostic x = get_rand(0, (MAXROOMS-1));
85132689Sbostic y = get_rand(0, (MAXROOMS-1));
85232689Sbostic } while (x == y);
85332689Sbostic swap(random_rooms[x], random_rooms[y]);
85432689Sbostic }
85532689Sbostic }
856