home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / games / rogue / hit.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-04-08  |  9.7 KB  |  457 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[] = "@(#)hit.c    5.3 (Berkeley) 6/1/90";
  39. #endif /* not lint */
  40.  
  41. /*
  42.  * 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. object *fight_monster = 0;
  56. char hit_message[80] = "";
  57.  
  58. extern short halluc, blind, cur_level;
  59. extern short add_strength, ring_exp, r_rings;
  60. extern boolean being_held, interrupted, wizard, con_mon;
  61.  
  62. mon_hit(monster)
  63. register object *monster;
  64. {
  65.     short damage, hit_chance;
  66.     char *mn;
  67.     float minus;
  68.  
  69.     if (fight_monster && (monster != fight_monster)) {
  70.         fight_monster = 0;
  71.     }
  72.     monster->trow = NO_ROOM;
  73.     if (cur_level >= (AMULET_LEVEL * 2)) {
  74.         hit_chance = 100;
  75.     } else {
  76.         hit_chance = monster->m_hit_chance;
  77.         hit_chance -= (((2 * rogue.exp) + (2 * ring_exp)) - r_rings);
  78.     }
  79.     if (wizard) {
  80.         hit_chance /= 2;
  81.     }
  82.     if (!fight_monster) {
  83.         interrupted = 1;
  84.     }
  85.     mn = mon_name(monster);
  86.  
  87.     if (!rand_percent(hit_chance)) {
  88.         if (!fight_monster) {
  89.             sprintf(hit_message + strlen(hit_message), "the %s misses", mn);
  90.             message(hit_message, 1);
  91.             hit_message[0] = 0;
  92.         }
  93.         return;
  94.     }
  95.     if (!fight_monster) {
  96.         sprintf(hit_message + strlen(hit_message), "the %s hit", mn);
  97.         message(hit_message, 1);
  98.         hit_message[0] = 0;
  99.     }
  100.     if (!(monster->m_flags & STATIONARY)) {
  101.         damage = get_damage(monster->m_damage, 1);
  102.         if (cur_level >= (AMULET_LEVEL * 2)) {
  103.             minus = (float) ((AMULET_LEVEL * 2) - cur_level);
  104.         } else {
  105.             minus = (float) get_armor_class(rogue.armor) * 3.00;
  106.             minus = minus/100.00 * (float) damage;
  107.         }
  108.         damage -= (short) minus;
  109.     } else {
  110.         damage = monster->stationary_damage++;
  111.     }
  112.     if (wizard) {
  113.         damage /= 3;
  114.     }
  115.     if (damage > 0) {
  116.         rogue_damage(damage, monster, 0);
  117.     }
  118.     if (monster->m_flags & SPECIAL_HIT) {
  119.         special_hit(monster);
  120.     }
  121. }
  122.  
  123. rogue_hit(monster, force_hit)
  124. register object *monster;
  125. boolean force_hit;
  126. {
  127.     short damage, hit_chance;
  128.  
  129.     if (monster) {
  130.         if (check_imitator(monster)) {
  131.             return;
  132.         }
  133.         hit_chance = force_hit ? 100 : get_hit_chance(rogue.weapon);
  134.  
  135.         if (wizard) {
  136.             hit_chance *= 2;
  137.         }
  138.         if (!rand_percent(hit_chance)) {
  139.             if (!fight_monster) {
  140.                 (void) strcpy(hit_message, "you miss  ");
  141.             }
  142.             goto RET;
  143.         }
  144.         damage = get_weapon_damage(rogue.weapon);
  145.         if (wizard) {
  146.             damage *= 3;
  147.         }
  148.         if (con_mon) {
  149.             s_con_mon(monster);
  150.         }
  151.         if (mon_damage(monster, damage)) {    /* still alive? */
  152.             if (!fight_monster) {
  153.                 (void) strcpy(hit_message, "you hit  ");
  154.             }
  155.         }
  156. RET:    check_gold_seeker(monster);
  157.         wake_up(monster);
  158.     }
  159. }
  160.  
  161. rogue_damage(d, monster, other)
  162. short d;
  163. object *monster;
  164. short other;
  165. {
  166.     if (d >= rogue.hp_current) {
  167.         rogue.hp_current = 0;
  168.         print_stats(STAT_HP);
  169.         killed_by(monster, other);
  170.     }
  171.     if (d > 0) {
  172.         rogue.hp_current -= d;
  173.         print_stats(STAT_HP);
  174.     }
  175. }
  176.  
  177. get_damage(ds, r)
  178. char *ds;
  179. boolean r;
  180. {
  181.     register i = 0, j, n, d, total = 0;
  182.  
  183.     while (ds[i]) {
  184.         n = get_number(ds+i);
  185.         while (ds[i++] != 'd') ;
  186.         d = get_number(ds+i);
  187.         while ((ds[i] != '/') && ds[i]) i++;
  188.  
  189.         for (j = 0; j < n; j++) {
  190.             if (r) {
  191.                 total += get_rand(1, d);
  192.             } else {
  193.                 total += d;
  194.             }
  195.         }
  196.         if (ds[i] == '/') {
  197.             i++;
  198.         }
  199.     }
  200.     return(total);
  201. }
  202.  
  203. get_w_damage(obj)
  204. object *obj;
  205. {
  206.     char new_damage[12];
  207.     register to_hit, damage;
  208.     register i = 0;
  209.  
  210.     if ((!obj) || (obj->what_is != WEAPON)) {
  211.         return(-1);
  212.     }
  213.     to_hit = get_number(obj->damage) + obj->hit_enchant;
  214.     while (obj->damage[i++] != 'd') ;
  215.     damage = get_number(obj->damage + i) + obj->d_enchant;
  216.  
  217.     sprintf(new_damage, "%dd%d", to_hit, damage);
  218.  
  219.     return(get_damage(new_damage, 1));
  220. }
  221.  
  222. get_number(s)
  223. register char *s;
  224. {
  225.     register i = 0;
  226.     register total = 0;
  227.  
  228.     while ((s[i] >= '0') && (s[i] <= '9')) {
  229.         total = (10 * total) + (s[i] - '0');
  230.         i++;
  231.     }
  232.     return(total);
  233. }
  234.  
  235. long
  236. lget_number(s)
  237. char *s;
  238. {
  239.     short i = 0;
  240.     long total = 0;
  241.  
  242.     while ((s[i] >= '0') && (s[i] <= '9')) {
  243.         total = (10 * total) + (s[i] - '0');
  244.         i++;
  245.     }
  246.     return(total);
  247. }
  248.  
  249. to_hit(obj)
  250. object *obj;
  251. {
  252.     if (!obj) {
  253.         return(1);
  254.     }
  255.     return(get_number(obj->damage) + obj->hit_enchant);
  256. }
  257.  
  258. damage_for_strength()
  259. {
  260.     short strength;
  261.  
  262.     strength = rogue.str_current + add_strength;
  263.  
  264.     if (strength <= 6) {
  265.         return(strength-5);
  266.     }
  267.     if (strength <= 14) {
  268.         return(1);
  269.     }
  270.     if (strength <= 17) {
  271.         return(3);
  272.     }
  273.     if (strength <= 18) {
  274.         return(4);
  275.     }
  276.     if (strength <= 20) {
  277.         return(5);
  278.     }
  279.     if (strength <= 21) {
  280.         return(6);
  281.     }
  282.     if (strength <= 30) {
  283.         return(7);
  284.     }
  285.     return(8);
  286. }
  287.  
  288. mon_damage(monster, damage)
  289. object *monster;
  290. short damage;
  291. {
  292.     char *mn;
  293.     short row, col;
  294.  
  295.     monster->hp_to_kill -= damage;
  296.  
  297.     if (monster->hp_to_kill <= 0) {
  298.         row = monster->row;
  299.         col = monster->col;
  300.         dungeon[row][col] &= ~MONSTER;
  301.         mvaddch(row, col, (int) get_dungeon_char(row, col));
  302.  
  303.         fight_monster = 0;
  304.         cough_up(monster);
  305.         mn = mon_name(monster);
  306.         sprintf(hit_message+strlen(hit_message), "defeated the %s", mn);
  307.         message(hit_message, 1);
  308.         hit_message[0] = 0;
  309.         add_exp(monster->kill_exp, 1);
  310.         take_from_pack(monster, &level_monsters);
  311.  
  312.         if (monster->m_flags & HOLDS) {
  313.             being_held = 0;
  314.         }
  315.         free_object(monster);
  316.         return(0);
  317.     }
  318.     return(1);
  319. }
  320.  
  321. fight(to_the_death)
  322. boolean to_the_death;
  323. {
  324.     short ch, c, d;
  325.     short row, col;
  326.     boolean first_miss = 1;
  327.     short possible_damage;
  328.     object *monster;
  329.  
  330.     while (!is_direction(ch = rgetchar(), &d)) {
  331.         sound_bell();
  332.         if (first_miss) {
  333.             message("direction?", 0);
  334.             first_miss = 0;
  335.         }
  336.     }
  337.     check_message();
  338.     if (ch == CANCEL) {
  339.         return;
  340.     }
  341.     row = rogue.row; col = rogue.col;
  342.     get_dir_rc(d, &row, &col, 0);
  343.  
  344.     c = mvinch(row, col);
  345.     if (((c < 'A') || (c > 'Z')) ||
  346.         (!can_move(rogue.row, rogue.col, row, col))) {
  347.         message("I see no monster there", 0);
  348.         return;
  349.     }
  350.     if (!(fight_monster = object_at(&level_monsters, row, col))) {
  351.         return;
  352.     }
  353.     if (!(fight_monster->m_flags & STATIONARY)) {
  354.         possible_damage = ((get_damage(fight_monster->m_damage, 0) * 2) / 3);
  355.     } else {
  356.         possible_damage = fight_monster->stationary_damage - 1;
  357.     }
  358.     while (fight_monster) {
  359.         (void) one_move_rogue(ch, 0);
  360.         if (((!to_the_death) && (rogue.hp_current <= possible_damage)) ||
  361.             interrupted || (!(dungeon[row][col] & MONSTER))) {
  362.             fight_monster = 0;
  363.         } else {
  364.             monster = object_at(&level_monsters, row, col);
  365.             if (monster != fight_monster) {
  366.                 fight_monster = 0;
  367.             }
  368.         }
  369.     }
  370. }
  371.  
  372. get_dir_rc(dir, row, col, allow_off_screen)
  373. short dir;
  374. short *row, *col;
  375. short allow_off_screen;
  376. {
  377.     switch(dir) {
  378.     case LEFT:
  379.         if (allow_off_screen || (*col > 0)) {
  380.             (*col)--;
  381.         }
  382.         break;
  383.     case DOWN:
  384.         if (allow_off_screen || (*row < (DROWS-2))) {
  385.             (*row)++;
  386.         }
  387.         break;
  388.     case UPWARD:
  389.         if (allow_off_screen || (*row > MIN_ROW)) {
  390.             (*row)--;
  391.         }
  392.         break;
  393.     case RIGHT:
  394.         if (allow_off_screen || (*col < (DCOLS-1))) {
  395.             (*col)++;
  396.         }
  397.         break;
  398.     case UPLEFT:
  399.         if (allow_off_screen || ((*row > MIN_ROW) && (*col > 0))) {
  400.             (*row)--;
  401.             (*col)--;
  402.         }
  403.         break;
  404.     case UPRIGHT:
  405.         if (allow_off_screen || ((*row > MIN_ROW) && (*col < (DCOLS-1)))) {
  406.             (*row)--;
  407.             (*col)++;
  408.         }
  409.         break;
  410.     case DOWNRIGHT:
  411.         if (allow_off_screen || ((*row < (DROWS-2)) && (*col < (DCOLS-1)))) {
  412.             (*row)++;
  413.             (*col)++;
  414.         }
  415.         break;
  416.     case DOWNLEFT:
  417.         if (allow_off_screen || ((*row < (DROWS-2)) && (*col > 0))) {
  418.             (*row)++;
  419.             (*col)--;
  420.         }
  421.         break;
  422.     }
  423. }
  424.  
  425. get_hit_chance(weapon)
  426. object *weapon;
  427. {
  428.     short hit_chance;
  429.  
  430.     hit_chance = 40;
  431.     hit_chance += 3 * to_hit(weapon);
  432.     hit_chance += (((2 * rogue.exp) + (2 * ring_exp)) - r_rings);
  433.     return(hit_chance);
  434. }
  435.  
  436. get_weapon_damage(weapon)
  437. object *weapon;
  438. {
  439.     short damage;
  440.  
  441.     damage = get_w_damage(weapon);
  442.     damage += damage_for_strength();
  443.     damage += ((((rogue.exp + ring_exp) - r_rings) + 1) / 2);
  444.     return(damage);
  445. }
  446.  
  447. s_con_mon(monster)
  448. object *monster;
  449. {
  450.     if (con_mon) {
  451.         monster->m_flags |= CONFUSED;
  452.         monster->moves_confused += get_rand(12, 22);
  453.         message("the monster appears confused", 0);
  454.         con_mon = 0;
  455.     }
  456. }
  457.