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 } 614