home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / games / rogue / zap.c < prev   
Encoding:
C/C++ Source or Header  |  1991-04-08  |  9.8 KB  |  406 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[] = "@(#)zap.c    5.3 (Berkeley) 6/1/90";
  39. #endif /* not lint */
  40.  
  41. /*
  42.  * zap.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. boolean wizard = 0;
  56.  
  57. extern boolean being_held, score_only, detect_monster;
  58. extern short cur_room;
  59.  
  60. zapp()
  61. {
  62.     short wch;
  63.     boolean first_miss = 1;
  64.     object *wand;
  65.     short dir, d, row, col;
  66.     object *monster;
  67.  
  68.     while (!is_direction(dir = rgetchar(), &d)) {
  69.         sound_bell();
  70.         if (first_miss) {
  71.             message("direction? ", 0);
  72.             first_miss = 0;
  73.         }
  74.     }
  75.     check_message();
  76.     if (dir == CANCEL) {
  77.         return;
  78.     }
  79.     if ((wch = pack_letter("zap with what?", WAND)) == CANCEL) {
  80.         return;
  81.     }
  82.     check_message();
  83.  
  84.     if (!(wand = get_letter_object(wch))) {
  85.         message("no such item.", 0);
  86.         return;
  87.     }
  88.     if (wand->what_is != WAND) {
  89.         message("you can't zap with that", 0);
  90.         return;
  91.     }
  92.     if (wand->class <= 0) {
  93.         message("nothing happens", 0);
  94.     } else {
  95.         wand->class--;
  96.         row = rogue.row; col = rogue.col;
  97.         if ((wand->which_kind == COLD) || (wand->which_kind == FIRE)) {
  98.             bounce((short) wand->which_kind, d, row, col, 0);
  99.         } else {
  100.             monster = get_zapped_monster(d, &row, &col);
  101.             if (wand->which_kind == DRAIN_LIFE) {
  102.                 wdrain_life(monster);
  103.             } else if (monster) {
  104.                 wake_up(monster);
  105.                 s_con_mon(monster);
  106.                 zap_monster(monster, wand->which_kind);
  107.                 relight();
  108.             }
  109.         }
  110.     }
  111.     (void) reg_move();
  112. }
  113.  
  114. object *
  115. get_zapped_monster(dir, row, col)
  116. short dir;
  117. short *row, *col;
  118. {
  119.     short orow, ocol;
  120.  
  121.     for (;;) {
  122.         orow = *row; ocol = *col;
  123.         get_dir_rc(dir, row, col, 0);
  124.         if (((*row == orow) && (*col == ocol)) ||
  125.            (dungeon[*row][*col] & (HORWALL | VERTWALL)) ||
  126.            (dungeon[*row][*col] == NOTHING)) {
  127.             return(0);
  128.         }
  129.         if (dungeon[*row][*col] & MONSTER) {
  130.             if (!imitating(*row, *col)) {
  131.                 return(object_at(&level_monsters, *row, *col));
  132.             }
  133.         }
  134.     }
  135. }
  136.  
  137. zap_monster(monster, kind)
  138. object *monster;
  139. unsigned short kind;
  140. {
  141.     short row, col;
  142.     object *nm;
  143.     short tc;
  144.  
  145.     row = monster->row;
  146.     col = monster->col;
  147.  
  148.     switch(kind) {
  149.     case SLOW_MONSTER:
  150.         if (monster->m_flags & HASTED) {
  151.             monster->m_flags &= (~HASTED);
  152.         } else {
  153.             monster->slowed_toggle = 0;
  154.             monster->m_flags |= SLOWED;
  155.         }
  156.         break;
  157.     case HASTE_MONSTER:
  158.         if (monster->m_flags & SLOWED) {
  159.             monster->m_flags &= (~SLOWED);
  160.         } else {
  161.             monster->m_flags |= HASTED;
  162.         }
  163.         break;
  164.     case TELE_AWAY:
  165.         tele_away(monster);
  166.         break;
  167.     case INVISIBILITY:
  168.         monster->m_flags |= INVISIBLE;
  169.         break;
  170.     case POLYMORPH:
  171.         if (monster->m_flags & HOLDS) {
  172.             being_held = 0;
  173.         }
  174.         nm = monster->next_monster;
  175.         tc = monster->trail_char;
  176.         (void) gr_monster(monster, get_rand(0, MONSTERS-1));
  177.         monster->row = row;
  178.         monster->col = col;
  179.         monster->next_monster = nm;
  180.         monster->trail_char = tc;
  181.         if (!(monster->m_flags & IMITATES)) {
  182.             wake_up(monster);
  183.         }
  184.         break;
  185.     case MAGIC_MISSILE:
  186.         rogue_hit(monster, 1);
  187.         break;
  188.     case CANCELLATION:
  189.         if (monster->m_flags & HOLDS) {
  190.             being_held = 0;
  191.         }
  192.         if (monster->m_flags & STEALS_ITEM) {
  193.             monster->drop_percent = 0;
  194.         }
  195.         monster->m_flags &= (~(FLIES | FLITS | SPECIAL_HIT | INVISIBLE |
  196.             FLAMES | IMITATES | CONFUSES | SEEKS_GOLD | HOLDS));
  197.         break;
  198.     case DO_NOTHING:
  199.         message("nothing happens", 0);
  200.         break;
  201.     }
  202. }
  203.  
  204. tele_away(monster)
  205. object *monster;
  206. {
  207.     short row, col;
  208.  
  209.     if (monster->m_flags & HOLDS) {
  210.         being_held = 0;
  211.     }
  212.     gr_row_col(&row, &col, (FLOOR | TUNNEL | STAIRS | OBJECT));
  213.     mvaddch(monster->row, monster->col, monster->trail_char);
  214.     dungeon[monster->row][monster->col] &= ~MONSTER;
  215.     monster->row = row; monster->col = col;
  216.     dungeon[row][col] |= MONSTER;
  217.     monster->trail_char = mvinch(row, col);
  218.     if (detect_monster || rogue_can_see(row, col)) {
  219.         mvaddch(row, col, gmc(monster));
  220.     }
  221. }
  222.  
  223. wizardize()
  224. {
  225.     char buf[100];
  226.  
  227.     if (wizard) {
  228.         wizard = 0;
  229.         message("not wizard anymore", 0);
  230.     } else {
  231.         if (get_input_line("wizard's password:", "", buf, "", 0, 0)) {
  232.             (void) xxx(1);
  233.             xxxx(buf, strlen(buf));
  234.             if (!strncmp(buf, "\247\104\126\272\115\243\027", 7)) {
  235.                 wizard = 1;
  236.                 score_only = 1;
  237.                 message("Welcome, mighty wizard!", 0);
  238.             } else {
  239.                 message("sorry", 0);
  240.             }
  241.         }
  242.     }
  243. }
  244.  
  245. wdrain_life(monster)
  246. object *monster;
  247. {
  248.     short hp;
  249.     object *lmon, *nm;
  250.  
  251.     hp = rogue.hp_current / 3;
  252.     rogue.hp_current = (rogue.hp_current + 1) / 2;
  253.  
  254.     if (cur_room >= 0) {
  255.         lmon = level_monsters.next_monster;
  256.         while (lmon) {
  257.             nm = lmon->next_monster;
  258.             if (get_room_number(lmon->row, lmon->col) == cur_room) {
  259.                 wake_up(lmon);
  260.                 (void) mon_damage(lmon, hp);
  261.             }
  262.             lmon = nm;
  263.         }
  264.     } else {
  265.         if (monster) {
  266.             wake_up(monster);
  267.             (void) mon_damage(monster, hp);
  268.         }
  269.     }
  270.     print_stats(STAT_HP);
  271.     relight();
  272. }
  273.  
  274. bounce(ball, dir, row, col, r)
  275. short ball, dir, row, col, r;
  276. {
  277.     short orow, ocol;
  278.     char buf[DCOLS], *s;
  279.     short i, ch, new_dir = -1, damage;
  280.     static short btime;
  281.  
  282.     if (++r == 1) {
  283.         btime = get_rand(3, 6);
  284.     } else if (r > btime) {
  285.         return;
  286.     }
  287.  
  288.     if (ball == FIRE) {
  289.         s = "fire";
  290.     } else {
  291.         s = "ice";
  292.     }
  293.     if (r > 1) {
  294.         sprintf(buf, "the %s bounces", s);
  295.         message(buf, 0);
  296.     }
  297.     orow = row;
  298.     ocol = col;
  299.     do {
  300.         ch = mvinch(orow, ocol);
  301.         standout();
  302.         mvaddch(orow, ocol, ch);
  303.         get_dir_rc(dir, &orow, &ocol, 1);
  304.     } while (!(    (ocol <= 0) ||
  305.                 (ocol >= DCOLS-1) ||
  306.                 (dungeon[orow][ocol] == NOTHING) ||
  307.                 (dungeon[orow][ocol] & MONSTER) ||
  308.                 (dungeon[orow][ocol] & (HORWALL | VERTWALL)) ||
  309.                 ((orow == rogue.row) && (ocol == rogue.col))));
  310.     standend();
  311.     refresh();
  312.     do {
  313.         orow = row;
  314.         ocol = col;
  315.         ch = mvinch(row, col);
  316.         mvaddch(row, col, ch);
  317.         get_dir_rc(dir, &row, &col, 1);
  318.     } while (!(    (col <= 0) ||
  319.                 (col >= DCOLS-1) ||
  320.                 (dungeon[row][col] == NOTHING) ||
  321.                 (dungeon[row][col] & MONSTER) ||
  322.                 (dungeon[row][col] & (HORWALL | VERTWALL)) ||
  323.                 ((row == rogue.row) && (col == rogue.col))));
  324.  
  325.     if (dungeon[row][col] & MONSTER) {
  326.         object *monster;
  327.  
  328.         monster = object_at(&level_monsters, row, col);
  329.  
  330.         wake_up(monster);
  331.         if (rand_percent(33)) {
  332.             sprintf(buf, "the %s misses the %s", s, mon_name(monster));
  333.             message(buf, 0);
  334.             goto ND;
  335.         }
  336.         if (ball == FIRE) {
  337.             if (!(monster->m_flags & RUSTS)) {
  338.                 if (monster->m_flags & FREEZES) {
  339.                     damage = monster->hp_to_kill;
  340.                 } else if (monster->m_flags & FLAMES) {
  341.                     damage = (monster->hp_to_kill / 10) + 1;
  342.                 } else {
  343.                     damage = get_rand((rogue.hp_current / 3), rogue.hp_max);
  344.                 }
  345.             } else {
  346.                 damage = (monster->hp_to_kill / 2) + 1;
  347.             }
  348.             sprintf(buf, "the %s hits the %s", s, mon_name(monster));
  349.             message(buf, 0);
  350.             (void) mon_damage(monster, damage);
  351.         } else {
  352.             damage = -1;
  353.             if (!(monster->m_flags & FREEZES)) {
  354.                 if (rand_percent(33)) {
  355.                     message("the monster is frozen", 0);
  356.                     monster->m_flags |= (ASLEEP | NAPPING);
  357.                     monster->nap_length = get_rand(3, 6);
  358.                 } else {
  359.                     damage = rogue.hp_current / 4;
  360.                 }
  361.             } else {
  362.                 damage = -2;
  363.             }
  364.             if (damage != -1) {
  365.                 sprintf(buf, "the %s hits the %s", s, mon_name(monster));
  366.                 message(buf, 0);
  367.                 (void) mon_damage(monster, damage);
  368.             }
  369.         }
  370.     } else if ((row == rogue.row) && (col == rogue.col)) {
  371.         if (rand_percent(10 + (3 * get_armor_class(rogue.armor)))) {
  372.             sprintf(buf, "the %s misses", s);
  373.             message(buf, 0);
  374.             goto ND;
  375.         } else {
  376.             damage = get_rand(3, (3 * rogue.exp));
  377.             if (ball == FIRE) {
  378.                 damage = (damage * 3) / 2;
  379.                 damage -= get_armor_class(rogue.armor);
  380.             }
  381.             sprintf(buf, "the %s hits", s);
  382.             rogue_damage(damage, (object *) 0,
  383.                     ((ball == FIRE) ? KFIRE : HYPOTHERMIA));
  384.             message(buf, 0);
  385.         }
  386.     } else {
  387.         short nrow, ncol;
  388.  
  389. ND:        for (i = 0; i < 10; i++) {
  390.             dir = get_rand(0, DIRS-1);
  391.             nrow = orow;
  392.             ncol = ocol;
  393.             get_dir_rc(dir, &nrow, &ncol, 1);
  394.             if (((ncol >= 0) && (ncol <= DCOLS-1)) &&
  395.                 (dungeon[nrow][ncol] != NOTHING) &&
  396.                 (!(dungeon[nrow][ncol] & (VERTWALL | HORWALL)))) {
  397.                 new_dir = dir;
  398.                 break;
  399.             }
  400.         }
  401.         if (new_dir != -1) {
  402.             bounce(ball, new_dir, orow, ocol, r);
  403.         }
  404.     }
  405. }
  406.