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