1: /* 2: * room.c 3: * 4: * This source herein may be modified and/or distributed by anybody who 5: * so desires, with the following restrictions: 6: * 1.) No portion of this notice shall be removed. 7: * 2.) Credit shall not be taken for the creation of this source. 8: * 3.) This code is not to be traded, sold, or used for personal 9: * gain or profit. 10: * 11: */ 12: 13: #ifndef lint 14: static char sccsid[] = "@(#)room.c 5.1 (Berkeley) 11/25/87"; 15: #endif /* not lint */ 16: 17: #include "rogue.h" 18: 19: room rooms[MAXROOMS]; 20: boolean rooms_visited[MAXROOMS]; 21: 22: extern short blind; 23: extern boolean detect_monster, jump, passgo, no_skull, ask_quit; 24: extern char *nick_name, *fruit, *save_file, *press_space; 25: 26: #define NOPTS 7 27: 28: struct option { 29: char *prompt; 30: boolean is_bool; 31: char **strval; 32: boolean *bval; 33: } options[NOPTS] = { 34: { 35: "Show position only at end of run (\"jump\"): ", 36: 1, (char **) 0, &jump 37: }, 38: { 39: "Follow turnings in passageways (\"passgo\"): ", 40: 1, (char **) 0, &passgo 41: }, 42: { 43: "Don't print skull when killed (\"noskull\" or \"notombstone\"): ", 44: 1, (char **) 0, &no_skull 45: }, 46: { 47: "Ask player before saying 'Okay, bye-bye!' (\"askquit\"): ", 48: 1, (char **) 0, &ask_quit 49: }, 50: { 51: "Name (\"name\"): ", 52: 0, &nick_name 53: }, 54: { 55: "Fruit (\"fruit\"): ", 56: 0, &fruit 57: }, 58: { 59: "Save file (\"file\"): ", 60: 0, &save_file 61: } 62: }; 63: 64: light_up_room(rn) 65: int rn; 66: { 67: short i, j; 68: 69: if (!blind) { 70: for (i = rooms[rn].top_row; 71: i <= rooms[rn].bottom_row; i++) { 72: for (j = rooms[rn].left_col; 73: j <= rooms[rn].right_col; j++) { 74: if (dungeon[i][j] & MONSTER) { 75: object *monster; 76: 77: if (monster = object_at(&level_monsters, i, j)) { 78: dungeon[monster->row][monster->col] &= (~MONSTER); 79: monster->trail_char = 80: get_dungeon_char(monster->row, monster->col); 81: dungeon[monster->row][monster->col] |= MONSTER; 82: } 83: } 84: mvaddch(i, j, get_dungeon_char(i, j)); 85: } 86: } 87: mvaddch(rogue.row, rogue.col, rogue.fchar); 88: } 89: } 90: 91: light_passage(row, col) 92: { 93: short i, j, i_end, j_end; 94: 95: if (blind) { 96: return; 97: } 98: i_end = (row < (DROWS-2)) ? 1 : 0; 99: j_end = (col < (DCOLS-1)) ? 1 : 0; 100: 101: for (i = ((row > MIN_ROW) ? -1 : 0); i <= i_end; i++) { 102: for (j = ((col > 0) ? -1 : 0); j <= j_end; j++) { 103: if (can_move(row, col, row+i, col+j)) { 104: mvaddch(row+i, col+j, get_dungeon_char(row+i, col+j)); 105: } 106: } 107: } 108: } 109: 110: darken_room(rn) 111: short rn; 112: { 113: short i, j; 114: 115: for (i = rooms[rn].top_row + 1; i < rooms[rn].bottom_row; i++) { 116: for (j = rooms[rn].left_col + 1; j < rooms[rn].right_col; j++) { 117: if (blind) { 118: mvaddch(i, j, ' '); 119: } else { 120: if (!(dungeon[i][j] & (OBJECT | STAIRS)) && 121: !(detect_monster && (dungeon[i][j] & MONSTER))) { 122: if (!imitating(i, j)) { 123: mvaddch(i, j, ' '); 124: } 125: if ((dungeon[i][j] & TRAP) && (!(dungeon[i][j] & HIDDEN))) { 126: mvaddch(i, j, '^'); 127: } 128: } 129: } 130: } 131: } 132: } 133: 134: get_dungeon_char(row, col) 135: register row, col; 136: { 137: register unsigned short mask = dungeon[row][col]; 138: 139: if (mask & MONSTER) { 140: return(gmc_row_col(row, col)); 141: } 142: if (mask & OBJECT) { 143: object *obj; 144: 145: obj = object_at(&level_objects, row, col); 146: return(get_mask_char(obj->what_is)); 147: } 148: if (mask & (TUNNEL | STAIRS | HORWALL | VERTWALL | FLOOR | DOOR)) { 149: if ((mask & (TUNNEL| STAIRS)) && (!(mask & HIDDEN))) { 150: return(((mask & STAIRS) ? '%' : '#')); 151: } 152: if (mask & HORWALL) { 153: return('-'); 154: } 155: if (mask & VERTWALL) { 156: return('|'); 157: } 158: if (mask & FLOOR) { 159: if (mask & TRAP) { 160: if (!(dungeon[row][col] & HIDDEN)) { 161: return('^'); 162: } 163: } 164: return('.'); 165: } 166: if (mask & DOOR) { 167: if (mask & HIDDEN) { 168: if (((col > 0) && (dungeon[row][col-1] & HORWALL)) || 169: ((col < (DCOLS-1)) && (dungeon[row][col+1] & HORWALL))) { 170: return('-'); 171: } else { 172: return('|'); 173: } 174: } else { 175: return('+'); 176: } 177: } 178: } 179: return(' '); 180: } 181: 182: get_mask_char(mask) 183: register unsigned short mask; 184: { 185: switch(mask) { 186: case SCROL: 187: return('?'); 188: case POTION: 189: return('!'); 190: case GOLD: 191: return('*'); 192: case FOOD: 193: return(':'); 194: case WAND: 195: return('/'); 196: case ARMOR: 197: return(']'); 198: case WEAPON: 199: return(')'); 200: case RING: 201: return('='); 202: case AMULET: 203: return(','); 204: default: 205: return('~'); /* unknown, something is wrong */ 206: } 207: } 208: 209: gr_row_col(row, col, mask) 210: short *row, *col; 211: unsigned short mask; 212: { 213: short rn; 214: short r, c; 215: 216: do { 217: r = get_rand(MIN_ROW, DROWS-2); 218: c = get_rand(0, DCOLS-1); 219: rn = get_room_number(r, c); 220: } while ((rn == NO_ROOM) || 221: (!(dungeon[r][c] & mask)) || 222: (dungeon[r][c] & (~mask)) || 223: (!(rooms[rn].is_room & (R_ROOM | R_MAZE))) || 224: ((r == rogue.row) && (c == rogue.col))); 225: 226: *row = r; 227: *col = c; 228: } 229: 230: gr_room() 231: { 232: short i; 233: 234: do { 235: i = get_rand(0, MAXROOMS-1); 236: } while (!(rooms[i].is_room & (R_ROOM | R_MAZE))); 237: 238: return(i); 239: } 240: 241: party_objects(rn) 242: { 243: short i, j, nf = 0; 244: object *obj; 245: short n, N, row, col; 246: boolean found; 247: 248: N = ((rooms[rn].bottom_row - rooms[rn].top_row) - 1) * 249: ((rooms[rn].right_col - rooms[rn].left_col) - 1); 250: n = get_rand(5, 10); 251: if (n > N) { 252: n = N - 2; 253: } 254: for (i = 0; i < n; i++) { 255: for (j = found = 0; ((!found) && (j < 250)); j++) { 256: row = get_rand(rooms[rn].top_row+1, 257: rooms[rn].bottom_row-1); 258: col = get_rand(rooms[rn].left_col+1, 259: rooms[rn].right_col-1); 260: if ((dungeon[row][col] == FLOOR) || (dungeon[row][col] == TUNNEL)) { 261: found = 1; 262: } 263: } 264: if (found) { 265: obj = gr_object(); 266: place_at(obj, row, col); 267: nf++; 268: } 269: } 270: return(nf); 271: } 272: 273: get_room_number(row, col) 274: register row, col; 275: { 276: short i; 277: 278: for (i = 0; i < MAXROOMS; i++) { 279: if ((row >= rooms[i].top_row) && (row <= rooms[i].bottom_row) && 280: (col >= rooms[i].left_col) && (col <= rooms[i].right_col)) { 281: return(i); 282: } 283: } 284: return(NO_ROOM); 285: } 286: 287: is_all_connected() 288: { 289: short i, starting_room; 290: 291: for (i = 0; i < MAXROOMS; i++) { 292: rooms_visited[i] = 0; 293: if (rooms[i].is_room & (R_ROOM | R_MAZE)) { 294: starting_room = i; 295: } 296: } 297: 298: visit_rooms(starting_room); 299: 300: for (i = 0; i < MAXROOMS; i++) { 301: if ((rooms[i].is_room & (R_ROOM | R_MAZE)) && (!rooms_visited[i])) { 302: return(0); 303: } 304: } 305: return(1); 306: } 307: 308: visit_rooms(rn) 309: int rn; 310: { 311: short i; 312: short oth_rn; 313: 314: rooms_visited[rn] = 1; 315: 316: for (i = 0; i < 4; i++) { 317: oth_rn = rooms[rn].doors[i].oth_room; 318: if ((oth_rn >= 0) && (!rooms_visited[oth_rn])) { 319: visit_rooms(oth_rn); 320: } 321: } 322: } 323: 324: draw_magic_map() 325: { 326: short i, j, ch, och; 327: unsigned short mask = (HORWALL | VERTWALL | DOOR | TUNNEL | TRAP | STAIRS | 328: MONSTER); 329: unsigned short s; 330: 331: for (i = 0; i < DROWS; i++) { 332: for (j = 0; j < DCOLS; j++) { 333: s = dungeon[i][j]; 334: if (s & mask) { 335: if (((ch = mvinch(i, j)) == ' ') || 336: ((ch >= 'A') && (ch <= 'Z')) || (s & (TRAP | HIDDEN))) { 337: och = ch; 338: dungeon[i][j] &= (~HIDDEN); 339: if (s & HORWALL) { 340: ch = '-'; 341: } else if (s & VERTWALL) { 342: ch = '|'; 343: } else if (s & DOOR) { 344: ch = '+'; 345: } else if (s & TRAP) { 346: ch = '^'; 347: } else if (s & STAIRS) { 348: ch = '%'; 349: } else if (s & TUNNEL) { 350: ch = '#'; 351: } else { 352: continue; 353: } 354: if ((!(s & MONSTER)) || (och == ' ')) { 355: addch(ch); 356: } 357: if (s & MONSTER) { 358: object *monster; 359: 360: if (monster = object_at(&level_monsters, i, j)) { 361: monster->trail_char = ch; 362: } 363: } 364: } 365: } 366: } 367: } 368: } 369: 370: dr_course(monster, entering, row, col) 371: object *monster; 372: boolean entering; 373: short row, col; 374: { 375: short i, j, k, rn; 376: short r, rr; 377: 378: monster->row = row; 379: monster->col = col; 380: 381: if (mon_sees(monster, rogue.row, rogue.col)) { 382: monster->trow = NO_ROOM; 383: return; 384: } 385: rn = get_room_number(row, col); 386: 387: if (entering) { /* entering room */ 388: /* look for door to some other room */ 389: r = get_rand(0, MAXROOMS-1); 390: for (i = 0; i < MAXROOMS; i++) { 391: rr = (r + i) % MAXROOMS; 392: if ((!(rooms[rr].is_room & (R_ROOM | R_MAZE))) || (rr == rn)) { 393: continue; 394: } 395: for (k = 0; k < 4; k++) { 396: if (rooms[rr].doors[k].oth_room == rn) { 397: monster->trow = rooms[rr].doors[k].oth_row; 398: monster->tcol = rooms[rr].doors[k].oth_col; 399: if ((monster->trow == row) && 400: (monster->tcol == col)) { 401: continue; 402: } 403: return; 404: } 405: } 406: } 407: /* look for door to dead end */ 408: for (i = rooms[rn].top_row; i <= rooms[rn].bottom_row; i++) { 409: for (j = rooms[rn].left_col; j <= rooms[rn].right_col; j++) { 410: if ((i != monster->row) && (j != monster->col) && 411: (dungeon[i][j] & DOOR)) { 412: monster->trow = i; 413: monster->tcol = j; 414: return; 415: } 416: } 417: } 418: /* return monster to room that he came from */ 419: for (i = 0; i < MAXROOMS; i++) { 420: for (j = 0; j < 4; j++) { 421: if (rooms[i].doors[j].oth_room == rn) { 422: for (k = 0; k < 4; k++) { 423: if (rooms[rn].doors[k].oth_room == i) { 424: monster->trow = rooms[rn].doors[k].oth_row; 425: monster->tcol = rooms[rn].doors[k].oth_col; 426: return; 427: } 428: } 429: } 430: } 431: } 432: /* no place to send monster */ 433: monster->trow = NO_ROOM; 434: } else { /* exiting room */ 435: if (!get_oth_room(rn, &row, &col)) { 436: monster->trow = NO_ROOM; 437: } else { 438: monster->trow = row; 439: monster->tcol = col; 440: } 441: } 442: } 443: 444: get_oth_room(rn, row, col) 445: short rn, *row, *col; 446: { 447: short d = -1; 448: 449: if (*row == rooms[rn].top_row) { 450: d = UPWARD/2; 451: } else if (*row == rooms[rn].bottom_row) { 452: d = DOWN/2; 453: } else if (*col == rooms[rn].left_col) { 454: d = LEFT/2; 455: } else if (*col == rooms[rn].right_col) { 456: d = RIGHT/2; 457: } 458: if ((d != -1) && (rooms[rn].doors[d].oth_room >= 0)) { 459: *row = rooms[rn].doors[d].oth_row; 460: *col = rooms[rn].doors[d].oth_col; 461: return(1); 462: } 463: return(0); 464: } 465: 466: edit_opts() 467: { 468: char save[NOPTS+1][DCOLS]; 469: short i, j; 470: short ch; 471: boolean done = 0; 472: char buf[MAX_OPT_LEN + 2]; 473: 474: for (i = 0; i < NOPTS+1; i++) { 475: for (j = 0; j < DCOLS; j++) { 476: save[i][j] = mvinch(i, j); 477: } 478: if (i < NOPTS) { 479: opt_show(i); 480: } 481: } 482: opt_go(0); 483: i = 0; 484: 485: while (!done) { 486: refresh(); 487: ch = rgetchar(); 488: CH: 489: switch(ch) { 490: case '\033': 491: done = 1; 492: break; 493: case '\012': 494: case '\015': 495: if (i == (NOPTS - 1)) { 496: mvaddstr(NOPTS, 0, press_space); 497: refresh(); 498: wait_for_ack(); 499: done = 1; 500: } else { 501: i++; 502: opt_go(i); 503: } 504: break; 505: case '-': 506: if (i > 0) { 507: opt_go(--i); 508: } else { 509: sound_bell(); 510: } 511: break; 512: case 't': 513: case 'T': 514: case 'f': 515: case 'F': 516: if (options[i].is_bool) { 517: *(options[i].bval) = (((ch == 't') || (ch == 'T')) ? 1 : 0); 518: opt_show(i); 519: opt_go(++i); 520: break; 521: } 522: default: 523: if (options[i].is_bool) { 524: sound_bell(); 525: break; 526: } 527: j = 0; 528: if ((ch == '\010') || ((ch >= ' ') && (ch <= '~'))) { 529: opt_erase(i); 530: do { 531: if ((ch >= ' ') && (ch <= '~') && (j < MAX_OPT_LEN)) { 532: buf[j++] = ch; 533: buf[j] = '\0'; 534: addch(ch); 535: } else if ((ch == '\010') && (j > 0)) { 536: buf[--j] = '\0'; 537: move(i, j + strlen(options[i].prompt)); 538: addch(' '); 539: move(i, j + strlen(options[i].prompt)); 540: } 541: refresh(); 542: ch = rgetchar(); 543: } while ((ch != '\012') && (ch != '\015') && (ch != '\033')); 544: if (j != 0) { 545: (void) strcpy(*(options[i].strval), buf); 546: } 547: opt_show(i); 548: goto CH; 549: } else { 550: sound_bell(); 551: } 552: break; 553: } 554: } 555: 556: for (i = 0; i < NOPTS+1; i++) { 557: move(i, 0); 558: for (j = 0; j < DCOLS; j++) { 559: addch(save[i][j]); 560: } 561: } 562: } 563: 564: opt_show(i) 565: int i; 566: { 567: char *s; 568: struct option *opt = &options[i]; 569: 570: opt_erase(i); 571: 572: if (opt->is_bool) { 573: s = *(opt->bval) ? "True" : "False"; 574: } else { 575: s = *(opt->strval); 576: } 577: addstr(s); 578: } 579: 580: opt_erase(i) 581: int i; 582: { 583: struct option *opt = &options[i]; 584: 585: mvaddstr(i, 0, opt->prompt); 586: clrtoeol(); 587: } 588: 589: opt_go(i) 590: int i; 591: { 592: move(i, strlen(options[i].prompt)); 593: } 594: 595: do_shell() 596: { 597: #ifdef UNIX 598: char *sh; 599: 600: md_ignore_signals(); 601: if (!(sh = md_getenv("SHELL"))) { 602: sh = "/bin/sh"; 603: } 604: move(LINES-1, 0); 605: refresh(); 606: stop_window(); 607: printf("\nCreating new shell...\n"); 608: md_shell(sh); 609: start_window(); 610: wrefresh(curscr); 611: md_heed_signals(); 612: #endif 613: }