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