home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / games / rogue / room.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-04-08  |  13.3 KB  |  650 lines

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