home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / games / rogue / spec_hit.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-04-08  |  11.4 KB  |  535 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[] = "@(#)spec_hit.c    5.3 (Berkeley) 6/1/90";
  39. #endif /* not lint */
  40.  
  41. /*
  42.  * special_hit.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 less_hp = 0;
  56. boolean being_held;
  57.  
  58. extern short cur_level, max_level, blind, levitate, ring_exp;
  59. extern long level_points[];
  60. extern boolean detect_monster, mon_disappeared;
  61. extern boolean sustain_strength, maintain_armor;
  62. extern char *you_can_move_again;
  63.  
  64. special_hit(monster)
  65. object *monster;
  66. {
  67.     if ((monster->m_flags & CONFUSED) && rand_percent(66)) {
  68.         return;
  69.     }
  70.     if (monster->m_flags & RUSTS) {
  71.         rust(monster);
  72.     }
  73.     if ((monster->m_flags & HOLDS) && !levitate) {
  74.         being_held = 1;
  75.     }
  76.     if (monster->m_flags & FREEZES) {
  77.         freeze(monster);
  78.     }
  79.     if (monster->m_flags & STINGS) {
  80.         sting(monster);
  81.     }
  82.     if (monster->m_flags & DRAINS_LIFE) {
  83.         drain_life();
  84.     }
  85.     if (monster->m_flags & DROPS_LEVEL) {
  86.         drop_level();
  87.     }
  88.     if (monster->m_flags & STEALS_GOLD) {
  89.         steal_gold(monster);
  90.     } else if (monster->m_flags & STEALS_ITEM) {
  91.         steal_item(monster);
  92.     }
  93. }
  94.  
  95. rust(monster)
  96. object *monster;
  97. {
  98.     if ((!rogue.armor) || (get_armor_class(rogue.armor) <= 1) ||
  99.         (rogue.armor->which_kind == LEATHER)) {
  100.         return;
  101.     }
  102.     if ((rogue.armor->is_protected) || maintain_armor) {
  103.         if (monster && (!(monster->m_flags & RUST_VANISHED))) {
  104.             message("the rust vanishes instantly", 0);
  105.             monster->m_flags |= RUST_VANISHED;
  106.         }
  107.     } else {
  108.         rogue.armor->d_enchant--;
  109.         message("your armor weakens", 0);
  110.         print_stats(STAT_ARMOR);
  111.     }
  112. }
  113.  
  114. freeze(monster)
  115. object *monster;
  116. {
  117.     short freeze_percent = 99;
  118.     short i, n;
  119.  
  120.     if (rand_percent(12)) {
  121.         return;
  122.     }
  123.     freeze_percent -= (rogue.str_current+(rogue.str_current / 2));
  124.     freeze_percent -= ((rogue.exp + ring_exp) * 4);
  125.     freeze_percent -= (get_armor_class(rogue.armor) * 5);
  126.     freeze_percent -= (rogue.hp_max / 3);
  127.  
  128.     if (freeze_percent > 10) {
  129.         monster->m_flags |= FREEZING_ROGUE;
  130.         message("you are frozen", 1);
  131.  
  132.         n = get_rand(4, 8);
  133.         for (i = 0; i < n; i++) {
  134.             mv_mons();
  135.         }
  136.         if (rand_percent(freeze_percent)) {
  137.             for (i = 0; i < 50; i++) {
  138.                 mv_mons();
  139.             }
  140.             killed_by((object *)0, HYPOTHERMIA);
  141.         }
  142.         message(you_can_move_again, 1);
  143.         monster->m_flags &= (~FREEZING_ROGUE);
  144.     }
  145. }
  146.  
  147. steal_gold(monster)
  148. object *monster;
  149. {
  150.     int amount;
  151.  
  152.     if ((rogue.gold <= 0) || rand_percent(10)) {
  153.         return;
  154.     }
  155.  
  156.     amount = get_rand((cur_level * 10), (cur_level * 30));
  157.  
  158.     if (amount > rogue.gold) {
  159.         amount = rogue.gold;
  160.     }
  161.     rogue.gold -= amount;
  162.     message("your purse feels lighter", 0);
  163.     print_stats(STAT_GOLD);
  164.     disappear(monster);
  165. }
  166.  
  167. steal_item(monster)
  168. object *monster;
  169. {
  170.     object *obj;
  171.     short i, n, t;
  172.     char desc[80];
  173.     boolean has_something = 0;
  174.  
  175.     if (rand_percent(15)) {
  176.         return;
  177.     }
  178.     obj = rogue.pack.next_object;
  179.  
  180.     if (!obj) {
  181.         goto DSPR;
  182.     }
  183.     while (obj) {
  184.         if (!(obj->in_use_flags & BEING_USED)) {
  185.             has_something = 1;
  186.             break;
  187.         }
  188.         obj = obj->next_object;
  189.     }
  190.     if (!has_something) {
  191.         goto DSPR;
  192.     }
  193.     n = get_rand(0, MAX_PACK_COUNT);
  194.     obj = rogue.pack.next_object;
  195.  
  196.     for (i = 0; i <= n; i++) {
  197.         obj = obj->next_object;
  198.         while ((!obj) || (obj->in_use_flags & BEING_USED)) {
  199.             if (!obj) {
  200.                 obj = rogue.pack.next_object;
  201.             } else {
  202.                 obj = obj->next_object;
  203.             }
  204.         }
  205.     }
  206.     (void) strcpy(desc, "she stole ");
  207.     if (obj->what_is != WEAPON) {
  208.         t = obj->quantity;
  209.         obj->quantity = 1;
  210.     }
  211.     get_desc(obj, desc+10);
  212.     message(desc, 0);
  213.  
  214.     obj->quantity = ((obj->what_is != WEAPON) ? t : 1);
  215.  
  216.     vanish(obj, 0, &rogue.pack);
  217. DSPR:
  218.     disappear(monster);
  219. }
  220.  
  221. disappear(monster)
  222. object *monster;
  223. {
  224.     short row, col;
  225.  
  226.     row = monster->row;
  227.     col = monster->col;
  228.  
  229.     dungeon[row][col] &= ~MONSTER;
  230.     if (rogue_can_see(row, col)) {
  231.         mvaddch(row, col, get_dungeon_char(row, col));
  232.     }
  233.     take_from_pack(monster, &level_monsters);
  234.     free_object(monster);
  235.     mon_disappeared = 1;
  236. }
  237.  
  238. cough_up(monster)
  239. object *monster;
  240. {
  241.     object *obj;
  242.     short row, col, i, n;
  243.  
  244.     if (cur_level < max_level) {
  245.         return;
  246.     }
  247.  
  248.     if (monster->m_flags & STEALS_GOLD) {
  249.         obj = alloc_object();
  250.         obj->what_is = GOLD;
  251.         obj->quantity = get_rand((cur_level * 15), (cur_level * 30));
  252.     } else {
  253.         if (!rand_percent((int) monster->drop_percent)) {
  254.             return;
  255.         }
  256.         obj = gr_object();
  257.     }
  258.     row = monster->row;
  259.     col = monster->col;
  260.  
  261.     for (n = 0; n <= 5; n++) {
  262.         for (i = -n; i <= n; i++) {
  263.             if (try_to_cough(row+n, col+i, obj)) {
  264.                 return;
  265.             }
  266.             if (try_to_cough(row-n, col+i, obj)) {
  267.                 return;
  268.             }
  269.         }
  270.         for (i = -n; i <= n; i++) {
  271.             if (try_to_cough(row+i, col-n, obj)) {
  272.                 return;
  273.             }
  274.             if (try_to_cough(row+i, col+n, obj)) {
  275.                 return;
  276.             }
  277.         }
  278.     }
  279.     free_object(obj);
  280. }
  281.  
  282. try_to_cough(row, col, obj)
  283. short row, col;
  284. object *obj;
  285. {
  286.     if ((row < MIN_ROW) || (row > (DROWS-2)) || (col < 0) || (col>(DCOLS-1))) {
  287.         return(0);
  288.     }
  289.     if ((!(dungeon[row][col] & (OBJECT | STAIRS | TRAP))) &&
  290.         (dungeon[row][col] & (TUNNEL | FLOOR | DOOR))) {
  291.         place_at(obj, row, col);
  292.         if (((row != rogue.row) || (col != rogue.col)) &&
  293.             (!(dungeon[row][col] & MONSTER))) {
  294.             mvaddch(row, col, get_dungeon_char(row, col));
  295.         }
  296.         return(1);
  297.     }
  298.     return(0);
  299. }
  300.  
  301. seek_gold(monster)
  302. object *monster;
  303. {
  304.     short i, j, rn, s;
  305.  
  306.     if ((rn = get_room_number(monster->row, monster->col)) < 0) {
  307.         return(0);
  308.     }
  309.     for (i = rooms[rn].top_row+1; i < rooms[rn].bottom_row; i++) {
  310.         for (j = rooms[rn].left_col+1; j < rooms[rn].right_col; j++) {
  311.             if ((gold_at(i, j)) && !(dungeon[i][j] & MONSTER)) {
  312.                 monster->m_flags |= CAN_FLIT;
  313.                 s = mon_can_go(monster, i, j);
  314.                 monster->m_flags &= (~CAN_FLIT);
  315.                 if (s) {
  316.                     move_mon_to(monster, i, j);
  317.                     monster->m_flags |= ASLEEP;
  318.                     monster->m_flags &= (~(WAKENS | SEEKS_GOLD));
  319.                     return(1);
  320.                 }
  321.                 monster->m_flags &= (~SEEKS_GOLD);
  322.                 monster->m_flags |= CAN_FLIT;
  323.                 mv_1_monster(monster, i, j);
  324.                 monster->m_flags &= (~CAN_FLIT);
  325.                 monster->m_flags |= SEEKS_GOLD;
  326.                 return(1);
  327.             }
  328.         }
  329.     }
  330.     return(0);
  331. }
  332.  
  333. gold_at(row, col)
  334. short row, col;
  335. {
  336.     if (dungeon[row][col] & OBJECT) {
  337.         object *obj;
  338.  
  339.         if ((obj = object_at(&level_objects, row, col)) &&
  340.                 (obj->what_is == GOLD)) {
  341.             return(1);
  342.         }
  343.     }
  344.     return(0);
  345. }
  346.  
  347. check_gold_seeker(monster)
  348. object *monster;
  349. {
  350.     monster->m_flags &= (~SEEKS_GOLD);
  351. }
  352.  
  353. check_imitator(monster)
  354. object *monster;
  355. {
  356.     char msg[80];
  357.  
  358.     if (monster->m_flags & IMITATES) {
  359.         wake_up(monster);
  360.         if (!blind) {
  361.             mvaddch(monster->row, monster->col,
  362.                     get_dungeon_char(monster->row, monster->col));
  363.             check_message();
  364.             sprintf(msg, "wait, that's a %s!", mon_name(monster));
  365.             message(msg, 1);
  366.         }
  367.         return(1);
  368.     }
  369.     return(0);
  370. }
  371.  
  372. imitating(row, col)
  373. register short row, col;
  374. {
  375.     if (dungeon[row][col] & MONSTER) {
  376.         object *object_at(), *monster;
  377.  
  378.         if (monster = object_at(&level_monsters, row, col)) {
  379.             if (monster->m_flags & IMITATES) {
  380.                 return(1);
  381.             }
  382.         }
  383.     }
  384.     return(0);
  385. }
  386.  
  387. sting(monster)
  388. object *monster;
  389. {
  390.     short sting_chance = 35;
  391.     char msg[80];
  392.  
  393.     if ((rogue.str_current <= 3) || sustain_strength) {
  394.         return;
  395.     }
  396.     sting_chance += (6 * (6 - get_armor_class(rogue.armor)));
  397.  
  398.     if ((rogue.exp + ring_exp) > 8) {
  399.         sting_chance -= (6 * ((rogue.exp + ring_exp) - 8));
  400.     }
  401.     if (rand_percent(sting_chance)) {
  402.         sprintf(msg, "the %s's bite has weakened you",
  403.         mon_name(monster));
  404.         message(msg, 0);
  405.         rogue.str_current--;
  406.         print_stats(STAT_STRENGTH);
  407.     }
  408. }
  409.  
  410. drop_level()
  411. {
  412.     int hp;
  413.  
  414.     if (rand_percent(80) || (rogue.exp <= 5)) {
  415.         return;
  416.     }
  417.     rogue.exp_points = level_points[rogue.exp-2] - get_rand(9, 29);
  418.     rogue.exp -= 2;
  419.     hp = hp_raise();
  420.     if ((rogue.hp_current -= hp) <= 0) {
  421.         rogue.hp_current = 1;
  422.     }
  423.     if ((rogue.hp_max -= hp) <= 0) {
  424.         rogue.hp_max = 1;
  425.     }
  426.     add_exp(1, 0);
  427. }
  428.  
  429. drain_life()
  430. {
  431.     short n;
  432.  
  433.     if (rand_percent(60) || (rogue.hp_max <= 30) || (rogue.hp_current < 10)) {
  434.         return;
  435.     }
  436.     n = get_rand(1, 3);        /* 1 Hp, 2 Str, 3 both */
  437.  
  438.     if ((n != 2) || (!sustain_strength)) {
  439.         message("you feel weaker", 0);
  440.     }
  441.     if (n != 2) {
  442.         rogue.hp_max--;
  443.         rogue.hp_current--;
  444.         less_hp++;
  445.     }
  446.     if (n != 1) {
  447.         if ((rogue.str_current > 3) && (!sustain_strength)) {
  448.             rogue.str_current--;
  449.             if (coin_toss()) {
  450.                 rogue.str_max--;
  451.             }
  452.         }
  453.     }
  454.     print_stats((STAT_STRENGTH | STAT_HP));
  455. }
  456.  
  457. m_confuse(monster)
  458. object *monster;
  459. {
  460.     char msg[80];
  461.  
  462.     if (!rogue_can_see(monster->row, monster->col)) {
  463.         return(0);
  464.     }
  465.     if (rand_percent(45)) {
  466.         monster->m_flags &= (~CONFUSES);    /* will not confuse the rogue */
  467.         return(0);
  468.     }
  469.     if (rand_percent(55)) {
  470.         monster->m_flags &= (~CONFUSES);
  471.         sprintf(msg, "the gaze of the %s has confused you", mon_name(monster));
  472.         message(msg, 1);
  473.         cnfs();
  474.         return(1);
  475.     }
  476.     return(0);
  477. }
  478.  
  479. flame_broil(monster)
  480. object *monster;
  481. {
  482.     short row, col, dir;
  483.  
  484.     if ((!mon_sees(monster, rogue.row, rogue.col)) || coin_toss()) {
  485.         return(0);
  486.     }
  487.     row = rogue.row - monster->row;
  488.     col = rogue.col - monster->col;
  489.     if (row < 0) {
  490.         row = -row;
  491.     }
  492.     if (col < 0) {
  493.         col = -col;
  494.     }
  495.     if (((row != 0) && (col != 0) && (row != col)) ||
  496.         ((row > 7) || (col > 7))) {
  497.         return(0);
  498.     }
  499.     dir = get_dir(monster->row, monster->col, row, col);
  500.     bounce(FIRE, dir, monster->row, monster->col, 0);
  501.  
  502.     return(1);
  503. }
  504.  
  505. get_dir(srow, scol, drow, dcol)
  506. short srow, scol, drow, dcol;
  507. {
  508.     if (srow == drow) {
  509.         if (scol < dcol) {
  510.             return(RIGHT);
  511.         } else {
  512.             return(LEFT);
  513.         }
  514.     }
  515.     if (scol == dcol) {
  516.         if (srow < drow) {
  517.             return(DOWN);
  518.         } else {
  519.             return(UPWARD);
  520.         }
  521.     }
  522.     if ((srow > drow) && (scol > dcol)) {
  523.         return(UPLEFT);
  524.     }
  525.     if ((srow < drow) && (scol < dcol)) {
  526.         return(DOWNRIGHT);
  527.     }
  528.     if ((srow < drow) && (scol > dcol)) {
  529.         return(DOWNLEFT);
  530.     }
  531.     /*if ((srow > drow) && (scol < dcol)) {*/
  532.         return(UPRIGHT);
  533.     /*}*/
  534. }
  535.