home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 January
/
usenetsourcesnewsgroupsinfomagicjanuary1994.iso
/
sources
/
games
/
volume14
/
umoria4
/
part06
< prev
next >
Wrap
Internet Message Format
|
1992-08-31
|
57KB
Path: uunet!zephyr.ens.tek.com!master!saab!billr
From: billr@saab.CNA.TEK.COM (Bill Randle)
Newsgroups: comp.sources.games
Subject: v14i038: umoria4 - single player dungeon simulation (ver. 5.5), Part06/39
Message-ID: <3396@master.CNA.TEK.COM>
Date: 20 Aug 92 18:02:48 GMT
Sender: news@master.CNA.TEK.COM
Lines: 2078
Approved: billr@saab.CNA.TEK.COM
Submitted-by: grabiner@math.harvard.edu (David Grabiner)
Posting-number: Volume 14, Issue 38
Archive-name: umoria4/Part06
Supersedes: umoria3: Volume 9, Issue 55-97; Volume 10, Issue 15-17
Environment: Curses, Unix, Mac, MS-DOS, Atari-ST, Amiga, VMS
#! /bin/sh
# This is a shell archive. Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of archive 6 (of 39)."
# Contents: source/creature.c util/printit/pr_monst.c
# Wrapped by billr@saab on Thu Aug 20 09:11:27 1992
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'source/creature.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'source/creature.c'\"
else
echo shar: Extracting \"'source/creature.c'\" \(46325 characters\)
sed "s/^X//" >'source/creature.c' <<'END_OF_FILE'
X/* source/creature.c: handle monster movement and attacks
X
X Copyright (c) 1989-92 James E. Wilson, Robert A. Koeneke
X
X This software may be copied and distributed for educational, research, and
X not for profit purposes provided that this copyright and statement are
X included in all such copies. */
X
X#ifdef __TURBOC__
X#include <stdio.h>
X#include <stdlib.h>
X#endif /* __TURBOC__ */
X
X#include "config.h"
X#include "constant.h"
X#include "types.h"
X#include "externs.h"
X
X#ifdef USG
X#ifndef ATARIST_MWC
X#include <string.h>
X#else
Xchar *strcat();
Xchar *strcpy();
X#endif
X#else
X#include <strings.h>
X#endif
X
X#if defined(LINT_ARGS)
Xstatic int movement_rate(int16);
Xstatic int check_mon_lite(int, int);
Xstatic void get_moves(int, int *);
Xstatic void make_attack(int);
Xstatic void make_move(int, int *, int32u *);
Xstatic void mon_cast_spell(int, int *);
Xstatic void mon_move(int, int32u *);
X#endif
X
X#ifdef ATARIST_TC
X/* Include this to get prototypes for standard library functions. */
X#include <stdlib.h>
X#endif
X
X
X/* Updates screen when monsters move about -RAK- */
Xvoid update_mon(monptr)
Xint monptr;
X{
X register int flag;
X register cave_type *c_ptr;
X register monster_type *m_ptr;
X register creature_type *r_ptr;
X#ifdef ATARIST_MWC
X int32u holder;
X#endif
X
X m_ptr = &m_list[monptr];
X flag = FALSE;
X if ((m_ptr->cdis <= MAX_SIGHT) &&
X !(py.flags.status & PY_BLIND) &&
X (panel_contains((int)m_ptr->fy, (int)m_ptr->fx)))
X {
X /* Wizard sight. */
X if (wizard)
X flag = TRUE;
X /* Normal sight. */
X else if (los(char_row, char_col, (int)m_ptr->fy, (int)m_ptr->fx))
X {
X c_ptr = &cave[m_ptr->fy][m_ptr->fx];
X r_ptr = &c_list[m_ptr->mptr];
X if (c_ptr->pl || c_ptr->tl ||
X (find_flag && m_ptr->cdis < 2 && player_light))
X {
X#ifdef ATARIST_MWC
X holder = CM_INVISIBLE;
X if ((holder & r_ptr->cmove) == 0)
X#else
X if ((CM_INVISIBLE & r_ptr->cmove) == 0)
X#endif
X flag = TRUE;
X else if (py.flags.see_inv)
X {
X flag = TRUE;
X#ifdef ATARIST_MWC
X c_recall[m_ptr->mptr].r_cmove |= holder;
X#else
X c_recall[m_ptr->mptr].r_cmove |= CM_INVISIBLE;
X#endif
X }
X }
X /* Infra vision. */
X else if ((py.flags.see_infra > 0) &&
X (m_ptr->cdis <= py.flags.see_infra) &&
X (CD_INFRA & r_ptr->cdefense))
X {
X flag = TRUE;
X c_recall[m_ptr->mptr].r_cdefense |= CD_INFRA;
X }
X }
X }
X /* Light it up. */
X if (flag)
X {
X if (!m_ptr->ml)
X {
X disturb (1, 0);
X m_ptr->ml = TRUE;
X lite_spot((int)m_ptr->fy, (int)m_ptr->fx);
X screen_change = TRUE; /* notify inven_command */
X }
X }
X /* Turn it off. */
X else if (m_ptr->ml)
X {
X m_ptr->ml = FALSE;
X lite_spot((int)m_ptr->fy, (int)m_ptr->fx);
X screen_change = TRUE; /* notify inven_command */
X }
X}
X
X
X/* Given speed, returns number of moves this turn. -RAK- */
X/* NOTE: Player must always move at least once per iteration, */
X/* a slowed player is handled by moving monsters faster */
Xstatic int movement_rate(speed)
Xregister int16 speed;
X{
X if (speed > 0)
X {
X if (py.flags.rest != 0)
X return 1;
X else
X return speed;
X }
X else
X {
X /* speed must be negative here */
X return ((turn % (2 - speed)) == 0);
X }
X}
X
X
X/* Makes sure a new creature gets lit up. -CJS- */
Xstatic int check_mon_lite(y, x)
Xint y, x;
X{
X register int monptr;
X
X monptr = cave[y][x].cptr;
X if (monptr <= 1)
X return FALSE;
X else
X {
X update_mon(monptr);
X return m_list[monptr].ml;
X }
X}
X
X
X/* Choose correct directions for monster movement -RAK- */
Xstatic void get_moves(monptr, mm)
Xint monptr;
Xregister int *mm;
X{
X int y, ay, x, ax, move_val;
X
X y = m_list[monptr].fy - char_row;
X x = m_list[monptr].fx - char_col;
X if (y < 0)
X {
X move_val = 8;
X ay = -y;
X }
X else
X {
X move_val = 0;
X ay = y;
X }
X if (x > 0)
X {
X move_val += 4;
X ax = x;
X }
X else
X ax = -x;
X /* this has the advantage of preventing the diamond maneuvre, also faster */
X if (ay > (ax << 1))
X move_val += 2;
X else if (ax > (ay << 1))
X move_val++;
X switch(move_val)
X {
X case 0:
X mm[0] = 9;
X if (ay > ax)
X {
X mm[1] = 8;
X mm[2] = 6;
X mm[3] = 7;
X mm[4] = 3;
X }
X else
X {
X mm[1] = 6;
X mm[2] = 8;
X mm[3] = 3;
X mm[4] = 7;
X }
X break;
X case 1: case 9:
X mm[0] = 6;
X if (y < 0)
X {
X mm[1] = 3;
X mm[2] = 9;
X mm[3] = 2;
X mm[4] = 8;
X }
X else
X {
X mm[1] = 9;
X mm[2] = 3;
X mm[3] = 8;
X mm[4] = 2;
X }
X break;
X case 2: case 6:
X mm[0] = 8;
X if (x < 0)
X {
X mm[1] = 9;
X mm[2] = 7;
X mm[3] = 6;
X mm[4] = 4;
X }
X else
X {
X mm[1] = 7;
X mm[2] = 9;
X mm[3] = 4;
X mm[4] = 6;
X }
X break;
X case 4:
X mm[0] = 7;
X if (ay > ax)
X {
X mm[1] = 8;
X mm[2] = 4;
X mm[3] = 9;
X mm[4] = 1;
X }
X else
X {
X mm[1] = 4;
X mm[2] = 8;
X mm[3] = 1;
X mm[4] = 9;
X }
X break;
X case 5: case 13:
X mm[0] = 4;
X if (y < 0)
X {
X mm[1] = 1;
X mm[2] = 7;
X mm[3] = 2;
X mm[4] = 8;
X }
X else
X {
X mm[1] = 7;
X mm[2] = 1;
X mm[3] = 8;
X mm[4] = 2;
X }
X break;
X case 8:
X mm[0] = 3;
X if (ay > ax)
X {
X mm[1] = 2;
X mm[2] = 6;
X mm[3] = 1;
X mm[4] = 9;
X }
X else
X {
X mm[1] = 6;
X mm[2] = 2;
X mm[3] = 9;
X mm[4] = 1;
X }
X break;
X case 10: case 14:
X mm[0] = 2;
X if (x < 0)
X {
X mm[1] = 3;
X mm[2] = 1;
X mm[3] = 6;
X mm[4] = 4;
X }
X else
X {
X mm[1] = 1;
X mm[2] = 3;
X mm[3] = 4;
X mm[4] = 6;
X }
X break;
X case 12:
X mm[0] = 1;
X if (ay > ax)
X {
X mm[1] = 2;
X mm[2] = 4;
X mm[3] = 3;
X mm[4] = 7;
X }
X else
X {
X mm[1] = 4;
X mm[2] = 2;
X mm[3] = 7;
X mm[4] = 3;
X }
X break;
X }
X}
X
X
X/* Make an attack on the player (chuckle.) -RAK- */
Xstatic void make_attack(monptr)
Xint monptr;
X{
X int attype, adesc, adice, asides;
X int i, j, damage, flag, attackn, notice, visible;
X int32 gold;
X int8u *attstr;
X vtype cdesc, tmp_str, ddesc;
X register creature_type *r_ptr;
X monster_type *m_ptr;
X register struct misc *p_ptr;
X register struct flags *f_ptr;
X register inven_type *i_ptr;
X#ifdef ATARIST_MWC
X int32u holder;
X#endif
X
X if (death) /* don't beat a dead body! */
X return;
X
X m_ptr = &m_list[monptr];
X r_ptr = &c_list[m_ptr->mptr];
X if (!m_ptr->ml)
X (void) strcpy(cdesc, "It ");
X else
X (void) sprintf(cdesc, "The %s ", r_ptr->name);
X /* For "DIED_FROM" string */
X#ifdef ATARIST_MWC
X holder = CM_WIN;
X if (holder & r_ptr->cmove)
X#else
X if (CM_WIN & r_ptr->cmove)
X#endif
X (void) sprintf(ddesc, "The %s", r_ptr->name);
X else if (is_a_vowel (r_ptr->name[0]))
X (void) sprintf(ddesc, "an %s", r_ptr->name);
X else
X (void) sprintf (ddesc, "a %s", r_ptr->name);
X /* End DIED_FROM */
X
X attackn = 0;
X attstr = r_ptr->damage;
X while ((*attstr != 0) && !death)
X {
X attype = monster_attacks[*attstr].attack_type;
X adesc = monster_attacks[*attstr].attack_desc;
X adice = monster_attacks[*attstr].attack_dice;
X asides = monster_attacks[*attstr].attack_sides;
X attstr++;
X flag = FALSE;
X if ((py.flags.protevil > 0) && (r_ptr->cdefense & CD_EVIL) &&
X ((py.misc.lev + 1) > r_ptr->level))
X {
X if (m_ptr->ml)
X c_recall[m_ptr->mptr].r_cdefense |= CD_EVIL;
X attype = 99;
X adesc = 99;
X }
X p_ptr = &py.misc;
X switch(attype)
X {
X case 1: /*Normal attack */
X if (test_hit(60, (int)r_ptr->level, 0, p_ptr->pac+p_ptr->ptoac,
X CLA_MISC_HIT))
X flag = TRUE;
X break;
X case 2: /*Lose Strength*/
X if (test_hit(-3, (int)r_ptr->level, 0, p_ptr->pac+p_ptr->ptoac,
X CLA_MISC_HIT))
X flag = TRUE;
X break;
X case 3: /*Confusion attack*/
X if (test_hit(10, (int)r_ptr->level, 0, p_ptr->pac+p_ptr->ptoac,
X CLA_MISC_HIT))
X flag = TRUE;
X break;
X case 4: /*Fear attack */
X if (test_hit(10, (int)r_ptr->level, 0, p_ptr->pac+p_ptr->ptoac,
X CLA_MISC_HIT))
X flag = TRUE;
X break;
X case 5: /*Fire attack */
X if (test_hit(10, (int)r_ptr->level, 0, p_ptr->pac+p_ptr->ptoac,
X CLA_MISC_HIT))
X flag = TRUE;
X break;
X case 6: /*Acid attack */
X if (test_hit(0, (int)r_ptr->level, 0, p_ptr->pac+p_ptr->ptoac,
X CLA_MISC_HIT))
X flag = TRUE;
X break;
X case 7: /*Cold attack */
X if (test_hit(10, (int)r_ptr->level, 0, p_ptr->pac+p_ptr->ptoac,
X CLA_MISC_HIT))
X flag = TRUE;
X break;
X case 8: /*Lightning attack*/
X if (test_hit(10, (int)r_ptr->level, 0, p_ptr->pac+p_ptr->ptoac,
X CLA_MISC_HIT))
X flag = TRUE;
X break;
X case 9: /*Corrosion attack*/
X if (test_hit(0, (int)r_ptr->level, 0, p_ptr->pac+p_ptr->ptoac,
X CLA_MISC_HIT))
X flag = TRUE;
X break;
X case 10: /*Blindness attack*/
X if (test_hit(2, (int)r_ptr->level, 0, p_ptr->pac+p_ptr->ptoac,
X CLA_MISC_HIT))
X flag = TRUE;
X break;
X case 11: /*Paralysis attack*/
X if (test_hit(2, (int)r_ptr->level, 0, p_ptr->pac+p_ptr->ptoac,
X CLA_MISC_HIT))
X flag = TRUE;
X break;
X case 12: /*Steal Money */
X if ((test_hit(5, (int)r_ptr->level, 0, (int)py.misc.lev,
X CLA_MISC_HIT))
X && (py.misc.au > 0))
X flag = TRUE;
X break;
X case 13: /*Steal Object */
X if ((test_hit(2, (int)r_ptr->level, 0, (int)py.misc.lev,
X CLA_MISC_HIT))
X && (inven_ctr > 0))
X flag = TRUE;
X break;
X case 14: /*Poison */
X if (test_hit(5, (int)r_ptr->level, 0, p_ptr->pac+p_ptr->ptoac,
X CLA_MISC_HIT))
X flag = TRUE;
X break;
X case 15: /*Lose dexterity*/
X if (test_hit(0, (int)r_ptr->level, 0, p_ptr->pac+p_ptr->ptoac,
X CLA_MISC_HIT))
X flag = TRUE;
X break;
X case 16: /*Lose constitution*/
X if (test_hit(0, (int)r_ptr->level, 0, p_ptr->pac+p_ptr->ptoac,
X CLA_MISC_HIT))
X flag = TRUE;
X break;
X case 17: /*Lose intelligence*/
X if (test_hit(2, (int)r_ptr->level, 0, p_ptr->pac+p_ptr->ptoac,
X CLA_MISC_HIT))
X flag = TRUE;
X break;
X case 18: /*Lose wisdom*/
X if (test_hit(2, (int)r_ptr->level, 0, p_ptr->pac+p_ptr->ptoac,
X CLA_MISC_HIT))
X flag = TRUE;
X break;
X case 19: /*Lose experience*/
X if (test_hit(5, (int)r_ptr->level, 0, p_ptr->pac+p_ptr->ptoac,
X CLA_MISC_HIT))
X flag = TRUE;
X break;
X case 20: /*Aggravate monsters*/
X flag = TRUE;
X break;
X case 21: /*Disenchant */
X if (test_hit(20, (int)r_ptr->level, 0, p_ptr->pac+p_ptr->ptoac,
X CLA_MISC_HIT))
X flag = TRUE;
X break;
X case 22: /*Eat food */
X if (test_hit(5, (int)r_ptr->level, 0, p_ptr->pac+p_ptr->ptoac,
X CLA_MISC_HIT))
X flag = TRUE;
X break;
X case 23: /*Eat light */
X if (test_hit(5, (int)r_ptr->level, 0, p_ptr->pac+p_ptr->ptoac,
X CLA_MISC_HIT))
X flag = TRUE;
X break;
X case 24: /*Eat charges */
X if ((test_hit(15, (int)r_ptr->level, 0, p_ptr->pac+p_ptr->ptoac,
X CLA_MISC_HIT)) &&
X (inven_ctr > 0)) /* check to make sure an object exists */
X flag = TRUE;
X break;
X case 99:
X flag = TRUE;
X break;
X default:
X break;
X }
X if (flag)
X {
X /* can not strcat to cdesc because the creature may have
X multiple attacks */
X disturb (1, 0);
X (void) strcpy(tmp_str, cdesc);
X switch(adesc)
X {
X case 1: msg_print(strcat(tmp_str, "hits you.")); break;
X case 2: msg_print(strcat(tmp_str, "bites you.")); break;
X case 3: msg_print(strcat(tmp_str, "claws you.")); break;
X case 4: msg_print(strcat(tmp_str, "stings you.")); break;
X case 5: msg_print(strcat(tmp_str, "touches you.")); break;
X#if 0
X case 6: msg_print(strcat(tmp_str, "kicks you.")); break;
X#endif
X case 7: msg_print(strcat(tmp_str, "gazes at you.")); break;
X case 8: msg_print(strcat(tmp_str, "breathes on you.")); break;
X case 9: msg_print(strcat(tmp_str, "spits on you.")); break;
X case 10: msg_print(strcat(tmp_str,"makes a horrible wail."));break;
X#if 0
X case 11: msg_print(strcat(tmp_str, "embraces you.")); break;
X#endif
X case 12: msg_print(strcat(tmp_str, "crawls on you.")); break;
X case 13:
X msg_print(strcat(tmp_str, "releases a cloud of spores.")); break;
X case 14: msg_print(strcat(tmp_str, "begs you for money.")); break;
X case 15: msg_print("You've been slimed!"); break;
X case 16: msg_print(strcat(tmp_str, "crushes you.")); break;
X case 17: msg_print(strcat(tmp_str, "tramples you.")); break;
X case 18: msg_print(strcat(tmp_str, "drools on you.")); break;
X case 19:
X switch(randint(9))
X {
X case 1: msg_print(strcat(tmp_str, "insults you!")); break;
X case 2:
X msg_print(strcat(tmp_str, "insults your mother!")); break;
X case 3:
X msg_print(strcat(tmp_str, "gives you the finger!")); break;
X case 4: msg_print(strcat(tmp_str, "humiliates you!")); break;
X case 5: msg_print(strcat(tmp_str, "wets on your leg!")); break;
X case 6: msg_print(strcat(tmp_str, "defiles you!")); break;
X case 7: msg_print(strcat(tmp_str, "dances around you!"));break;
X case 8:
X msg_print(strcat(tmp_str, "makes obscene gestures!")); break;
X case 9: msg_print(strcat(tmp_str, "moons you!!!")); break;
X }
X break;
X case 99: msg_print(strcat(tmp_str, "is repelled.")); break;
X default: break;
X }
X
X notice = TRUE;
X /* always fail to notice attack if creature invisible, set notice
X and visible here since creature may be visible when attacking
X and then teleport afterwards (becoming effectively invisible) */
X if (!m_ptr->ml)
X {
X visible = FALSE;
X notice = FALSE;
X }
X else
X visible = TRUE;
X
X damage = damroll (adice, asides);
X switch(attype)
X {
X case 1: /*Normal attack */
X /* round half-way case down */
X damage -= ((p_ptr->pac+p_ptr->ptoac) * damage) / 200;
X take_hit(damage, ddesc);
X break;
X case 2: /*Lose Strength*/
X take_hit(damage, ddesc);
X if (py.flags.sustain_str)
X msg_print("You feel weaker for a moment, but it passes.");
X else if (randint(2) == 1)
X {
X msg_print("You feel weaker.");
X (void) dec_stat (A_STR);
X }
X else
X notice = FALSE;
X break;
X case 3: /*Confusion attack*/
X f_ptr = &py.flags;
X take_hit(damage, ddesc);
X if (randint(2) == 1)
X {
X if (f_ptr->confused < 1)
X {
X msg_print("You feel confused.");
X f_ptr->confused += randint((int)r_ptr->level);
X }
X else
X notice = FALSE;
X f_ptr->confused += 3;
X }
X else
X notice = FALSE;
X break;
X case 4: /*Fear attack */
X f_ptr = &py.flags;
X take_hit(damage, ddesc);
X if (player_saves())
X msg_print("You resist the effects!");
X else if (f_ptr->afraid < 1)
X {
X msg_print("You are suddenly afraid!");
X f_ptr->afraid += 3 + randint((int)r_ptr->level);
X }
X else
X {
X f_ptr->afraid += 3;
X notice = FALSE;
X }
X break;
X case 5: /*Fire attack */
X msg_print("You are enveloped in flames!");
X fire_dam(damage, ddesc);
X break;
X case 6: /*Acid attack */
X msg_print("You are covered in acid!");
X acid_dam(damage, ddesc);
X break;
X case 7: /*Cold attack */
X msg_print("You are covered with frost!");
X cold_dam(damage, ddesc);
X break;
X case 8: /*Lightning attack*/
X msg_print("Lightning strikes you!");
X light_dam(damage, ddesc);
X break;
X case 9: /*Corrosion attack*/
X msg_print("A stinging red gas swirls about you.");
X corrode_gas(ddesc);
X take_hit(damage, ddesc);
X break;
X case 10: /*Blindness attack*/
X f_ptr = &py.flags;
X take_hit(damage, ddesc);
X if (f_ptr->blind < 1)
X {
X f_ptr->blind += 10 + randint((int)r_ptr->level);
X msg_print("Your eyes begin to sting.");
X }
X else
X {
X f_ptr->blind += 5;
X notice = FALSE;
X }
X break;
X case 11: /*Paralysis attack*/
X f_ptr = &py.flags;
X take_hit(damage, ddesc);
X if (player_saves())
X msg_print("You resist the effects!");
X else if (f_ptr->paralysis < 1)
X {
X if (f_ptr->free_act)
X msg_print("You are unaffected.");
X else
X {
X f_ptr->paralysis = randint((int)r_ptr->level) + 3;
X msg_print("You are paralyzed.");
X }
X }
X else
X notice = FALSE;
X break;
X case 12: /*Steal Money */
X if ((py.flags.paralysis < 1) &&
X (randint(124) < py.stats.use_stat[A_DEX]))
X msg_print("You quickly protect your money pouch!");
X else
X {
X gold = (p_ptr->au/10) + randint(25);
X if (gold > p_ptr->au)
X p_ptr->au = 0;
X else
X p_ptr->au -= gold;
X msg_print("Your purse feels lighter.");
X prt_gold();
X }
X if (randint(2) == 1)
X {
X msg_print("There is a puff of smoke!");
X teleport_away(monptr, MAX_SIGHT);
X }
X break;
X case 13: /*Steal Object */
X if ((py.flags.paralysis < 1) &&
X (randint(124) < py.stats.use_stat[A_DEX]))
X msg_print("You grab hold of your backpack!");
X else
X {
X i = randint(inven_ctr) - 1;
X inven_destroy(i);
X msg_print("Your backpack feels lighter.");
X }
X if (randint(2) == 1)
X {
X msg_print("There is a puff of smoke!");
X teleport_away(monptr, MAX_SIGHT);
X }
X break;
X case 14: /*Poison */
X f_ptr = &py.flags;
X take_hit(damage, ddesc);
X msg_print("You feel very sick.");
X f_ptr->poisoned += randint((int)r_ptr->level)+5;
X break;
X case 15: /*Lose dexterity */
X f_ptr = &py.flags;
X take_hit(damage, ddesc);
X if (f_ptr->sustain_dex)
X msg_print("You feel clumsy for a moment, but it passes.");
X else
X {
X msg_print("You feel more clumsy.");
X (void) dec_stat (A_DEX);
X }
X break;
X case 16: /*Lose constitution */
X f_ptr = &py.flags;
X take_hit(damage, ddesc);
X if (f_ptr->sustain_con)
X msg_print("Your body resists the effects of the disease.");
X else
X {
X msg_print("Your health is damaged!");
X (void) dec_stat (A_CON);
X }
X break;
X case 17: /*Lose intelligence */
X f_ptr = &py.flags;
X take_hit(damage, ddesc);
X msg_print("You have trouble thinking clearly.");
X if (f_ptr->sustain_int)
X msg_print("But your mind quickly clears.");
X else
X (void) dec_stat (A_INT);
X break;
X case 18: /*Lose wisdom */
X f_ptr = &py.flags;
X take_hit(damage, ddesc);
X if (f_ptr->sustain_wis)
X msg_print("Your wisdom is sustained.");
X else
X {
X msg_print("Your wisdom is drained.");
X (void) dec_stat (A_WIS);
X }
X break;
X case 19: /*Lose experience */
X msg_print("You feel your life draining away!");
X lose_exp(damage + (py.misc.exp / 100)*MON_DRAIN_LIFE);
X break;
X case 20: /*Aggravate monster*/
X (void) aggravate_monster(20);
X break;
X case 21: /*Disenchant */
X flag = FALSE;
X switch(randint(7))
X {
X case 1: i = INVEN_WIELD; break;
X case 2: i = INVEN_BODY; break;
X case 3: i = INVEN_ARM; break;
X case 4: i = INVEN_OUTER; break;
X case 5: i = INVEN_HANDS; break;
X case 6: i = INVEN_HEAD; break;
X case 7: i = INVEN_FEET; break;
X }
X i_ptr = &inventory[i];
X if (i_ptr->tohit > 0)
X {
X i_ptr->tohit -= randint(2);
X /* don't send it below zero */
X if (i_ptr->tohit < 0)
X i_ptr->tohit = 0;
X flag = TRUE;
X }
X if (i_ptr->todam > 0)
X {
X i_ptr->todam -= randint(2);
X /* don't send it below zero */
X if (i_ptr->todam < 0)
X i_ptr->todam = 0;
X flag = TRUE;
X }
X if (i_ptr->toac > 0)
X {
X i_ptr->toac -= randint(2);
X /* don't send it below zero */
X if (i_ptr->toac < 0)
X i_ptr->toac = 0;
X flag = TRUE;
X }
X if (flag)
X {
X msg_print("There is a static feeling in the air.");
X calc_bonuses ();
X }
X else
X notice = FALSE;
X break;
X case 22: /*Eat food */
X if (find_range(TV_FOOD, TV_NEVER, &i, &j))
X {
X inven_destroy(i);
X msg_print ("It got at your rations!");
X }
X else
X notice = FALSE;
X break;
X case 23: /*Eat light */
X i_ptr = &inventory[INVEN_LIGHT];
X if (i_ptr->p1 > 0)
X {
X i_ptr->p1 -= (250 + randint(250));
X if (i_ptr->p1 < 1) i_ptr->p1 = 1;
X if (py.flags.blind < 1)
X msg_print("Your light dims.");
X else
X notice = FALSE;
X }
X else
X notice = FALSE;
X break;
X case 24: /*Eat charges */
X i = randint(inven_ctr) - 1;
X j = r_ptr->level;
X i_ptr = &inventory[i];
X if (((i_ptr->tval == TV_STAFF) || (i_ptr->tval == TV_WAND))
X && (i_ptr->p1 > 0))
X {
X m_ptr->hp += j*i_ptr->p1;
X i_ptr->p1 = 0;
X if (! known2_p (i_ptr))
X add_inscribe (i_ptr, ID_EMPTY);
X msg_print("Energy drains from your pack!");
X }
X else
X notice = FALSE;
X break;
X case 99:
X notice = FALSE;
X break;
X default:
X notice = FALSE;
X break;
X }
X
X /* Moved here from mon_move, so that monster only confused if it
X actually hits. A monster that has been repelled has not hit
X the player, so it should not be confused. */
X if (py.flags.confuse_monster && adesc != 99)
X {
X msg_print("Your hands stop glowing.");
X py.flags.confuse_monster = FALSE;
X if ((randint(MAX_MONS_LEVEL) < r_ptr->level) ||
X (CD_NO_SLEEP & r_ptr->cdefense))
X (void) sprintf(tmp_str, "%sis unaffected.", cdesc);
X else
X {
X (void) sprintf(tmp_str, "%sappears confused.", cdesc);
X m_ptr->confused = TRUE;
X }
X msg_print(tmp_str);
X if (visible && !death && randint(4) == 1)
X c_recall[m_ptr->mptr].r_cdefense |= r_ptr->cdefense &
X CD_NO_SLEEP;
X }
X
X /* increase number of attacks if notice true, or if visible and had
X previously noticed the attack (in which case all this does is
X help player learn damage), note that in the second case do
X not increase attacks if creature repelled (no damage done) */
X if ((notice ||
X (visible && c_recall[m_ptr->mptr].r_attacks[attackn] != 0 &&
X attype != 99))
X && c_recall[m_ptr->mptr].r_attacks[attackn] < MAX_UCHAR)
X c_recall[m_ptr->mptr].r_attacks[attackn]++;
X if (death && c_recall[m_ptr->mptr].r_deaths < MAX_SHORT)
X c_recall[m_ptr->mptr].r_deaths++;
X }
X else
X {
X if ((adesc >= 1 && adesc <= 3) || (adesc == 6))
X {
X disturb (1, 0);
X (void) strcpy(tmp_str, cdesc);
X msg_print(strcat(tmp_str, "misses you."));
X }
X }
X if (attackn < MAX_MON_NATTACK-1)
X attackn++;
X else
X break;
X }
X}
X
X
X/* Make the move if possible, five choices -RAK- */
Xstatic void make_move(monptr, mm, rcmove)
Xint monptr;
Xint *mm;
Xint32u *rcmove;
X{
X int i, newy, newx, do_turn, do_move, stuck_door;
X int32u movebits;
X register cave_type *c_ptr;
X register monster_type *m_ptr;
X register inven_type *t_ptr;
X#ifdef ATARIST_MWC
X int32u holder;
X#endif
X
X i = 0;
X do_turn = FALSE;
X do_move = FALSE;
X m_ptr = &m_list[monptr];
X movebits = c_list[m_ptr->mptr].cmove;
X do
X {
X /* Get new position */
X newy = m_ptr->fy;
X newx = m_ptr->fx;
X (void) mmove(mm[i], &newy, &newx);
X c_ptr = &cave[newy][newx];
X if (c_ptr->fval != BOUNDARY_WALL)
X {
X /* Floor is open? */
X if (c_ptr->fval <= MAX_OPEN_SPACE)
X do_move = TRUE;
X /* Creature moves through walls? */
X#ifdef ATARIST_MWC
X else if (movebits & (holder = CM_PHASE))
X#else
X else if (movebits & CM_PHASE)
X#endif
X {
X do_move = TRUE;
X#ifdef ATARIST_MWC
X *rcmove |= holder;
X#else
X *rcmove |= CM_PHASE;
X#endif
X }
X /* Creature can open doors? */
X else if (c_ptr->tptr != 0)
X {
X t_ptr = &t_list[c_ptr->tptr];
X#ifdef ATARIST_MWC
X if (movebits & (holder = CM_OPEN_DOOR))
X#else
X if (movebits & CM_OPEN_DOOR)
X#endif
X { /* Creature can open doors. */
X stuck_door = FALSE;
X if (t_ptr->tval == TV_CLOSED_DOOR)
X {
X do_turn = TRUE;
X if (t_ptr->p1 == 0) /* Closed doors */
X do_move = TRUE;
X else if (t_ptr->p1 > 0) /* Locked doors */
X {
X if (randint((m_ptr->hp+1)*(50+t_ptr->p1)) <
X 40*(m_ptr->hp-10-t_ptr->p1))
X t_ptr->p1 = 0;
X }
X else if (t_ptr->p1 < 0) /* Stuck doors */
X {
X if (randint((m_ptr->hp+1)*(50-t_ptr->p1)) <
X 40*(m_ptr->hp-10+t_ptr->p1))
X {
X msg_print("You hear a door burst open!");
X disturb (1, 0);
X stuck_door = TRUE;
X do_move = TRUE;
X }
X }
X }
X else if (t_ptr->tval == TV_SECRET_DOOR)
X {
X do_turn = TRUE;
X do_move = TRUE;
X }
X if (do_move)
X {
X invcopy(t_ptr, OBJ_OPEN_DOOR);
X if (stuck_door) /* 50% chance of breaking door */
X t_ptr->p1 = 1 - randint(2);
X c_ptr->fval = CORR_FLOOR;
X lite_spot(newy, newx);
X#ifdef ATARIST_MWC
X *rcmove |= holder;
X#else
X *rcmove |= CM_OPEN_DOOR;
X#endif
X do_move = FALSE;
X }
X }
X else
X { /* Creature can not open doors, must bash them */
X if (t_ptr->tval == TV_CLOSED_DOOR)
X {
X do_turn = TRUE;
X if (randint((m_ptr->hp+1)*(80+abs(t_ptr->p1))) <
X 40*(m_ptr->hp-20-abs(t_ptr->p1)))
X {
X invcopy(t_ptr, OBJ_OPEN_DOOR);
X /* 50% chance of breaking door */
X t_ptr->p1 = 1 - randint(2);
X c_ptr->fval = CORR_FLOOR;
X lite_spot(newy, newx);
X msg_print ("You hear a door burst open!");
X disturb (1, 0);
X }
X }
X }
X }
X /* Glyph of warding present? */
X if (do_move && (c_ptr->tptr != 0) &&
X (t_list[c_ptr->tptr].tval == TV_VIS_TRAP) &&
X (t_list[c_ptr->tptr].subval == 99))
X {
X if (randint(OBJ_RUNE_PROT) < c_list[m_ptr->mptr].level)
X {
X if ((newy==char_row) && (newx==char_col))
X msg_print("The rune of protection is broken!");
X (void) delete_object(newy, newx);
X }
X else
X {
X do_move = FALSE;
X /* If the creature moves only to attack, */
X /* don't let it move if the glyph prevents */
X /* it from attacking */
X if (movebits & CM_ATTACK_ONLY)
X do_turn = TRUE;
X }
X }
X /* Creature has attempted to move on player? */
X if (do_move)
X if (c_ptr->cptr == 1)
X {
X /* if the monster is not lit, must call update_mon, it may
X be faster than character, and hence could have just
X moved next to character this same turn */
X if (!m_ptr->ml)
X update_mon(monptr);
X make_attack(monptr);
X do_move = FALSE;
X do_turn = TRUE;
X }
X /* Creature is attempting to move on other creature? */
X else if ((c_ptr->cptr > 1) &&
X ((newy != m_ptr->fy) ||
X (newx != m_ptr->fx)))
X {
X /* Creature eats other creatures? */
X#ifdef ATARIST_MWC
X if ((movebits & (holder = CM_EATS_OTHER)) &&
X#else
X if ((movebits & CM_EATS_OTHER) &&
X#endif
X (c_list[m_ptr->mptr].mexp >=
X c_list[m_list[c_ptr->cptr].mptr].mexp))
X {
X if (m_list[c_ptr->cptr].ml)
X#ifdef ATARIST_MWC
X *rcmove |= holder;
X#else
X *rcmove |= CM_EATS_OTHER;
X#endif
X /* It ate an already processed monster. Handle normally. */
X if (monptr < c_ptr->cptr)
X delete_monster((int) c_ptr->cptr);
X /* If it eats this monster, an already processed monster
X will take its place, causing all kinds of havoc. Delay
X the kill a bit. */
X else
X fix1_delete_monster((int) c_ptr->cptr);
X }
X else
X do_move = FALSE;
X }
X /* Creature has been allowed move. */
X if (do_move)
X {
X /* Pick up or eat an object */
X#ifdef ATARIST_MWC
X if (movebits & (holder = CM_PICKS_UP))
X#else
X if (movebits & CM_PICKS_UP)
X#endif
X {
X c_ptr = &cave[newy][newx];
X
X if ((c_ptr->tptr != 0)
X && (t_list[c_ptr->tptr].tval <= TV_MAX_OBJECT))
X {
X#ifdef ATARIST_MWC
X *rcmove |= holder;
X#else
X *rcmove |= CM_PICKS_UP;
X#endif
X (void) delete_object(newy, newx);
X }
X }
X /* Move creature record */
X move_rec((int)m_ptr->fy, (int)m_ptr->fx, newy, newx);
X if (m_ptr->ml)
X {
X m_ptr->ml = FALSE;
X lite_spot ((int)m_ptr->fy, (int)m_ptr->fx);
X }
X m_ptr->fy = newy;
X m_ptr->fx = newx;
X m_ptr->cdis = distance (char_row, char_col, newy, newx);
X do_turn = TRUE;
X }
X }
X i++;
X /* Up to 5 attempts at moving, give up. */
X }
X while ((!do_turn) && (i < 5));
X}
X
X
X/* Creatures can cast spells too. (Dragon Breath) -RAK- */
X/* cast_spell = true if creature changes position */
X/* took_turn = true if creature casts a spell */
Xstatic void mon_cast_spell(monptr, took_turn)
Xint monptr;
Xint *took_turn;
X{
X int32u i;
X int y, x, chance, thrown_spell, r1;
X register int k;
X int spell_choice[30];
X vtype cdesc, outval, ddesc;
X register monster_type *m_ptr;
X register creature_type *r_ptr;
X#ifdef ATARIST_MWC
X int32u holder;
X#endif
X
X if (death)
X return;
X
X m_ptr = &m_list[monptr];
X r_ptr = &c_list[m_ptr->mptr];
X chance = (int)(r_ptr->spells & CS_FREQ);
X /* 1 in x chance of casting spell */
X if (randint(chance) != 1)
X *took_turn = FALSE;
X /* Must be within certain range */
X else if (m_ptr->cdis > MAX_SPELL_DIS)
X *took_turn = FALSE;
X /* Must have unobstructed Line-Of-Sight */
X else if (!los(char_row, char_col, (int)m_ptr->fy, (int)m_ptr->fx))
X *took_turn = FALSE;
X else /* Creature is going to cast a spell */
X {
X *took_turn = TRUE;
X /* Check to see if monster should be lit. */
X update_mon (monptr);
X /* Describe the attack */
X if (m_ptr->ml)
X (void) sprintf(cdesc, "The %s ", r_ptr->name);
X else
X (void) strcpy(cdesc, "It ");
X /* For "DIED_FROM" string */
X#ifdef ATARIST_MWC
X holder = CM_WIN;
X if (holder & r_ptr->cmove)
X#else
X if (CM_WIN & r_ptr->cmove)
X#endif
X (void) sprintf(ddesc, "The %s", r_ptr->name);
X else if (is_a_vowel (r_ptr->name[0]))
X (void) sprintf (ddesc, "an %s", r_ptr->name);
X else
X (void) sprintf(ddesc, "a %s", r_ptr->name);
X /* End DIED_FROM */
X
X /* Extract all possible spells into spell_choice */
X#ifdef ATARIST_MWC
X holder = ~CS_FREQ;
X i = (r_ptr->spells & holder);
X#else
X i = (r_ptr->spells & ~CS_FREQ);
X#endif
X k = 0;
X while (i != 0)
X {
X spell_choice[k] = bit_pos(&i);
X k++;
X }
X /* Choose a spell to cast */
X thrown_spell = spell_choice[randint(k) - 1];
X thrown_spell++;
X /* all except teleport_away() and drain mana spells always disturb */
X if (thrown_spell > 6 && thrown_spell != 17)
X disturb (1, 0);
X /* save some code/data space here, with a small time penalty */
X if ((thrown_spell < 14 && thrown_spell > 6) || (thrown_spell == 16))
X {
X (void) strcat(cdesc, "casts a spell.");
X msg_print(cdesc);
X }
X /* Cast the spell. */
X switch(thrown_spell)
X {
X case 5: /*Teleport Short*/
X teleport_away(monptr, 5);
X break;
X case 6: /*Teleport Long */
X teleport_away(monptr, MAX_SIGHT);
X break;
X case 7: /*Teleport To */
X teleport_to((int)m_ptr->fy, (int)m_ptr->fx);
X break;
X case 8: /*Light Wound */
X if (player_saves())
X msg_print("You resist the effects of the spell.");
X else
X take_hit(damroll(3, 8), ddesc);
X break;
X case 9: /*Serious Wound */
X if (player_saves())
X msg_print("You resist the effects of the spell.");
X else
X take_hit(damroll(8, 8), ddesc);
X break;
X case 10: /*Hold Person */
X if (py.flags.free_act)
X msg_print("You are unaffected.");
X else if (player_saves())
X msg_print("You resist the effects of the spell.");
X else if (py.flags.paralysis > 0)
X py.flags.paralysis += 2;
X else
X py.flags.paralysis = randint(5)+4;
X break;
X case 11: /*Cause Blindness*/
X if (player_saves())
X msg_print("You resist the effects of the spell.");
X else if (py.flags.blind > 0)
X py.flags.blind += 6;
X else
X py.flags.blind += 12 + randint(3);
X break;
X case 12: /*Cause Confuse */
X if (player_saves())
X msg_print("You resist the effects of the spell.");
X else if (py.flags.confused > 0)
X py.flags.confused += 2;
X else
X py.flags.confused = randint(5) + 3;
X break;
X case 13: /*Cause Fear */
X if (player_saves())
X msg_print("You resist the effects of the spell.");
X else if (py.flags.afraid > 0)
X py.flags.afraid += 2;
X else
X py.flags.afraid = randint(5) + 3;
X break;
X case 14: /*Summon Monster*/
X (void) strcat(cdesc, "magically summons a monster!");
X msg_print(cdesc);
X y = char_row;
X x = char_col;
X /* in case compact_monster() is called,it needs monptr */
X hack_monptr = monptr;
X (void) summon_monster(&y, &x, FALSE);
X hack_monptr = -1;
X update_mon ((int)cave[y][x].cptr);
X break;
X case 15: /*Summon Undead*/
X (void) strcat(cdesc, "magically summons an undead!");
X msg_print(cdesc);
X y = char_row;
X x = char_col;
X /* in case compact_monster() is called,it needs monptr */
X hack_monptr = monptr;
X (void) summon_undead(&y, &x);
X hack_monptr = -1;
X update_mon ((int)cave[y][x].cptr);
X break;
X case 16: /*Slow Person */
X if (py.flags.free_act)
X msg_print("You are unaffected.");
X else if (player_saves())
X msg_print("You resist the effects of the spell.");
X else if (py.flags.slow > 0)
X py.flags.slow += 2;
X else
X py.flags.slow = randint(5) + 3;
X break;
X case 17: /*Drain Mana */
X if (py.misc.cmana > 0)
X {
X disturb (1, 0);
X (void) sprintf(outval, "%sdraws psychic energy from you!",cdesc);
X msg_print(outval);
X if (m_ptr->ml)
X {
X (void) sprintf(outval, "%sappears healthier.", cdesc);
X msg_print(outval);
X }
X r1 = (randint((int)r_ptr->level) >> 1) + 1;
X if (r1 > py.misc.cmana)
X {
X r1 = py.misc.cmana;
X py.misc.cmana = 0;
X py.misc.cmana_frac = 0;
X }
X else
X py.misc.cmana -= r1;
X prt_cmana();
X m_ptr->hp += 6*(r1);
X }
X break;
X case 20: /*Breath Light */
X (void) strcat(cdesc, "breathes lightning.");
X msg_print(cdesc);
X breath(GF_LIGHTNING, char_row, char_col, (m_ptr->hp / 4), ddesc,
X monptr);
X break;
X case 21: /*Breath Gas */
X (void) strcat(cdesc, "breathes gas.");
X msg_print(cdesc);
X breath(GF_POISON_GAS, char_row, char_col, (m_ptr->hp / 3), ddesc,
X monptr);
X break;
X case 22: /*Breath Acid */
X (void) strcat(cdesc, "breathes acid.");
X msg_print(cdesc);
X breath(GF_ACID, char_row, char_col, (m_ptr->hp / 3), ddesc, monptr);
X break;
X case 23: /*Breath Frost */
X (void) strcat(cdesc, "breathes frost.");
X msg_print(cdesc);
X breath(GF_FROST, char_row, char_col, (m_ptr->hp / 3), ddesc, monptr);
X break;
X case 24: /*Breath Fire */
X (void) strcat(cdesc, "breathes fire.");
X msg_print(cdesc);
X breath(GF_FIRE, char_row, char_col, (m_ptr->hp / 3), ddesc, monptr);
X break;
X default:
X (void) strcat (cdesc, "cast unknown spell.");
X msg_print(cdesc);
X }
X /* End of spells */
X if (m_ptr->ml)
X {
X c_recall[m_ptr->mptr].r_spells |= 1L << (thrown_spell-1);
X if ((c_recall[m_ptr->mptr].r_spells & CS_FREQ) != CS_FREQ)
X c_recall[m_ptr->mptr].r_spells++;
X if (death && c_recall[m_ptr->mptr].r_deaths < MAX_SHORT)
X c_recall[m_ptr->mptr].r_deaths++;
X }
X }
X}
X
X
X/* Places creature adjacent to given location -RAK- */
X/* Rats and Flys are fun! */
Xint multiply_monster(y, x, cr_index, monptr)
Xint y, x, cr_index;
Xint monptr;
X{
X register int i, j, k;
X register cave_type *c_ptr;
X int result;
X#ifdef ATARIST_MWC
X int32u holder;
X#endif
X
X i = 0;
X do
X {
X j = y - 2 + randint(3);
X k = x - 2 + randint(3);
X /* don't create a new creature on top of the old one, that causes
X invincible/invisible creatures to appear */
X if (in_bounds(j, k) && (j != y || k != x))
X {
X c_ptr = &cave[j][k];
X if ((c_ptr->fval <= MAX_OPEN_SPACE) && (c_ptr->tptr == 0) &&
X (c_ptr->cptr != 1))
X {
X if (c_ptr->cptr > 1) /* Creature there already? */
X {
X /* Some critters are cannibalistic! */
X#ifdef ATARIST_MWC
X holder = CM_EATS_OTHER;
X if ((c_list[cr_index].cmove & holder)
X#else
X if ((c_list[cr_index].cmove & CM_EATS_OTHER)
X#endif
X /* Check the experience level -CJS- */
X && c_list[cr_index].mexp >=
X c_list[m_list[c_ptr->cptr].mptr].mexp)
X {
X /* It ate an already processed monster.Handle normally.*/
X if (monptr < c_ptr->cptr)
X delete_monster((int) c_ptr->cptr);
X /* If it eats this monster, an already processed mosnter
X will take its place, causing all kinds of havoc.
X Delay the kill a bit. */
X else
X fix1_delete_monster((int) c_ptr->cptr);
X
X /* in case compact_monster() is called,it needs monptr */
X hack_monptr = monptr;
X /* Place_monster() may fail if monster list full. */
X result = place_monster(j, k, cr_index, FALSE);
X hack_monptr = -1;
X if (! result)
X return FALSE;
X mon_tot_mult++;
X return check_mon_lite(j, k);
X }
X }
X else
X /* All clear, place a monster */
X {
X /* in case compact_monster() is called,it needs monptr */
X hack_monptr = monptr;
X /* Place_monster() may fail if monster list full. */
X result = place_monster(j, k, cr_index, FALSE);
X hack_monptr = -1;
X if (! result)
X return FALSE;
X mon_tot_mult++;
X return check_mon_lite(j, k);
X }
X }
X }
X i++;
X }
X while (i <= 18);
X return FALSE;
X}
X
X
X/* Move the critters about the dungeon -RAK- */
Xstatic void mon_move(monptr, rcmove)
Xint monptr;
Xint32u *rcmove;
X{
X register int i, j;
X int k, move_test, dir;
X#ifdef M_XENIX
X /* Avoid 'register' bug. */
X creature_type *r_ptr;
X#else
X register creature_type *r_ptr;
X#endif
X register monster_type *m_ptr;
X int mm[9];
X#ifdef ATARIST_MWC
X int32u holder;
X#endif
X int rest_val;
X
X m_ptr = &m_list[monptr];
X r_ptr = &c_list[m_ptr->mptr];
X /* Does the critter multiply? */
X /* rest could be negative, to be safe, only use mod with positive values. */
X rest_val = abs (py.flags.rest);
X#ifdef ATARIST_MWC
X holder = CM_MULTIPLY;
X if ((r_ptr->cmove & holder) && (MAX_MON_MULT >= mon_tot_mult) &&
X#else
X if ((r_ptr->cmove & CM_MULTIPLY) && (MAX_MON_MULT >= mon_tot_mult) &&
X#endif
X ((rest_val % MON_MULT_ADJ) == 0))
X {
X k = 0;
X for (i = m_ptr->fy-1; i <= m_ptr->fy+1; i++)
X for (j = m_ptr->fx-1; j <= m_ptr->fx+1; j++)
X if (in_bounds(i, j) && (cave[i][j].cptr > 1))
X k++;
X /* can't call randint with a value of zero, increment counter
X to allow creature multiplication */
X if (k == 0)
X k++;
X if ((k < 4) && (randint(k*MON_MULT_ADJ) == 1))
X if (multiply_monster((int)m_ptr->fy, (int)m_ptr->fx,
X (int)m_ptr->mptr, monptr))
X#ifdef ATARIST_MWC
X *rcmove |= holder;
X#else
X *rcmove |= CM_MULTIPLY;
X#endif
X }
X move_test = FALSE;
X
X /* if in wall, must immediately escape to a clear area */
X#ifdef ATARIST_MWC
X holder = CM_PHASE;
X if (!(r_ptr->cmove & holder) &&
X#else
X if (!(r_ptr->cmove & CM_PHASE) &&
X#endif
X (cave[m_ptr->fy][m_ptr->fx].fval >= MIN_CAVE_WALL))
X {
X /* If the monster is already dead, don't kill it again!
X This can happen for monsters moving faster than the player. They
X will get multiple moves, but should not if they die on the first
X move. This is only a problem for monsters stuck in rock. */
X if (m_ptr->hp < 0)
X return;
X
X k = 0;
X dir = 1;
X /* note direction of for loops matches direction of keypad from 1 to 9*/
X /* do not allow attack against the player */
X /* Must cast fy-1 to signed int, so that a nagative value of i will
X fail the comparison. */
X for (i = m_ptr->fy+1; i >= (int)(m_ptr->fy-1); i--)
X for (j = m_ptr->fx-1; j <= m_ptr->fx+1; j++)
X {
X if ((dir != 5) && (cave[i][j].fval <= MAX_OPEN_SPACE)
X && (cave[i][j].cptr != 1))
X mm[k++] = dir;
X dir++;
X }
X if (k != 0)
X {
X /* put a random direction first */
X dir = randint (k) - 1;
X i = mm[0];
X mm[0] = mm[dir];
X mm[dir] = i;
X make_move (monptr, mm, rcmove);
X /* this can only fail if mm[0] has a rune of protection */
X }
X /* if still in a wall, let it dig itself out, but also apply some
X more damage */
X if (cave[m_ptr->fy][m_ptr->fx].fval >= MIN_CAVE_WALL)
X {
X /* in case the monster dies, may need to call fix1_delete_monster()
X instead of delete_monsters() */
X hack_monptr = monptr;
X i = mon_take_hit(monptr, damroll (8, 8));
X hack_monptr = -1;
X if (i >= 0)
X {
X msg_print("You hear a scream muffled by rock!");
X prt_experience();
X }
X else
X {
X msg_print ("A creature digs itself out from the rock!");
X (void) twall ((int)m_ptr->fy, (int)m_ptr->fx, 1, 0);
X }
X }
X return; /* monster movement finished */
X }
X /* Creature is confused? Chance it becomes un-confused */
X else if (m_ptr->confused)
X {
X mm[0] = randint(9);
X mm[1] = randint(9);
X mm[2] = randint(9);
X mm[3] = randint(9);
X mm[4] = randint(9);
X /* don't move him if he is not supposed to move! */
X if (!(r_ptr->cmove & CM_ATTACK_ONLY))
X make_move(monptr, mm, rcmove);
X if (randint(8) == 1)
X m_ptr->confused = FALSE;
X move_test = TRUE;
X }
X /* Creature may cast a spell */
X else if (r_ptr->spells != 0)
X mon_cast_spell(monptr, &move_test);
X if (!move_test)
X {
X /* 75% random movement */
X if ((r_ptr->cmove & CM_75_RANDOM) && (randint(100) < 75))
X {
X mm[0] = randint(9);
X mm[1] = randint(9);
X mm[2] = randint(9);
X mm[3] = randint(9);
X mm[4] = randint(9);
X *rcmove |= CM_75_RANDOM;
X make_move(monptr, mm, rcmove);
X }
X /* 40% random movement */
X else if ((r_ptr->cmove & CM_40_RANDOM) && (randint(100) < 40))
X {
X mm[0] = randint(9);
X mm[1] = randint(9);
X mm[2] = randint(9);
X mm[3] = randint(9);
X mm[4] = randint(9);
X *rcmove |= CM_40_RANDOM;
X make_move(monptr, mm, rcmove);
X }
X /* 20% random movement */
X else if ((r_ptr->cmove & CM_20_RANDOM) && (randint(100) < 20))
X {
X mm[0] = randint(9);
X mm[1] = randint(9);
X mm[2] = randint(9);
X mm[3] = randint(9);
X mm[4] = randint(9);
X *rcmove |= CM_20_RANDOM;
X make_move(monptr, mm, rcmove);
X }
X /* Normal movement */
X else if (r_ptr->cmove & CM_MOVE_NORMAL)
X {
X if (randint(200) == 1)
X {
X mm[0] = randint(9);
X mm[1] = randint(9);
X mm[2] = randint(9);
X mm[3] = randint(9);
X mm[4] = randint(9);
X }
X else
X get_moves(monptr, mm);
X *rcmove |= CM_MOVE_NORMAL;
X make_move(monptr, mm, rcmove);
X }
X /* Attack, but don't move */
X else if (r_ptr->cmove & CM_ATTACK_ONLY)
X {
X if (m_ptr->cdis < 2)
X {
X get_moves(monptr, mm);
X make_move(monptr, mm, rcmove);
X }
X else
X /* Learn that the monster does does not move when it should have
X moved, but didn't. */
X *rcmove |= CM_ATTACK_ONLY;
X }
X else if ((r_ptr->cmove & CM_ONLY_MAGIC) && (m_ptr->cdis < 2))
X {
X /* A little hack for Quylthulgs, so that one will eventually notice
X that they have no physical attacks. */
X if (c_recall[m_ptr->mptr].r_attacks[0] < MAX_UCHAR)
X c_recall[m_ptr->mptr].r_attacks[0]++;
X /* Another little hack for Quylthulgs, so that one can eventually
X learn their speed. */
X if (c_recall[m_ptr->mptr].r_attacks[0] > 20)
X c_recall[m_ptr->mptr].r_cmove |= CM_ONLY_MAGIC;
X }
X }
X}
X
X
X/* Creatures movement and attacking are done from here -RAK- */
Xvoid creatures(attack)
Xint attack;
X{
X register int i, k;
X register monster_type *m_ptr;
X recall_type *r_ptr;
X int32u notice, rcmove;
X int wake, ignore;
X vtype cdesc;
X#ifdef ATARIST_MWC
X int32u holder;
X#endif
X
X /* Process the monsters */
X for (i = mfptr - 1; i >= MIN_MONIX && !death; i--)
X {
X m_ptr = &m_list[i];
X /* Get rid of an eaten/breathed on monster. Note: Be sure not to
X process this monster. This is necessary because we can't delete
X monsters while scanning the m_list here. */
X if (m_ptr->hp < 0)
X {
X fix2_delete_monster(i);
X continue;
X }
X
X m_ptr->cdis = distance(char_row, char_col,
X (int)m_ptr->fy, (int)m_ptr->fx);
X if (attack) /* Attack is argument passed to CREATURE*/
X {
X k = movement_rate(m_ptr->cspeed);
X if (k <= 0)
X update_mon(i);
X else
X while (k > 0)
X {
X k--;
X wake = FALSE;
X ignore = FALSE;
X rcmove = 0;
X if (m_ptr->ml || (m_ptr->cdis <= c_list[m_ptr->mptr].aaf)
X /* Monsters trapped in rock must be given a turn also,
X so that they will die/dig out immediately. */
X#ifdef ATARIST_MWC
X || ((! (c_list[m_ptr->mptr].cmove & (holder = CM_PHASE)))
X#else
X || ((! (c_list[m_ptr->mptr].cmove & CM_PHASE))
X#endif
X && cave[m_ptr->fy][m_ptr->fx].fval >= MIN_CAVE_WALL))
X {
X if (m_ptr->csleep > 0)
X if (py.flags.aggravate)
X m_ptr->csleep = 0;
X else if ((py.flags.rest == 0 && py.flags.paralysis < 1)
X || (randint(50) == 1))
X {
X notice = randint(1024);
X if (notice*notice*notice <= (1L << (29 - py.misc.stl)))
X {
X m_ptr->csleep -= (100 / m_ptr->cdis);
X if (m_ptr->csleep > 0)
X ignore = TRUE;
X else
X {
X wake = TRUE;
X /* force it to be exactly zero */
X m_ptr->csleep = 0;
X }
X }
X }
X if (m_ptr->stunned != 0)
X {
X /* NOTE: Balrog = 100*100 = 10000, it always
X recovers instantly */
X if (randint(5000) < c_list[m_ptr->mptr].level
X * c_list[m_ptr->mptr].level)
X m_ptr->stunned = 0;
X else
X m_ptr->stunned--;
X if (m_ptr->stunned == 0)
X {
X if (!m_ptr->ml)
X (void) strcpy(cdesc, "It ");
X else
X (void) sprintf(cdesc, "The %s ",
X c_list[m_ptr->mptr].name);
X msg_print(strcat(cdesc,
X "recovers and glares at you."));
X }
X }
X if ((m_ptr->csleep == 0) && (m_ptr->stunned == 0))
X mon_move (i, &rcmove);
X }
X
X update_mon(i);
X if (m_ptr->ml)
X {
X r_ptr = &c_recall[m_ptr->mptr];
X if (wake)
X {
X if (r_ptr->r_wake < MAX_UCHAR)
X r_ptr->r_wake++;
X }
X else if (ignore)
X {
X if (r_ptr->r_ignore < MAX_UCHAR)
X r_ptr->r_ignore++;
X }
X r_ptr->r_cmove |= rcmove;
X }
X }
X }
X else
X update_mon(i);
X
X /* Get rid of an eaten/breathed on monster. This is necessary because
X we can't delete monsters while scanning the m_list here. This
X monster may have been killed during mon_move(). */
X if (m_ptr->hp < 0)
X {
X fix2_delete_monster(i);
X continue;
X }
X }
X /* End processing monsters */
X}
END_OF_FILE
if test 46325 -ne `wc -c <'source/creature.c'`; then
echo shar: \"'source/creature.c'\" unpacked with wrong size!
fi
# end of 'source/creature.c'
fi
if test -f 'util/printit/pr_monst.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'util/printit/pr_monst.c'\"
else
echo shar: Extracting \"'util/printit/pr_monst.c'\" \(6250 characters\)
sed "s/^X//" >'util/printit/pr_monst.c' <<'END_OF_FILE'
X/* util/printit/pr_monst.c: pretty print monster info
X
X Copyright (c) 1990-1992 Carlton Hommel, James E. Wilson
X
X This software may be copied and distributed for educational, research, and
X not for profit purposes provided that this copyright and statement are
X included in all such copies. */
X
X#include "config.h"
X#include "constant.h"
X#include "types.h"
X
Xextern creature_type c_list[];
X
Xmain()
X{
X int i;
X creature_type *c;
X
X printf(" Lvl(Ep) [ HD, AC]\tspd aaf/{sleep}\t\t Name");
X printf("\tDamage(special) <Defense> {Moves} /* Spells */\n");
X for (i=0; i<MAX_CREATURES; i++) {
X c = &c_list[i];
X call_it(c);
X }
X return 0;
X}
X
Xcall_it(c)
Xcreature_type *c;
X{
X /* Line 1 */
X printf("'%c' ", c->cchar);
X printf("%2d", c->level);
X printf("(%4d) ", c->mexp);
X printf("[%2dd%d, %2d]\t", c->hd[0], c->hd[1], c->ac);
X
X printf("%2d ", ((int)c->speed)-10);
X printf("%2d/", c->aaf);
X printf("{%d}\t", c->sleep*10);
X
X printf("%20.20s\t", c->name);
X print_damage(c->damage);
X printf("\t");
X
X print_flags_cdefense(c->cdefense);
X printf(" ");
X print_flags_cmove(c->cmove);
X printf(" ");
X print_flags_spells(c->spells);
X
X printf("\n");
X
X}
X
Xprint_damage(attstr)
Xint8u attstr[4];
X{
X int attype, adesc, adice, asides;
X int count;
X char damstr[50];
X
X extern struct m_attack_type monster_attacks[];
X
X for (count=0; count<4; count++) {
X if (attstr[count] == 0) continue;
X attype = monster_attacks[attstr[count]].attack_type;
X adesc = monster_attacks[attstr[count]].attack_desc;
X adice = monster_attacks[attstr[count]].attack_dice;
X asides = monster_attacks[attstr[count]].attack_sides;
X
X sprintf(damstr, "%dd%d", adice, asides);
X switch(attype) {
X case 1: printf("%s ", damstr); break;
X case 2: printf("%s(-Str) ", damstr); break;
X case 3: printf("%s(Conf) ", damstr); break;
X case 4: printf("%s(Fear) ", damstr); break;
X case 5: printf("%s(Fire) ", damstr); break;
X case 6: printf("%s(Acid) ", damstr); break;
X case 7: printf("%s(Cold) ", damstr); break;
X case 8: printf("%s(Zap) ", damstr); break;
X case 9: printf("%s(Acid) ", damstr); break;
X case 10: printf("%s(Blind) ", damstr); break;
X case 11: printf("%s(Paral) ", damstr); break;
X case 12: printf("%s(-Money) ", damstr); break;
X case 13: printf("%s(-Object) ", damstr);break;
X case 14: printf("%s(Poison) ", damstr); break;
X case 15: printf("%s(-Dex) ", damstr); break;
X case 16: printf("%s(-Con ) ", damstr); break;
X case 17: printf("%s(-Int ) ", damstr); break;
X case 18: printf("%s(-Wis) ", damstr); break;
X case 19: printf("%s(-Exp) ", damstr); break;
X case 20: printf("%s(Aggr) ", damstr); break;
X case 21: printf("%s(-Magic) ", damstr); break;
X case 22: printf("%s(-Food) ", damstr); break;
X case 23: printf("%s(-Light) ", damstr); break;
X case 24: printf("%s(-Charges) ", damstr);break;
X default:
X case 99: printf("%s(Blank) ", damstr); break;
X }
X
X }
X}
X
Xprint_flags_spells(spells)
Xunsigned long spells;
X{
X int count;
X unsigned long mask;
X int chance;
X
X if (spells == 0)
X return;
X
X printf("/* ");
X chance = (int)spells & CS_FREQ;
X printf("%2.1f%% ", 1.0 / chance * 100.0);
X for (count=4,mask=0x010; count<32; mask <<= 1, count++) {
X switch (spells & mask) {
X case CS_TEL_SHORT: printf("CS_TEL_SHORT ");break;
X case CS_TEL_LONG: printf("CS_TEL_LONG "); break;
X case CS_TEL_TO: printf("CS_TEL_TO "); break;
X case CS_LGHT_WND: printf("CS_LGHT_WND "); break;
X case CS_SER_WND: printf("CS_SER_WND "); break;
X case CS_HOLD_PER: printf("CS_HOLD_PER "); break;
X case CS_BLIND: printf("CS_BLIND "); break;
X case CS_CONFUSE: printf("CS_CONFUSE "); break;
X case CS_FEAR: printf("CS_FEAR "); break;
X case CS_SUMMON_MON: printf("CS_SUMMON_MON ");break;
X case CS_SUMMON_UND: printf("CS_SUMMON_UND ");break;
X case CS_SLOW_PER: printf("CS_SLOW_PER "); break;
X case CS_DRAIN_MANA: printf("CS_DRAIN_MANA ");break;
X case CS_BR_LIGHT: printf("CS_BR_LIGHT "); break;
X case CS_BR_GAS: printf("CS_BR_GAS "); break;
X case CS_BR_ACID: printf("CS_BR_ACID "); break;
X case CS_BR_FROST: printf("CS_BR_FROST "); break;
X case CS_BR_FIRE: printf("CS_BR_FIRE "); break;
X }
X }
X printf("*/");
X}
X
Xprint_flags_cmove(cmove)
Xunsigned long cmove;
X{
X int count;
X unsigned long mask;
X
X if (cmove == 0)
X return;
X
X printf("<");
X for (count=0,mask=0x01; count<32; mask <<= 1, count++) {
X switch (cmove & mask) {
X case CM_ATTACK_ONLY: printf("CM_ATTACK_ONLY "); break;
X case CM_MOVE_NORMAL: /*printf("CM_MOVE_NORMAL ");*/ break;
X case CM_20_RANDOM: printf("CM_20_RANDOM "); break;
X case CM_40_RANDOM: printf("CM_40_RANDOM "); break;
X case CM_75_RANDOM: printf("CM_75_RANDOM "); break;
X case CM_INVISIBLE: printf("CM_INVISIBLE "); break;
X case CM_OPEN_DOOR: printf("CM_OPEN_DOOR "); break;
X case CM_PHASE: printf("CM_PHASE "); break;
X case CM_EATS_OTHER: printf("CM_EATS_OTHER "); break;
X case CM_PICKS_UP: printf("CM_PICKS_UP "); break;
X case CM_MULTIPLY: printf("CM_MULTIPLY "); break;
X case CM_CARRY_OBJ: printf("CM_CARRY_OTHER "); break;
X case CM_CARRY_GOLD: printf("CM_CARRY_GOLD "); break;
X case CM_60_RANDOM: printf("CM_60_RANDOM "); break;
X case CM_90_RANDOM: printf("CM_90_RANDOM "); break;
X case CM_1D2_OBJ: printf("CM_1D2_OBJ "); break;
X case CM_2D2_OBJ: printf("CM_2D2_OBJ "); break;
X case CM_4D2_OBJ: printf("CM_4D2_OBJ "); break;
X case CM_WIN: printf("CM_WIN "); break;
X }
X }
X printf(">");
X}
X
Xprint_flags_cdefense(cdefense)
Xunsigned int cdefense;
X{
X int count;
X unsigned int mask;
X
X if (cdefense == 0)
X return;
X
X printf("{");
X for (count=0,mask=0x01; count<16; mask <<= 1, count++) {
X switch (cdefense & mask) {
X case CD_DRAGON: printf("CD_DRAGON "); break;
X case CD_ANIMAL: printf("CD_ANIMAL "); break;
X case CD_EVIL: printf("CD_EVIL "); break;
X case CD_UNDEAD: printf("CD_UNDEAD "); break;
X case CD_FROST: printf("CD_FROST "); break;
X case CD_FIRE: printf("CD_FIRE "); break;
X case CD_POISON: printf("CD_POISON "); break;
X case CD_ACID: printf("CD_ACID "); break;
X case CD_LIGHT: printf("CD_LIGHT "); break;
X case CD_STONE: printf("CD_STONE "); break;
X case CD_NO_SLEEP: printf("CD_NO_SLEEP "); break;
X case CD_INFRA: printf("CD_INFRA "); break;
X case CD_MAX_HP: printf("CD_MAX_HP "); break;
X }
X }
X printf("}");
X}
END_OF_FILE
if test 6250 -ne `wc -c <'util/printit/pr_monst.c'`; then
echo shar: \"'util/printit/pr_monst.c'\" unpacked with wrong size!
fi
# end of 'util/printit/pr_monst.c'
fi
echo shar: End of archive 6 \(of 39\).
cp /dev/null ark6isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 39 archives.
echo "Now run "bldfiles.sh" to build split files"
rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
echo You still need to unpack the following archives:
echo " " ${MISSING}
fi
## End of shell archive.
exit 0