home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / games / rogue / move.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-04-08  |  12.6 KB  |  648 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[] = "@(#)move.c    5.3 (Berkeley) 6/1/90";
  39. #endif /* not lint */
  40.  
  41. /*
  42.  * move.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. short m_moves = 0;
  56. boolean jump = 0;
  57. char *you_can_move_again = "you can move again";
  58.  
  59. extern short cur_room, halluc, blind, levitate;
  60. extern short cur_level, max_level;
  61. extern short bear_trap, haste_self, confused;
  62. extern short e_rings, regeneration, auto_search;
  63. extern char hunger_str[];
  64. extern boolean being_held, interrupted, r_teleport, passgo;
  65.  
  66. one_move_rogue(dirch, pickup)
  67. short dirch, pickup;
  68. {
  69.     short row, col;
  70.     object *obj;
  71.     char desc[DCOLS];
  72.     short n, status, d;
  73.  
  74.     row = rogue.row;
  75.     col = rogue.col;
  76.  
  77.     if (confused) {
  78.         dirch = gr_dir();
  79.     }
  80.     (void) is_direction(dirch, &d);
  81.     get_dir_rc(d, &row, &col, 1);
  82.  
  83.     if (!can_move(rogue.row, rogue.col, row, col)) {
  84.         return(MOVE_FAILED);
  85.     }
  86.     if (being_held || bear_trap) {
  87.         if (!(dungeon[row][col] & MONSTER)) {
  88.             if (being_held) {
  89.                 message("you are being held", 1);
  90.             } else {
  91.                 message("you are still stuck in the bear trap", 0);
  92.                 (void) reg_move();
  93.             }
  94.             return(MOVE_FAILED);
  95.         }
  96.     }
  97.     if (r_teleport) {
  98.         if (rand_percent(R_TELE_PERCENT)) {
  99.             tele();
  100.             return(STOPPED_ON_SOMETHING);
  101.         }
  102.     }
  103.     if (dungeon[row][col] & MONSTER) {
  104.         rogue_hit(object_at(&level_monsters, row, col), 0);
  105.         (void) reg_move();
  106.         return(MOVE_FAILED);
  107.     }
  108.     if (dungeon[row][col] & DOOR) {
  109.         if (cur_room == PASSAGE) {
  110.             cur_room = get_room_number(row, col);
  111.             light_up_room(cur_room);
  112.             wake_room(cur_room, 1, row, col);
  113.         } else {
  114.             light_passage(row, col);
  115.         }
  116.     } else if ((dungeon[rogue.row][rogue.col] & DOOR) &&
  117.            (dungeon[row][col] & TUNNEL)) {
  118.         light_passage(row, col);
  119.         wake_room(cur_room, 0, rogue.row, rogue.col);
  120.         darken_room(cur_room);
  121.         cur_room = PASSAGE;
  122.     } else if (dungeon[row][col] & TUNNEL) {
  123.             light_passage(row, col);
  124.     }
  125.     mvaddch(rogue.row, rogue.col, get_dungeon_char(rogue.row, rogue.col));
  126.     mvaddch(row, col, rogue.fchar);
  127.  
  128.     if (!jump) {
  129.         refresh();
  130.     }
  131.     rogue.row = row;
  132.     rogue.col = col;
  133.     if (dungeon[row][col] & OBJECT) {
  134.         if (levitate && pickup) {
  135.             return(STOPPED_ON_SOMETHING);
  136.         }
  137.         if (pickup && !levitate) {
  138.             if (obj = pick_up(row, col, &status)) {
  139.                 get_desc(obj, desc);
  140.                 if (obj->what_is == GOLD) {
  141.                     free_object(obj);
  142.                     goto NOT_IN_PACK;
  143.                 }
  144.             } else if (!status) {
  145.                 goto MVED;
  146.             } else {
  147.                 goto MOVE_ON;
  148.             }
  149.         } else {
  150. MOVE_ON:
  151.             obj = object_at(&level_objects, row, col);
  152.             (void) strcpy(desc, "moved onto ");
  153.             get_desc(obj, desc+11);
  154.             goto NOT_IN_PACK;
  155.         }
  156.         n = strlen(desc);
  157.         desc[n] = '(';
  158.         desc[n+1] = obj->ichar;
  159.         desc[n+2] = ')';
  160.         desc[n+3] = 0;
  161. NOT_IN_PACK:
  162.         message(desc, 1);
  163.         (void) reg_move();
  164.         return(STOPPED_ON_SOMETHING);
  165.     }
  166.     if (dungeon[row][col] & (DOOR | STAIRS | TRAP)) {
  167.         if ((!levitate) && (dungeon[row][col] & TRAP)) {
  168.             trap_player(row, col);
  169.         }
  170.         (void) reg_move();
  171.         return(STOPPED_ON_SOMETHING);
  172.     }
  173. MVED:    if (reg_move()) {            /* fainted from hunger */
  174.             return(STOPPED_ON_SOMETHING);
  175.     }
  176.     return((confused ? STOPPED_ON_SOMETHING : MOVED));
  177. }
  178.  
  179. multiple_move_rogue(dirch)
  180. short dirch;
  181. {
  182.     short row, col;
  183.     short m;
  184.  
  185.     switch(dirch) {
  186.     case '\010':
  187.     case '\012':
  188.     case '\013':
  189.     case '\014':
  190.     case '\031':
  191.     case '\025':
  192.     case '\016':
  193.     case '\002':
  194.         do {
  195.             row = rogue.row;
  196.             col = rogue.col;
  197.             if (((m = one_move_rogue((dirch + 96), 1)) == MOVE_FAILED) ||
  198.                 (m == STOPPED_ON_SOMETHING) ||
  199.                 interrupted) {
  200.                 break;
  201.             }
  202.         } while (!next_to_something(row, col));
  203.         if (    (!interrupted) && passgo && (m == MOVE_FAILED) &&
  204.                 (dungeon[rogue.row][rogue.col] & TUNNEL)) {
  205.             turn_passage(dirch + 96, 0);
  206.         }
  207.         break;
  208.     case 'H':
  209.     case 'J':
  210.     case 'K':
  211.     case 'L':
  212.     case 'B':
  213.     case 'Y':
  214.     case 'U':
  215.     case 'N':
  216.         while ((!interrupted) && (one_move_rogue((dirch + 32), 1) == MOVED)) ;
  217.  
  218.         if (    (!interrupted) && passgo &&
  219.                 (dungeon[rogue.row][rogue.col] & TUNNEL)) {
  220.             turn_passage(dirch + 32, 1);
  221.         }
  222.         break;
  223.     }
  224. }
  225.  
  226. is_passable(row, col)
  227. register row, col;
  228. {
  229.     if ((row < MIN_ROW) || (row > (DROWS - 2)) || (col < 0) ||
  230.         (col > (DCOLS-1))) {
  231.         return(0);
  232.     }
  233.     if (dungeon[row][col] & HIDDEN) {
  234.         return((dungeon[row][col] & TRAP) ? 1 : 0);
  235.     }
  236.     return(dungeon[row][col] & (FLOOR | TUNNEL | DOOR | STAIRS | TRAP));
  237. }
  238.  
  239. next_to_something(drow, dcol)
  240. register drow, dcol;
  241. {
  242.     short i, j, i_end, j_end, row, col;
  243.     short pass_count = 0;
  244.     unsigned short s;
  245.  
  246.     if (confused) {
  247.         return(1);
  248.     }
  249.     if (blind) {
  250.         return(0);
  251.     }
  252.     i_end = (rogue.row < (DROWS-2)) ? 1 : 0;
  253.     j_end = (rogue.col < (DCOLS-1)) ? 1 : 0;
  254.  
  255.     for (i = ((rogue.row > MIN_ROW) ? -1 : 0); i <= i_end; i++) {
  256.         for (j = ((rogue.col > 0) ? -1 : 0); j <= j_end; j++) {
  257.             if ((i == 0) && (j == 0)) {
  258.                 continue;
  259.             }
  260.             if (((rogue.row+i) == drow) && ((rogue.col+j) == dcol)) {
  261.                 continue;
  262.             }
  263.             row = rogue.row + i;
  264.             col = rogue.col + j;
  265.             s = dungeon[row][col];
  266.             if (s & HIDDEN) {
  267.                 continue;
  268.             }
  269.             /* If the rogue used to be right, up, left, down, or right of
  270.              * row,col, and now isn't, then don't stop */
  271.             if (s & (MONSTER | OBJECT | STAIRS)) {
  272.                 if (((row == drow) || (col == dcol)) &&
  273.                     (!((row == rogue.row) || (col == rogue.col)))) {
  274.                     continue;
  275.                 }
  276.                 return(1);
  277.             }
  278.             if (s & TRAP) {
  279.                 if (!(s & HIDDEN)) {
  280.                     if (((row == drow) || (col == dcol)) &&
  281.                         (!((row == rogue.row) || (col == rogue.col)))) {
  282.                         continue;
  283.                     }
  284.                     return(1);
  285.                 }
  286.             }
  287.             if ((((i - j) == 1) || ((i - j) == -1)) && (s & TUNNEL)) {
  288.                 if (++pass_count > 1) {
  289.                     return(1);
  290.                 }
  291.             }
  292.             if ((s & DOOR) && ((i == 0) || (j == 0))) {
  293.                     return(1);
  294.             }
  295.         }
  296.     }
  297.     return(0);
  298. }
  299.  
  300. can_move(row1, col1, row2, col2) 
  301. {
  302.     if (!is_passable(row2, col2)) {
  303.         return(0);
  304.     }
  305.     if ((row1 != row2) && (col1 != col2)) {
  306.         if ((dungeon[row1][col1] & DOOR) || (dungeon[row2][col2] & DOOR)) {
  307.             return(0);
  308.         }
  309.         if ((!dungeon[row1][col2]) || (!dungeon[row2][col1])) {
  310.             return(0);
  311.         }
  312.     }
  313.     return(1);
  314. }
  315.  
  316. move_onto()
  317. {
  318.     short ch, d;
  319.     boolean first_miss = 1;
  320.  
  321.     while (!is_direction(ch = rgetchar(), &d)) {
  322.         sound_bell();
  323.         if (first_miss) {
  324.             message("direction? ", 0);
  325.             first_miss = 0;
  326.         }
  327.     }
  328.     check_message();
  329.     if (ch != CANCEL) {
  330.         (void) one_move_rogue(ch, 0);
  331.     }
  332. }
  333.  
  334. boolean
  335. is_direction(c, d)
  336. short c;
  337. short *d;
  338. {
  339.     switch(c) {
  340.     case 'h':
  341.         *d = LEFT;
  342.         break;
  343.     case 'j':
  344.         *d = DOWN;
  345.         break;
  346.     case 'k':
  347.         *d = UPWARD;
  348.         break;
  349.     case 'l':
  350.         *d = RIGHT;
  351.         break;
  352.     case 'b':
  353.         *d = DOWNLEFT;
  354.         break;
  355.     case 'y':
  356.         *d = UPLEFT;
  357.         break;
  358.     case 'u':
  359.         *d = UPRIGHT;
  360.         break;
  361.     case 'n':
  362.         *d = DOWNRIGHT;
  363.         break;
  364.     case CANCEL:
  365.         break;
  366.     default:
  367.         return(0);
  368.     }
  369.     return(1);
  370. }
  371.  
  372. boolean
  373. check_hunger(msg_only)
  374. boolean msg_only;
  375. {
  376.     register short i, n;
  377.     boolean fainted = 0;
  378.  
  379.     if (rogue.moves_left == HUNGRY) {
  380.         (void) strcpy(hunger_str, "hungry");
  381.         message(hunger_str, 0);
  382.         print_stats(STAT_HUNGER);
  383.     }
  384.     if (rogue.moves_left == WEAK) {
  385.         (void) strcpy(hunger_str, "weak");
  386.         message(hunger_str, 1);
  387.         print_stats(STAT_HUNGER);
  388.     }
  389.     if (rogue.moves_left <= FAINT) {
  390.         if (rogue.moves_left == FAINT) {
  391.             (void) strcpy(hunger_str, "faint");
  392.             message(hunger_str, 1);
  393.             print_stats(STAT_HUNGER);
  394.         }
  395.         n = get_rand(0, (FAINT - rogue.moves_left));
  396.         if (n > 0) {
  397.             fainted = 1;
  398.             if (rand_percent(40)) {
  399.                 rogue.moves_left++;
  400.             }
  401.             message("you faint", 1);
  402.             for (i = 0; i < n; i++) {
  403.                 if (coin_toss()) {
  404.                     mv_mons();
  405.                 }
  406.             }
  407.             message(you_can_move_again, 1);
  408.         }
  409.     }
  410.     if (msg_only) {
  411.         return(fainted);
  412.     }
  413.     if (rogue.moves_left <= STARVE) {
  414.         killed_by((object *) 0, STARVATION);
  415.     }
  416.  
  417.     switch(e_rings) {
  418.     /*case -2:
  419.         Subtract 0, i.e. do nothing.
  420.         break;*/
  421.     case -1:
  422.         rogue.moves_left -= (rogue.moves_left % 2);
  423.         break;
  424.     case 0:
  425.         rogue.moves_left--;
  426.         break;
  427.     case 1:
  428.         rogue.moves_left--;
  429.         (void) check_hunger(1);
  430.         rogue.moves_left -= (rogue.moves_left % 2);
  431.         break;
  432.     case 2:
  433.         rogue.moves_left--;
  434.         (void) check_hunger(1);
  435.         rogue.moves_left--;
  436.         break;
  437.     }
  438.     return(fainted);
  439. }
  440.  
  441. boolean
  442. reg_move()
  443. {
  444.     boolean fainted;
  445.  
  446.     if ((rogue.moves_left <= HUNGRY) || (cur_level >= max_level)) {
  447.         fainted = check_hunger(0);
  448.     } else {
  449.         fainted = 0;
  450.     }
  451.  
  452.     mv_mons();
  453.  
  454.     if (++m_moves >= 120) {
  455.         m_moves = 0;
  456.         wanderer();
  457.     }
  458.     if (halluc) {
  459.         if (!(--halluc)) {
  460.             unhallucinate();
  461.         } else {
  462.             hallucinate();
  463.         }
  464.     }
  465.     if (blind) {
  466.         if (!(--blind)) {
  467.             unblind();
  468.         }
  469.     }
  470.     if (confused) {
  471.         if (!(--confused)) {
  472.             unconfuse();
  473.         }
  474.     }
  475.     if (bear_trap) {
  476.         bear_trap--;
  477.     }
  478.     if (levitate) {
  479.         if (!(--levitate)) {
  480.             message("you float gently to the ground", 1);
  481.             if (dungeon[rogue.row][rogue.col] & TRAP) {
  482.                 trap_player(rogue.row, rogue.col);
  483.             }
  484.         }
  485.     }
  486.     if (haste_self) {
  487.         if (!(--haste_self)) {
  488.             message("you feel yourself slowing down", 0);
  489.         }
  490.     }
  491.     heal();
  492.     if (auto_search > 0) {
  493.         search(auto_search, auto_search);
  494.     }
  495.     return(fainted);
  496. }
  497.  
  498. rest(count)
  499. {
  500.     int i;
  501.  
  502.     interrupted = 0;
  503.  
  504.     for (i = 0; i < count; i++) {
  505.         if (interrupted) {
  506.             break;
  507.         }
  508.         (void) reg_move();
  509.     }
  510. }
  511.  
  512. gr_dir()
  513. {
  514.     short d;
  515.  
  516.     d = get_rand(1, 8);
  517.  
  518.     switch(d) {
  519.         case 1:
  520.             d = 'j';
  521.             break;
  522.         case 2:
  523.             d = 'k';
  524.             break;
  525.         case 3:
  526.             d = 'l';
  527.             break;
  528.         case 4:
  529.             d = 'h';
  530.             break;
  531.         case 5:
  532.             d = 'y';
  533.             break;
  534.         case 6:
  535.             d = 'u';
  536.             break;
  537.         case 7:
  538.             d = 'b';
  539.             break;
  540.         case 8:
  541.             d = 'n';
  542.             break;
  543.     }
  544.     return(d);
  545. }
  546.  
  547. heal()
  548. {
  549.     static short heal_exp = -1, n, c = 0;
  550.     static boolean alt;
  551.  
  552.     if (rogue.hp_current == rogue.hp_max) {
  553.         c = 0;
  554.         return;
  555.     }
  556.     if (rogue.exp != heal_exp) {
  557.         heal_exp = rogue.exp;
  558.  
  559.         switch(heal_exp) {
  560.         case 1:
  561.             n = 20;
  562.             break;
  563.         case 2:
  564.             n = 18;
  565.             break;
  566.         case 3:
  567.             n = 17;
  568.             break;
  569.         case 4:
  570.             n = 14;
  571.             break;
  572.         case 5:
  573.             n = 13;
  574.             break;
  575.         case 6:
  576.             n = 10;
  577.             break;
  578.         case 7:
  579.             n = 9;
  580.             break;
  581.         case 8:
  582.             n = 8;
  583.             break;
  584.         case 9:
  585.             n = 7;
  586.             break;
  587.         case 10:
  588.             n = 4;
  589.             break;
  590.         case 11:
  591.             n = 3;
  592.             break;
  593.         case 12:
  594.         default:
  595.             n = 2;
  596.         }
  597.     }
  598.     if (++c >= n) {
  599.         c = 0;
  600.         rogue.hp_current++;
  601.         if (alt = !alt) {
  602.             rogue.hp_current++;
  603.         }
  604.         if ((rogue.hp_current += regeneration) > rogue.hp_max) {
  605.             rogue.hp_current = rogue.hp_max;
  606.         }
  607.         print_stats(STAT_HP);
  608.     }
  609. }
  610.  
  611. static boolean
  612. can_turn(nrow, ncol)
  613. short nrow, ncol;
  614. {
  615.     if ((dungeon[nrow][ncol] & TUNNEL) && is_passable(nrow, ncol)) {
  616.         return(1);
  617.     }
  618.     return(0);
  619. }
  620.  
  621. turn_passage(dir, fast)
  622. short dir;
  623. boolean fast;
  624. {
  625.     short crow = rogue.row, ccol = rogue.col, turns = 0;
  626.     short ndir;
  627.  
  628.     if ((dir != 'h') && can_turn(crow, ccol + 1)) {
  629.         turns++;
  630.         ndir = 'l';
  631.     }
  632.     if ((dir != 'l') && can_turn(crow, ccol - 1)) {
  633.         turns++;
  634.         ndir = 'h';
  635.     }
  636.     if ((dir != 'k') && can_turn(crow + 1, ccol)) {
  637.         turns++;
  638.         ndir = 'j';
  639.     }
  640.     if ((dir != 'j') && can_turn(crow - 1, ccol)) {
  641.         turns++;
  642.         ndir = 'k';
  643.     }
  644.     if (turns == 1) {
  645.         multiple_move_rogue(ndir - (fast ? 32 : 96));
  646.     }
  647. }
  648.