home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 January
/
usenetsourcesnewsgroupsinfomagicjanuary1994.iso
/
sources
/
games
/
volume16
/
nethack31
/
part21
< prev
next >
Wrap
Internet Message Format
|
1993-02-01
|
59KB
Path: uunet!news.tek.com!master!saab!billr
From: billr@saab.CNA.TEK.COM (Bill Randle)
Newsgroups: comp.sources.games
Subject: v16i021: nethack31 - display oriented dungeons & dragons (Ver. 3.1), Part21/108
Message-ID: <4309@master.CNA.TEK.COM>
Date: 29 Jan 93 20:43:59 GMT
Sender: news@master.CNA.TEK.COM
Lines: 2094
Approved: billr@saab.CNA.TEK.COM
Xref: uunet comp.sources.games:1578
Submitted-by: izchak@linc.cis.upenn.edu (Izchak Miller)
Posting-number: Volume 16, Issue 21
Archive-name: nethack31/Part21
Supersedes: nethack3p9: Volume 10, Issue 46-102
Environment: Amiga, Atari, Mac, MS-DOS, OS2, Unix, VMS, X11
#! /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 21 (of 108)."
# Contents: dat/Healer.des src/mon.c
# Wrapped by billr@saab on Wed Jan 27 16:08:54 1993
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'dat/Healer.des' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'dat/Healer.des'\"
else
echo shar: Extracting \"'dat/Healer.des'\" \(11204 characters\)
sed "s/^X//" >'dat/Healer.des' <<'END_OF_FILE'
X# SCCS Id: @(#)Healer.des 3.1 93/01/23
X# Copyright (c) 1989 by Jean-Christophe Collet
X# Copyright (c) 1991 by M. Stephenson
X# NetHack may be freely redistributed. See license for details.
X#
X# The "start" level for the quest.
X#
X# Here you meet your (besieged) class leader, Hippocrates
X# and receive your quest assignment.
X#
XMAZE: "H-start",' '
XFLAGS: noteleport,hardfloor
XGEOMETRY:center,center
XMAP
XPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP
XPPPP........PPPP.....PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP.P..PPPPP......PPPPPPPP
XPPP..........PPPP...PPPPP.........................PPPP..PPPPP........PPPPPPP
XPP............PPPPPPPP..............................PPP...PPPP......PPPPPPPP
XP.....PPPPPPPPPPPPPPP................................PPPPPPPPPPPPPPPPPPPPPPP
XPPPP....PPPPPPPPPPPP...................................PPPPP.PPPPPPPPPPPPPPP
XPPPP........PPPPP.........-----------------------........PP...PPPPPPP.....PP
XPPP............PPPPP....--|.|......S..........S.|--.....PPPP.PPPPPPP.......P
XPPPP..........PPPPP.....|.S.|......-----------|S|.|......PPPPPP.PPP.......PP
XPPPPPP......PPPPPP......|.|.|......|...|......|.|.|.....PPPPPP...PP.......PP
XPPPPPPPPPPPPPPPPPPP.....+.|.|......S.\.S......|.|.+......PPPPPP.PPPP.......P
XPPP...PPPPP...PPPP......|.|.|......|...|......|.|.|.......PPPPPPPPPPP.....PP
XPP.....PPP.....PPP......|.|S|-----------......|.S.|......PPPPPPPPPPPPPPPPPPP
XPPP..PPPPP...PPPP.......--|.S..........S......|.|--.....PPPPPPPPP....PPPPPPP
XPPPPPPPPPPPPPPPP..........-----------------------..........PPPPP..........PP
XPPPPPPPPPPPPPPPPP........................................PPPPPP............P
XPPP.............PPPP...................................PPP..PPPP..........PP
XPP...............PPPPP................................PPPP...PPPP........PPP
XPPP.............PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP....PPPPPP
XPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP
XENDMAP
X# Random Monsters
XRANDOM_MONSTERS: 'r', ';', 'D'
X# Dungeon Description
XREGION:(00,00,75,19),lit,"ordinary"
X# Stairs
XSTAIR:(37,9),down
X# Portal arrival point
XBRANCH:(04,12,04,12),(0,0,0,0)
X# Doors
XDOOR:locked,(24,10)
XDOOR:closed,(26,08)
XDOOR:closed,(27,12)
XDOOR:locked,(28,13)
XDOOR:closed,(35,07)
XDOOR:locked,(35,10)
XDOOR:locked,(39,10)
XDOOR:closed,(39,13)
XDOOR:locked,(46,07)
XDOOR:closed,(47,08)
XDOOR:closed,(48,12)
XDOOR:locked,(50,10)
X# Hippocrates
XMONSTER:'@',"Hippocrates",(37,10)
X# The treasure of Hippocrates
XOBJECT:'(',"chest",(37,10)
X# intern guards for the audience chamber
XMONSTER:'@',"intern",(29,08)
XMONSTER:'@',"intern",(29,09)
XMONSTER:'@',"intern",(29,10)
XMONSTER:'@',"intern",(29,11)
XMONSTER:'@',"intern",(40,09)
XMONSTER:'@',"intern",(40,10)
XMONSTER:'@',"intern",(40,11)
XMONSTER:'@',"intern",(40,13)
X# Non diggable walls
XNON_DIGGABLE:(00,00,75,19)
X# Random traps
XTRAP:random,random
XTRAP:random,random
XTRAP:random,random
XTRAP:random,random
XTRAP:random,random
XTRAP:random,random
X# Monsters on siege duty.
XMONSTER: 'r',"rabid rat",random
XMONSTER: 'r',"rabid rat",random
XMONSTER: 'r',"rabid rat",random
XMONSTER: 'r',"rabid rat",random
XMONSTER: 'r',"rabid rat",random
XMONSTER: 'r',"rabid rat",random
XMONSTER: 'r',"rabid rat",random
XMONSTER: 'r',"rabid rat",random
XMONSTER: 'r',"rabid rat",random
XMONSTER: 'r',"rabid rat",random
XMONSTER: ';',"giant eel",random
XMONSTER: ';', random, random
XMONSTER: 'D',random,random,hostile
XMONSTER: 'D',random,random,hostile
XMONSTER: 'D',random,random,hostile
XMONSTER: 'D',random,random,hostile
XMONSTER: 'D',random,random,hostile
X
X#
X# The "locate" level for the quest.
X#
X# Here you have to find the Temple of Coeus to go
X# further towards your assigned quest.
X#
X
XMAZE: "H-locate",' '
XFLAGS: hardfloor
X#
XINIT_MAP: '.' , 'P', true , true , lit , false
XGEOMETRY:center,center
XMAP
XPPPPPPPPPPPPP.......PPPPPPPPPPP
XPPPPPPPP...............PPPPPPPP
XPPPP.....-------------...PPPPPP
XPPPPP....|.S.........|....PPPPP
XPPP......+.|.........|...PPPPPP
XPPP......+.|.........|..PPPPPPP
XPPPP.....|.S.........|..PPPPPPP
XPPPPP....-------------....PPPPP
XPPPPPPPP...............PPPPPPPP
XPPPPPPPPPPP........PPPPPPPPPPPP
XENDMAP
X# Dungeon Description
XREGION:(03,00,26,09),lit,"ordinary"
XREGION:(12,03,20,06),lit,"temple"
X# Doors
XDOOR:closed,(09,04)
XDOOR:closed,(09,05)
XDOOR:locked,(11,03)
XDOOR:locked,(11,06)
X# Stairs
XSTAIR:(04,04),up
XSTAIR:(20,06),down
X# Non diggable walls
XNON_DIGGABLE:(11,02,21,07)
X# Altar in the temple.
XALTAR:(13,05), chaos, shrine
X# Objects
XOBJECT:random,random,random
XOBJECT:random,random,random
XOBJECT:random,random,random
XOBJECT:random,random,random
XOBJECT:random,random,random
XOBJECT:random,random,random
XOBJECT:random,random,random
XOBJECT:random,random,random
XOBJECT:random,random,random
XOBJECT:random,random,random
XOBJECT:random,random,random
XOBJECT:random,random,random
XOBJECT:random,random,random
XOBJECT:random,random,random
XOBJECT:random,random,random
X# Random traps
XTRAP:random,random
XTRAP:random,random
XTRAP:random,random
XTRAP:random,random
XTRAP:random,random
XTRAP:random,random
X# Random monsters.
XMONSTER:'r',"rabid rat",random
XMONSTER:'r',"rabid rat",random
XMONSTER:'r',"rabid rat",random
XMONSTER:'r',"rabid rat",random
XMONSTER:'r',"rabid rat",random
XMONSTER:'r',"rabid rat",random
XMONSTER:'r',"rabid rat",random
XMONSTER:'r',"rabid rat",random
XMONSTER:'r',"rabid rat",random
XMONSTER:'r',"rabid rat",random
XMONSTER:'r',"rabid rat",random
XMONSTER:'r',"rabid rat",random
XMONSTER:'r',"rabid rat",random
XMONSTER:'r',"rabid rat",random
XMONSTER:'r',"rabid rat",random
XMONSTER:'r',"rabid rat",random
XMONSTER:'r',"rabid rat",random
XMONSTER:'r',random,random,hostile
XMONSTER:';',"giant eel",random
XMONSTER:';',"giant eel",random
XMONSTER:';',"giant eel",random
XMONSTER:';',"giant eel",random
XMONSTER:';',"giant eel",random
XMONSTER:';',"electric eel",random
XMONSTER:';',"electric eel",random
XMONSTER:';',"kraken",random
XMONSTER:';',random, random,hostile
XMONSTER:';',random, random,hostile
XMONSTER: 'D',random,random,hostile
XMONSTER: 'D',random,random,hostile
XMONSTER: 'D',random,random,hostile
XMONSTER: 'D',random,random,hostile
XMONSTER: 'D',random,random,hostile
X
X#
X# The "goal" level for the quest.
X#
X# Here you meet Cyclops your nemesis monster. You have to
X# defeat Cyclops in combat to gain the artifact you have
X# been assigned to retrieve.
X#
X
XMAZE: "H-goal", 'P'
X#
XINIT_MAP: '.' , 'P' , false , true , lit , false
XGEOMETRY:center,center
XMAP
X.P....................................PP.
XPP.......PPPPPPP....PPPPPPP....PPPP...PP.
X...PPPPPPP....PPPPPPP.....PPPPPP..PPP...P
X...PP..............................PPP...
X..PP..............................PP.....
X..PP..............................PPP....
X..PPP..............................PP....
X.PPP..............................PPPP...
X...PP............................PPP...PP
X..PPPP...PPPPP..PPPP...PPPPP.....PP...PP.
XP....PPPPP...PPPP..PPPPP...PPPPPPP...PP..
XPPP..................................PPP.
XENDMAP
X# Random Monsters
XRANDOM_MONSTERS: 'r', ';', 'D'
X# Dungeon Description
XREGION:(00,00,40,11),lit,"ordinary"
X# Stairs
XSTAIR:(38,10),up
X# Non diggable walls
XNON_DIGGABLE:(00,00,40,11)
X# Objects
XOBJECT:')',"quarterstaff",(20,06),blessed,0,"The Staff of Aesculapius"
XOBJECT:'/',"lightning",(20,06)
XOBJECT:random,random,random
XOBJECT:random,random,random
XOBJECT:random,random,random
XOBJECT:random,random,random
XOBJECT:random,random,random
XOBJECT:random,random,random
XOBJECT:random,random,random
XOBJECT:random,random,random
XOBJECT:random,random,random
XOBJECT:random,random,random
XOBJECT:random,random,random
XOBJECT:random,random,random
XOBJECT:random,random,random
XOBJECT:random,random,random
X# Random traps
XTRAP:random,random
XTRAP:random,random
XTRAP:random,random
XTRAP:random,random
XTRAP:random,random
XTRAP:random,random
X# Random monsters.
XMONSTER:'H',"Cyclops",(20,06),hostile
XMONSTER:'r',"rabid rat",random
XMONSTER:'r',"rabid rat",random
XMONSTER:'r',"rabid rat",random
XMONSTER:'r',"rabid rat",random
XMONSTER:'r',"rabid rat",random
XMONSTER:'r',"rabid rat",random
XMONSTER:'r',"rabid rat",random
XMONSTER:'r',"rabid rat",random
XMONSTER:'r',"rabid rat",random
XMONSTER:'r',"rabid rat",random
XMONSTER:'r',"rabid rat",random
XMONSTER:'r',"rabid rat",random
XMONSTER:'r',"rabid rat",random
XMONSTER:'r',"rabid rat",random
XMONSTER:'r',"rabid rat",random
XMONSTER:'r',"rabid rat",random
XMONSTER:'r',random,random,hostile
XMONSTER:'r',random,random,hostile
XMONSTER:';',"giant eel",random
XMONSTER:';',"giant eel",random
XMONSTER:';',"giant eel",random
XMONSTER:';',"giant eel",random
XMONSTER:';',"giant eel",random
XMONSTER:';',"giant eel",random
XMONSTER:';',"electric eel",random
XMONSTER:';',"electric eel",random
XMONSTER:';',random,random,hostile
XMONSTER: 'D',random,random,hostile
XMONSTER: 'D',random,random,hostile
XMONSTER: 'D',random,random,hostile
XMONSTER: 'D',random,random,hostile
XMONSTER: 'D',random,random,hostile
X
X#
X# The "fill" levels for the quest.
X#
X# These levels are used to fill out any levels not occupied by specific
X# levels as defined above. "filla" is the upper filler, between the
X# start and locate levels, and "fillb" the lower between the locate
X# and goal levels.
X#
X
XMAZE: "H-filla" , 'P'
XINIT_MAP: '.' , 'P' , false , true , lit , false
XNOMAP
X# Random Monsters
XRANDOM_MONSTERS: 'r', ';', 'D'
X#
XSTAIR: random, up
XSTAIR: random, down
X#
XOBJECT: random, random, random
XOBJECT: random, random, random
XOBJECT: random, random, random
XOBJECT: random, random, random
XOBJECT: random, random, random
XOBJECT: random, random, random
XOBJECT: random, random, random
XOBJECT: random, random, random
X#
XMONSTER: 'r', "rabid rat", random
XMONSTER: 'r', "rabid rat", random
XMONSTER: 'r', "rabid rat", random
XMONSTER: 'r', "rabid rat", random
XMONSTER: 'r', random, random,hostile
XMONSTER: 'r', random, random,hostile
XMONSTER: ';', "giant eel", random
XMONSTER: ';', "giant eel", random
XMONSTER: ';', "electric eel", random
XMONSTER: 'D',random,random,hostile
XMONSTER: 'D',random,random,hostile
XMONSTER: 'D',random,random,hostile
XMONSTER: 'D',random,random,hostile
X#
XTRAP: random, random
XTRAP: random, random
XTRAP: random, random
XTRAP: random, random
X
XMAZE: "H-fillb" , 'P'
XINIT_MAP: '.' , 'P' , false , true , lit , false
XNOMAP
X# Random Monsters
XRANDOM_MONSTERS: 'r', ';', 'D'
X#
XSTAIR: random, up
XSTAIR: random, down
X#
XOBJECT: random, random, random
XOBJECT: random, random, random
XOBJECT: random, random, random
XOBJECT: random, random, random
XOBJECT: random, random, random
XOBJECT: random, random, random
XOBJECT: random, random, random
XOBJECT: random, random, random
XOBJECT: random, random, random
XOBJECT: random, random, random
XOBJECT: random, random, random
X#
XMONSTER: 'r', "rabid rat", random
XMONSTER: 'r', "rabid rat", random
XMONSTER: 'r', "rabid rat", random
XMONSTER: 'r', "rabid rat", random
XMONSTER: 'r', "rabid rat", random
XMONSTER: 'r', random, random,hostile
XMONSTER: 'r', random, random,hostile
XMONSTER: ';', "giant eel", random
XMONSTER: ';', "giant eel", random
XMONSTER: ';', "giant eel", random
XMONSTER: ';', "giant eel", random
XMONSTER: ';', "giant eel", random
XMONSTER: ';', "electric eel", random
XMONSTER: ';', "electric eel", random
XMONSTER: 'D',random,random,hostile
XMONSTER: 'D',random,random,hostile
XMONSTER: 'D',random,random,hostile
XMONSTER: 'D',random,random,hostile
X#
XTRAP: random, random
XTRAP: random, random
XTRAP: random, random
XTRAP: random, random
END_OF_FILE
if test 11204 -ne `wc -c <'dat/Healer.des'`; then
echo shar: \"'dat/Healer.des'\" unpacked with wrong size!
fi
# end of 'dat/Healer.des'
fi
if test -f 'src/mon.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'src/mon.c'\"
else
echo shar: Extracting \"'src/mon.c'\" \(42736 characters\)
sed "s/^X//" >'src/mon.c' <<'END_OF_FILE'
X/* SCCS Id: @(#)mon.c 3.1 93/01/19 */
X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
X/* NetHack may be freely redistributed. See license for details. */
X
X/* If you're using precompiled headers, you don't want this either */
X#ifdef MICROPORT_BUG
X#define MKROOM_H
X#endif
X
X#include "hack.h"
X#include "mfndpos.h"
X#include "edog.h"
X#include <ctype.h>
X
XSTATIC_DCL boolean FDECL(restrap,(struct monst *));
XSTATIC_DCL void NDECL(dmonsfree);
X
X#ifdef OVL1
X#define warnDelay 10
Xlong lastwarntime;
Xint lastwarnlev;
Xconst char *warnings[] = {
X "white", "pink", "red", "ruby", "purple", "black" };
X
Xstatic void NDECL(warn_effects);
X
X#endif /* OVL1 */
X
X#ifdef OVLB
Xstatic struct obj *FDECL(make_corpse,(struct monst *));
Xstatic void FDECL(m_detach,(struct monst *));
X
Xstruct monst *fdmon; /* chain of dead monsters, need not be saved */
X /* otherwise used only in priest.c */
X
X/* Creates a monster corpse, a "special" corpse, or nothing if it doesn't
X * leave corpses. Monsters which leave "special" corpses should have
X * G_NOCORPSE set in order to prevent wishing for one, finding tins of one,
X * etc....
X */
Xstatic struct obj *
Xmake_corpse(mtmp)
Xregister struct monst *mtmp;
X{
X register struct permonst *mdat = mtmp->data;
X int num;
X struct obj *obj = (struct obj *)0;
X int x = mtmp->mx, y = mtmp->my;
X int mndx = monsndx(mdat);
X
X switch(mndx) {
X case PM_GRAY_DRAGON:
X case PM_RED_DRAGON:
X case PM_ORANGE_DRAGON:
X case PM_WHITE_DRAGON:
X case PM_BLACK_DRAGON:
X case PM_BLUE_DRAGON:
X case PM_GREEN_DRAGON:
X case PM_YELLOW_DRAGON:
X /* Make dragon scales. This assumes that the order of the */
X /* dragons is the same as the order of the scales. */
X if (!rn2(3)) {
X obj = mksobj_at(GRAY_DRAGON_SCALES +
X monsndx(mdat)-PM_GRAY_DRAGON, x, y, FALSE);
X obj->spe = 0;
X obj->cursed = obj->blessed = FALSE;
X }
X goto default_1;
X
X case PM_WHITE_UNICORN:
X case PM_GRAY_UNICORN:
X case PM_BLACK_UNICORN:
X (void) mksobj_at(UNICORN_HORN, x, y, TRUE);
X goto default_1;
X case PM_LONG_WORM:
X (void) mksobj_at(WORM_TOOTH, x, y, TRUE);
X goto default_1;
X case PM_KOBOLD_MUMMY:
X case PM_GNOME_MUMMY:
X case PM_ORC_MUMMY:
X case PM_ELF_MUMMY:
X case PM_HUMAN_MUMMY:
X case PM_GIANT_MUMMY:
X case PM_ETTIN_MUMMY:
X (void) mksobj_at(MUMMY_WRAPPING, x, y, TRUE); /* and fall through */
X case PM_KOBOLD_ZOMBIE:
X case PM_GNOME_ZOMBIE:
X case PM_ORC_ZOMBIE:
X case PM_ELF_ZOMBIE:
X case PM_HUMAN_ZOMBIE:
X case PM_GIANT_ZOMBIE:
X case PM_ETTIN_ZOMBIE:
X switch (mndx) {
X case PM_KOBOLD_ZOMBIE:
X case PM_KOBOLD_MUMMY:
X num = PM_KOBOLD; break;
X case PM_GNOME_MUMMY:
X case PM_GNOME_ZOMBIE:
X num = PM_GNOME; break;
X case PM_ORC_MUMMY:
X case PM_ORC_ZOMBIE:
X num = PM_ORC; break;
X case PM_ELF_MUMMY:
X case PM_ELF_ZOMBIE:
X num = PM_ELF; break;
X case PM_HUMAN_MUMMY:
X case PM_HUMAN_ZOMBIE:
X num = PM_HUMAN; break;
X case PM_GIANT_MUMMY:
X case PM_GIANT_ZOMBIE:
X num = PM_GIANT; break;
X case PM_ETTIN_MUMMY:
X case PM_ETTIN_ZOMBIE:
X#ifdef GCC_WARN
X default:
X#endif
X num = PM_ETTIN; break;
X }
X obj = mkcorpstat(CORPSE, &mons[num], x, y, TRUE);
X obj->age -= 100; /* this is an *OLD* corpse */
X break;
X case PM_IRON_GOLEM:
X num = d(2,6);
X while (num--)
X obj = mksobj_at(IRON_CHAIN, x, y, TRUE);
X mtmp->mnamelth = 0;
X break;
X case PM_CLAY_GOLEM:
X obj = mksobj_at(ROCK, x, y, FALSE);
X obj->quan = (long)(rn2(20) + 50);
X obj->owt = weight(obj);
X mtmp->mnamelth = 0;
X break;
X case PM_STONE_GOLEM:
X obj = mkcorpstat(STATUE, mdat, x, y, FALSE);
X break;
X case PM_WOOD_GOLEM:
X num = d(2,4);
X while(num--) {
X obj = mksobj_at(QUARTERSTAFF, x, y, TRUE);
X if (obj && obj->oartifact) { /* don't allow this */
X artifact_exists(obj, ONAME(obj), FALSE);
X Strcpy(ONAME(obj), ""); obj->onamelth = 0;
X }
X }
X mtmp->mnamelth = 0;
X break;
X case PM_LEATHER_GOLEM:
X num = d(2,4);
X while(num--)
X obj = mksobj_at(LEATHER_ARMOR, x, y, TRUE);
X mtmp->mnamelth = 0;
X break;
X default_1:
X default:
X if (mdat->geno & G_NOCORPSE)
X return (struct obj *)0;
X else obj = mkcorpstat(CORPSE, mdat, x, y, TRUE);
X break;
X }
X /* All special cases should precede the G_NOCORPSE check */
X
X /* Note: oname() cannot be used generically for non-inventory objects
X * unless you fix the link from the previous object in the chains.
X * (Here we know it's the first one, so there was no link.)
X */
X if (mtmp->mnamelth) {
X obj = oname(obj, NAME(mtmp), 0);
X fobj = obj;
X level.objects[x][y] = obj;
X }
X stackobj(fobj);
X newsym(x, y);
X return obj;
X}
X
X#endif /* OVLB */
X#ifdef OVL1
X
Xstatic void
Xwarn_effects()
X{
X if (warnlevel == 100) {
X if(!Blind &&
X (warnlevel > lastwarnlev || moves > lastwarntime + warnDelay)) {
X Your("%s %s!", aobjnam(uwep, "glow"),
X Hallucination ? hcolor() : light_blue);
X lastwarnlev = warnlevel;
X lastwarntime = moves;
X }
X warnlevel = 0;
X return;
X }
X
X if(warnlevel >= SIZE(warnings))
X warnlevel = SIZE(warnings)-1;
X if(!Blind && warnlevel >= 0)
X if(warnlevel > lastwarnlev || moves > lastwarntime + warnDelay) {
X register const char *rr;
X
X lastwarntime = moves;
X lastwarnlev = warnlevel;
X switch((int) (Warning & (LEFT_RING | RIGHT_RING))) {
X case LEFT_RING:
X rr = Hallucination ? "left mood ring glows" : "left ring glows";
X break;
X case RIGHT_RING:
X rr = Hallucination ? "right mood ring glows"
X : "right ring glows";
X break;
X case LEFT_RING | RIGHT_RING:
X rr = Hallucination ? "mood rings glow" : "rings both glow";
X break;
X default:
X if (Hallucination)
X Your("spider-sense is tingling....");
X else
X You("feel apprehensive as you sense a %s flash.",
X warnings[warnlevel]);
X return;
X }
X Your("%s %s!", rr, Hallucination ? hcolor() : warnings[warnlevel]);
X }
X}
X
X/* check mtmp and water for compatibility, 0 (survived), 1 (drowned) */
Xint
Xminwater(mtmp)
Xregister struct monst *mtmp;
X{
X boolean inpool, infountain;
X
X inpool = is_pool(mtmp->mx,mtmp->my);
X infountain = IS_FOUNTAIN(levl[mtmp->mx][mtmp->my].typ);
X
X /* Gremlin multiplying won't go on forever since the hit points
X * keep going down, and when it gets to 1 hit point the clone
X * function will fail.
X */
X if(mtmp->data->mlet == S_GREMLIN && (inpool || infountain) && rn2(3)) {
X struct monst *mtmp2 = clone_mon(mtmp);
X
X if (mtmp2) {
X mtmp2->mhpmax = (mtmp->mhpmax /= 2);
X if(cansee(mtmp->mx,mtmp->my))
X pline("%s multiplies.", Monnam(mtmp));
X dryup(mtmp->mx,mtmp->my);
X }
X return (0);
X }
X if (inpool) {
X /* most monsters drown in pools */
X if (!is_flyer(mtmp->data) && !is_clinger(mtmp->data)
X && !is_swimmer(mtmp->data) && !magic_breathing(mtmp->data)) {
X if (cansee(mtmp->mx,mtmp->my))
X pline("%s drowns.", Monnam(mtmp));
X mondead(mtmp);
X return (1);
X }
X } else {
X /* but eels have a difficult time outside */
X if (mtmp->data->mlet == S_EEL) {
X if(mtmp->mhp > 1) mtmp->mhp--;
X mtmp->mflee = 1;
X mtmp->mfleetim += 2;
X }
X }
X return (0);
X}
X
Xvoid
Xmovemon()
X{
X register struct monst *mtmp;
X register boolean tametype = TRUE;
X
X warnlevel = 0;
X
X while(1) {
X /* Find a monster that we have not treated yet.
X * Note that mtmp or mtmp->nmon might get killed
X * while mtmp moves, so we cannot just walk down the
X * chain (even new monsters might get created!)
X *
X * Do tame monsters first. Necessary so that when the tame
X * monster attacks something, the something gets a chance to
X * attack the tame monster back (which it's permitted to do
X * only if it hasn't made its move yet).
X */
X for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
X if(mtmp->mlstmv < monstermoves &&
X ((mtmp->mtame>0) == tametype)) goto next_mon;
X if(tametype) {
X /* checked all tame monsters, now do other ones */
X tametype = FALSE;
X continue;
X }
X /* treated all monsters */
X break;
X
X next_mon:
X mtmp->mlstmv = monstermoves;
X
X if(mtmp->mhp <= 0) {
X impossible("Monster with zero hp?");
X mtmp->mhp = mtmp->mhpmax = 1; /* repair */
X }
X if (minwater(mtmp)) continue;
X
X if(mtmp->mblinded && !--mtmp->mblinded)
X mtmp->mcansee = 1;
X if(mtmp->mfrozen && !--mtmp->mfrozen)
X mtmp->mcanmove = 1;
X if(mtmp->mfleetim && !--mtmp->mfleetim)
X mtmp->mflee = 0;
X if (is_hider(mtmp->data)) {
X /* unwatched mimics and piercers may hide again [MRS] */
X if(restrap(mtmp)) continue;
X if(mtmp->m_ap_type == M_AP_FURNITURE ||
X mtmp->m_ap_type == M_AP_OBJECT)
X continue;
X if(mtmp->mundetected) continue;
X }
X if(mtmp->mspeed != MSLOW || !(moves%2)) {
X /* continue if the monster died fighting */
X if (Conflict && !mtmp->iswiz && mtmp->mcansee) {
X /* Note:
X * Conflict does not take effect in the first round.
X * Therefore, A monster when stepping into the area will
X * get to swing at you.
X *
X * The call to fightm() must be _last_. The monster might
X * have died if it returns 1.
X */
X if (couldsee(mtmp->mx,mtmp->my) &&
X (distu(mtmp->mx,mtmp->my) <= BOLT_LIM*BOLT_LIM) &&
X fightm(mtmp))
X continue; /* mon might have died */
X }
X if(dochugw(mtmp))
X /* otherwise just move the monster */
X continue;
X }
X if(mtmp->mspeed == MFAST && dochugw(mtmp))
X continue;
X }
X if(warnlevel > 0)
X warn_effects();
X
X dmonsfree(); /* remove all dead monsters */
X}
X
X#endif /* OVL1 */
X#ifdef OVLB
X
Xvoid
Xmeatgold(mtmp)
X register struct monst *mtmp;
X{
X register struct obj *otmp;
X
X /* If a pet, eating is handled separately, in dog.c */
X if (mtmp->mtame) return;
X
X /* Eats topmost metal object if it is there */
X for (otmp = level.objects[mtmp->mx][mtmp->my];
X otmp; otmp = otmp->nexthere)
X if (is_metallic(otmp) && touch_artifact(otmp,mtmp)) {
X if (cansee(mtmp->mx,mtmp->my) && flags.verbose)
X pline("%s eats %s!", Monnam(mtmp),
X distant_name(otmp,doname));
X else if (flags.soundok && flags.verbose)
X You("hear a crunching sound.");
X mtmp->meating = otmp->owt/2 + 1;
X /* Heal up to the object's weight in hp */
X if (mtmp->mhp < mtmp->mhpmax) {
X mtmp->mhp += objects[otmp->otyp].oc_weight;
X if (mtmp->mhp > mtmp->mhpmax) mtmp->mhp = mtmp->mhpmax;
X }
X if(otmp == uball) {
X unpunish();
X delobj(otmp);
X } else if(otmp == uchain)
X unpunish(); /* frees uchain */
X else
X delobj(otmp);
X /* Left behind a pile? */
X if(rnd(25) < 3) (void) mksobj_at(ROCK, mtmp->mx, mtmp->my, TRUE);
X newsym(mtmp->mx, mtmp->my);
X break;
X }
X}
X
Xvoid
Xmeatobj(mtmp) /* for gelatinous cubes */
X register struct monst *mtmp;
X{
X register struct obj *otmp, *otmp2;
X
X /* If a pet, eating is handled separately, in dog.c */
X if (mtmp->mtame) return;
X
X /* Eats organic objects, including cloth and wood, if there */
X /* Engulfs others, except huge rocks and metal attached to player */
X for (otmp = level.objects[mtmp->mx][mtmp->my]; otmp; otmp = otmp2) {
X otmp2 = otmp->nexthere;
X if(is_organic(otmp) && touch_artifact(otmp,mtmp)) {
X if (otmp->otyp == CORPSE && otmp->corpsenm == PM_COCKATRICE
X && !resists_ston(mtmp->data))
X continue;
X if (cansee(mtmp->mx,mtmp->my) && flags.verbose)
X pline("%s eats %s!", Monnam(mtmp),
X distant_name(otmp, doname));
X else if (flags.soundok && flags.verbose)
X You("hear a slurping sound.");
X /* Heal up to the object's weight in hp */
X if (mtmp->mhp < mtmp->mhpmax) {
X mtmp->mhp += objects[otmp->otyp].oc_weight;
X if (mtmp->mhp > mtmp->mhpmax) mtmp->mhp = mtmp->mhpmax;
X }
X delobj(otmp); /* munch */
X } else if (otmp->oclass != ROCK_CLASS &&
X otmp != uball && otmp != uchain) {
X if (cansee(mtmp->mx, mtmp->my) && flags.verbose)
X pline("%s engulfs %s.", Monnam(mtmp),
X distant_name(otmp,doname));
X freeobj(otmp);
X mpickobj(mtmp, otmp); /* slurp */
X }
X /* Engulf & devour is instant, so don't set meating */
X newsym(mtmp->mx, mtmp->my);
X }
X}
X
Xvoid
Xmpickgold(mtmp)
X register struct monst *mtmp;
X{
X register struct obj *gold;
X
X if ((gold = g_at(mtmp->mx, mtmp->my)) != 0) {
X mtmp->mgold += gold->quan;
X delobj(gold);
X if (cansee(mtmp->mx, mtmp->my) ) {
X if (flags.verbose && !mtmp->isgd)
X pline("%s picks up some gold.", Monnam(mtmp));
X newsym(mtmp->mx, mtmp->my);
X }
X }
X}
X
X/* Now includes giants which pick up enormous rocks. KAA */
Xvoid
Xmpickgems(mtmp)
X register struct monst *mtmp;
X{
X register struct obj *otmp;
X
X for(otmp = level.objects[mtmp->mx][mtmp->my]; otmp; otmp=otmp->nexthere)
X if(throws_rocks(mtmp->data) ? otmp->otyp == BOULDER :
X (otmp->oclass == GEM_CLASS &&
X objects[otmp->otyp].oc_material != MINERAL))
X if (touch_artifact(otmp,mtmp))
X if(mtmp->data->mlet != S_UNICORN
X || objects[otmp->otyp].oc_material == GEMSTONE){
X if (cansee(mtmp->mx,mtmp->my) && flags.verbose)
X pline("%s picks up %s.", Monnam(mtmp),
X distant_name(otmp, doname));
X freeobj(otmp);
X mpickobj(mtmp, otmp);
X if (otmp->otyp == BOULDER)
X unblock_point(otmp->ox,otmp->oy); /* vision */
X newsym(mtmp->mx, mtmp->my);
X return; /* pick only one object */
X }
X}
X
X#endif /* OVLB */
X#ifdef OVL2
X
Xvoid
Xmpickstuff(mtmp, str)
X register struct monst *mtmp;
X register const char *str;
X{
X register struct obj *otmp;
X
X/* prevent shopkeepers from leaving the door of their shop */
X if(mtmp->isshk && inhishop(mtmp)) return;
X
X for(otmp = level.objects[mtmp->mx][mtmp->my]; otmp; otmp=otmp->nexthere)
X/* Nymphs take everything. Most monsters don't pick up corpses. */
X if (
X#ifdef MUSE
X !str ? searches_for_item(mtmp,otmp) :
X#endif
X (index(str, otmp->oclass)
X && (otmp->otyp != CORPSE || mtmp->data->mlet == S_NYMPH))) {
X if (!touch_artifact(otmp,mtmp)) return;
X if (!can_carry(mtmp,otmp)) return;
X if (cansee(mtmp->mx,mtmp->my) && flags.verbose)
X pline("%s picks up %s.", Monnam(mtmp), doname(otmp));
X freeobj(otmp);
X mpickobj(mtmp, otmp);
X#ifdef MUSE
X m_dowear(mtmp, FALSE);
X#endif
X newsym(mtmp->mx, mtmp->my);
X return; /* pick only one object */
X }
X}
X
X#endif /* OVL2 */
X#ifdef OVL0
X
Xint
Xcurr_mon_load(mtmp)
Xregister struct monst *mtmp;
X{
X register int curload = 0;
X register struct obj *obj;
X
X for(obj = mtmp->minvent; obj; obj = obj->nobj) {
X if(obj->otyp != BOULDER || !throws_rocks(mtmp->data))
X curload += obj->owt;
X }
X
X return curload;
X}
X
Xint
Xmax_mon_load(mtmp)
Xregister struct monst *mtmp;
X{
X register long maxload;
X
X /* Base monster carrying capacity is equal to human maximum
X * carrying capacity, or half human maximum if not strong.
X * (for a polymorphed player, the value used would be the
X * non-polymorphed carrying capacity instead of max/half max).
X * This is then modified by the ratio between the monster weights
X * and human weights. Corpseless monsters are given a capacity
X * proportional to their size instead of weight.
X */
X if (!mtmp->data->cwt)
X maxload = (MAX_CARR_CAP * (long)mtmp->data->msize) / MZ_HUMAN;
X else if (!strongmonst(mtmp->data)
X || (strongmonst(mtmp->data) && (mtmp->data->cwt > WT_HUMAN)))
X maxload = (MAX_CARR_CAP * (long)mtmp->data->cwt) / WT_HUMAN;
X else maxload = MAX_CARR_CAP; /*strong monsters w/cwt <= WT_HUMAN*/
X
X if (!strongmonst(mtmp->data)) maxload /= 2;
X
X if (maxload < 1) maxload = 1;
X
X return (int) maxload;
X}
X
X/* for restricting monsters' object-pickup */
Xboolean
Xcan_carry(mtmp,otmp)
Xstruct monst *mtmp;
Xstruct obj *otmp;
X{
X register int newload = otmp->owt;
X
X if (otmp->otyp == CORPSE && otmp->corpsenm == PM_COCKATRICE
X && !resists_ston(mtmp->data))
X return(FALSE);
X if (mtmp->isshk) return(TRUE); /* no limit */
X if (mtmp->mpeaceful && !mtmp->mtame) return(FALSE);
X /* otherwise players might find themselves obligated to violate
X * their alignment if the monster takes something they need
X */
X
X /* special--boulder throwers carry unlimited amounts of boulders */
X if (throws_rocks(mtmp->data) && otmp->otyp == BOULDER)
X return(TRUE);
X
X /* nymphs deal in stolen merchandise, but not boulders or statues */
X if (mtmp->data->mlet == S_NYMPH)
X return !(otmp->oclass == ROCK_CLASS);
X
X if(curr_mon_load(mtmp) + newload > max_mon_load(mtmp)) return(FALSE);
X
X return(TRUE);
X}
X
X/* return number of acceptable neighbour positions */
Xint
Xmfndpos(mon, poss, info, flag)
X register struct monst *mon;
X coord *poss; /* coord poss[9] */
X long *info; /* long info[9] */
X long flag;
X{
X register xchar x,y,nx,ny;
X register int cnt = 0;
X register uchar ntyp;
X uchar nowtyp;
X boolean wantpool,poolok,lavaok,nodiag;
X int maxx, maxy;
X
X x = mon->mx;
X y = mon->my;
X nowtyp = levl[x][y].typ;
X
X nodiag = (mon->data == &mons[PM_GRID_BUG]);
X wantpool = mon->data->mlet == S_EEL;
X poolok = is_flyer(mon->data) || is_clinger(mon->data) ||
X (is_swimmer(mon->data) && !wantpool);
X lavaok = is_flyer(mon->data) || is_clinger(mon->data) ||
X (mon->data == &mons[PM_FIRE_ELEMENTAL]);
Xnexttry: /* eels prefer the water, but if there is no water nearby,
X they will crawl over land */
X if(mon->mconf) {
X flag |= ALLOW_ALL;
X flag &= ~NOTONL;
X }
X if(!mon->mcansee)
X flag |= ALLOW_SSM;
X maxx = min(x+1,COLNO-1);
X maxy = min(y+1,ROWNO-1);
X for(nx = max(1,x-1); nx <= maxx; nx++)
X for(ny = max(0,y-1); ny <= maxy; ny++) {
X if(nx == x && ny == y) continue;
X if(IS_ROCK(ntyp = levl[nx][ny].typ) && !(flag & ALLOW_WALL) &&
X !((flag & ALLOW_DIG) && may_dig(nx,ny))) continue;
X if(IS_DOOR(ntyp) && !amorphous(mon->data) &&
X ((levl[nx][ny].doormask & D_CLOSED && !(flag & OPENDOOR)) ||
X (levl[nx][ny].doormask & D_LOCKED && !(flag & UNLOCKDOOR))
X ) && !(flag & (ALLOW_WALL|ALLOW_DIG|BUSTDOOR))) continue;
X if(nx != x && ny != y && (nodiag ||
X#ifdef REINCARNATION
X ((IS_DOOR(nowtyp) &&
X ((levl[x][y].doormask & ~D_BROKEN) || Is_rogue_level(&u.uz))) ||
X (IS_DOOR(ntyp) &&
X ((levl[nx][ny].doormask & ~D_BROKEN) || Is_rogue_level(&u.uz))))
X#else
X ((IS_DOOR(nowtyp) && (levl[x][y].doormask & ~D_BROKEN)) ||
X (IS_DOOR(ntyp) && (levl[nx][ny].doormask & ~D_BROKEN)))
X#endif
X ))
X continue;
X if((is_pool(nx,ny) == wantpool || poolok) &&
X (lavaok || !is_lava(nx,ny))) {
X int dispx, dispy;
X boolean monseeu = (!Invis || perceives(mon->data));
X boolean checkobj = OBJ_AT(nx,ny);
X
X /* Displacement also displaces the Elbereth/scare monster,
X * as long as you are visible.
X */
X if(Displaced && monseeu && (mon->mux==nx) && (mon->muy==ny)) {
X dispx = u.ux;
X dispy = u.uy;
X } else {
X dispx = nx;
X dispy = ny;
X }
X
X info[cnt] = 0;
X if(((checkobj || Displaced) &&
X sobj_at(SCR_SCARE_MONSTER, dispx, dispy))
X#ifdef ELBERETH
X || sengr_at("Elbereth", dispx, dispy)
X#endif
X ) {
X if(!(flag & ALLOW_SSM)) continue;
X info[cnt] |= ALLOW_SSM;
X }
X if((nx == u.ux && ny == u.uy) ||
X (nx == mon->mux && ny == mon->muy)) {
X if (nx == u.ux && ny == u.uy) {
X /* If it's right next to you, it found you,
X * displaced or no. We must set mux and muy
X * right now, so when we return we can tell
X * that the ALLOW_U means to attack _you_ and
X * not the image.
X */
X mon->mux = u.ux;
X mon->muy = u.uy;
X }
X if(!(flag & ALLOW_U)) continue;
X info[cnt] |= ALLOW_U;
X } else {
X if(MON_AT(nx, ny)) {
X if(!(flag & ALLOW_M)) continue;
X info[cnt] |= ALLOW_M;
X if((m_at(nx,ny))->mtame) {
X if(!(flag & ALLOW_TM)) continue;
X info[cnt] |= ALLOW_TM;
X }
X }
X /* Note: ALLOW_SANCT only prevents movement, not */
X /* attack, into a temple. */
X if(level.flags.has_temple &&
X *in_rooms(nx, ny, TEMPLE) &&
X !*in_rooms(x, y, TEMPLE) &&
X in_your_sanctuary(nx, ny)){
X if(!(flag & ALLOW_SANCT)) continue;
X info[cnt] |= ALLOW_SANCT;
X }
X }
X if(checkobj && sobj_at(CLOVE_OF_GARLIC, nx, ny)) {
X if(flag & NOGARLIC) continue;
X info[cnt] |= NOGARLIC;
X }
X if(checkobj && sobj_at(BOULDER, nx, ny)) {
X if(!(flag & ALLOW_ROCK)) continue;
X info[cnt] |= ALLOW_ROCK;
X }
X if (monseeu && onlineu(nx,ny)) {
X if(flag & NOTONL) continue;
X info[cnt] |= NOTONL;
X }
X /* we cannot avoid traps of an unknown kind */
X { register struct trap *ttmp = t_at(nx, ny);
X register long tt;
X if(ttmp) {
X if(ttmp->ttyp >= TRAPNUM || ttmp->ttyp == 0) {
Ximpossible("A monster looked at a very strange trap of type %d.", ttmp->ttyp);
X continue;
X }
X tt = 1L << ttmp->ttyp;
X if(mon->mtrapseen & tt) {
X
X if(!(flag & tt)) continue;
X info[cnt] |= tt;
X }
X }
X }
X poss[cnt].x = nx;
X poss[cnt].y = ny;
X cnt++;
X }
X }
X if(!cnt && wantpool && !is_pool(x,y)) {
X wantpool = FALSE;
X goto nexttry;
X }
X return(cnt);
X}
X
X#endif /* OVL0 */
X#ifdef OVL1
X
Xboolean
Xmonnear(mon, x, y)
Xregister struct monst *mon;
Xregister int x,y;
X/* Is the square close enough for the monster to move or attack into? */
X{
X register int distance = dist2(mon->mx, mon->my, x, y);
X if (distance==2 && mon->data==&mons[PM_GRID_BUG]) return 0;
X return (distance < 3);
X}
X
X#endif /* OVL1 */
X#ifdef OVL2
X
XSTATIC_OVL void
Xdmonsfree()
X{
Xregister struct monst *mtmp;
X while ((mtmp = fdmon) != 0) {
X fdmon = mtmp->nmon;
X dealloc_monst(mtmp);
X }
X}
X
X#endif /* OVL2 */
X#ifdef OVLB
X/* we do not free monsters immediately, in order to have their name
X available shortly after their demise */
Xvoid
Xmonfree(mtmp)
Xregister struct monst *mtmp;
X{
X mtmp->nmon = fdmon;
X fdmon = mtmp;
X}
X
X/* called when monster is moved to larger structure */
Xvoid
Xreplmon(mtmp, mtmp2)
Xregister struct monst *mtmp, *mtmp2;
X{
X relmon(mtmp);
X monfree(mtmp);
X place_monster(mtmp2, mtmp2->mx, mtmp2->my);
X if (mtmp2->wormno) /* update level.monsters[wseg->wx][wseg->wy] */
X place_wsegs(mtmp2); /* locations to mtmp2 not mtmp. */
X mtmp2->nmon = fmon;
X fmon = mtmp2;
X if (u.ustuck == mtmp) u.ustuck = mtmp2;
X if (mtmp2->isshk) replshk(mtmp,mtmp2);
X}
X
X/* release mon from display and monster list */
Xvoid
Xrelmon(mon)
Xregister struct monst *mon;
X{
X register struct monst *mtmp;
X
X if (fmon == (struct monst *)0) panic ("relmon: no fmon available.");
X
X remove_monster(mon->mx, mon->my);
X
X if(mon == fmon) fmon = fmon->nmon;
X else {
X for(mtmp = fmon; mtmp && mtmp->nmon != mon; mtmp = mtmp->nmon) ;
X if(mtmp) mtmp->nmon = mon->nmon;
X else panic("relmon: mon not in list.");
X }
X}
X
X/* remove effects of mtmp from other data structures */
Xstatic void
Xm_detach(mtmp)
Xregister struct monst *mtmp;
X{
X#ifdef WALKIES
X if(mtmp->mleashed) m_unleash(mtmp);
X#endif
X /* to prevent an infinite relobj-flooreffects-hmon-killed loop */
X mtmp->mtrapped = 0;
X mtmp->mhp = 0; /* simplify some tests: force mhp to 0 */
X relobj(mtmp, 0, FALSE);
X relmon(mtmp);
X newsym(mtmp->mx,mtmp->my);
X unstuck(mtmp);
X fill_pit(mtmp->mx, mtmp->my);
X
X if(mtmp->isshk) shkgone(mtmp);
X if(mtmp->wormno) wormgone(mtmp);
X}
X
Xvoid
Xmondead(mtmp)
Xregister struct monst *mtmp;
X{
X int tmp, nk;
X
X if(mtmp->isgd) {
X /* if we're going to abort the death, it *must* be before
X * the m_detach or there will be relmon problems later */
X if(!grddead(mtmp)) return;
X }
X
X /* restore chameleon, lycanthropes to true form at death */
X if(mtmp->cham) mtmp->data = &mons[PM_CHAMELEON];
X if(mtmp->data == &mons[PM_WEREJACKAL])
X mtmp->data = &mons[PM_HUMAN_WEREJACKAL];
X if(mtmp->data == &mons[PM_WEREWOLF])
X mtmp->data = &mons[PM_HUMAN_WEREWOLF];
X if(mtmp->data == &mons[PM_WERERAT])
X mtmp->data = &mons[PM_HUMAN_WERERAT];
X
X /* if MAXMONNO monsters of a given type have died, and it
X * can be done, extinguish that monster.
X *
X * u.nr_killed does double duty as total number of dead monsters
X * and as experience factor for the player killing more monsters.
X * this means that a dragon dying by other means reduces the
X * experience the player gets for killing a dragon directly; this
X * is probably not too bad, since the player likely finagled the
X * first dead dragon via ring of conflict or pets, and extinguishing
X * based on only player kills probably opens more avenues of abuse
X * for rings of conflict and such.
X */
X tmp = monsndx(mtmp->data);
X u.nr_killed[tmp]++;
X nk = u.nr_killed[tmp];
X if(nk > (tmp == PM_NAZGUL ? 9 : tmp == PM_ERINYES ? 3 : MAXMONNO) &&
X !(mons[tmp].geno & (G_NOGEN | G_EXTINCT))) {
X#ifdef DEBUG
X pline("Automatically extinguished %s.", makeplural(mons[tmp].mname));
X#endif
X mons[tmp].geno |= G_EXTINCT;
X }
X#ifdef MAIL
X /* if the mail daemon dies, no more mail delivery. -3. */
X else if(tmp==PM_MAIL_DAEMON) mons[tmp].geno |= G_GENOD;
X#endif
X
X#ifdef KOPS
X if(mtmp->data->mlet == S_KOP && allow_kops) {
X /* Dead Kops may come back. */
X switch(rnd(5)) {
X case 1: /* returns near the stairs */
X (void) makemon(mtmp->data,xdnstair,ydnstair);
X break;
X case 2: /* randomly */
X (void) makemon(mtmp->data,0,0);
X break;
X default:
X break;
X }
X }
X#endif
X if(mtmp->iswiz) wizdead(mtmp);
X#ifdef MULDGN
X if(mtmp->data->msound == MS_NEMESIS) nemdead();
X#endif
X m_detach(mtmp);
X monfree(mtmp);
X}
X
X/* drop (perhaps) a cadaver and remove monster */
Xvoid
Xmondied(mdef)
Xregister struct monst *mdef;
X{
X mondead(mdef);
X if(rn2(3)
X#ifdef REINCARNATION
X && !Is_rogue_level(&u.uz)
X#endif
X )
X (void) make_corpse(mdef);
X}
X
X/* monster disappears, not dies */
Xvoid
Xmongone(mdef)
Xregister struct monst *mdef;
X{
X register struct obj *otmp, *otmp2;
X
X /* release monster's inventory */
X for (otmp = mdef->minvent; otmp; otmp = otmp2) {
X otmp2 = otmp->nobj;
X obfree(otmp, (struct obj *)0);
X }
X mdef->minvent = 0;
X mdef->mgold = 0;
X m_detach(mdef);
X monfree(mdef);
X}
X
X/* drop a statue or rock and remove monster */
Xvoid
Xmonstone(mdef)
Xregister struct monst *mdef;
X{
X struct obj *otmp, *contents;
X xchar x = mdef->mx, y = mdef->my;
X
X if((int)mdef->data->msize > MZ_TINY ||
X !rn2(2 + ((mdef->data->geno & G_FREQ) > 2))) {
X otmp = mk_named_object(STATUE, mdef->data, x, y,
X NAME(mdef), (int)mdef->mnamelth);
X contents = otmp->cobj = mdef->minvent;
X while(contents) {
X contents->owornmask = 0L;
X contents = contents->nobj;
X }
X mdef->minvent = (struct obj *)0;
X if (mdef->mgold) {
X struct obj *au;
X au = mksobj(GOLD_PIECE, FALSE, FALSE);
X au->quan = mdef->mgold;
X au->owt = weight(au);
X mdef->mgold = 0;
X au->nobj = otmp->cobj;
X otmp->cobj = au;
X }
X otmp->owt = weight(otmp);
X } else
X otmp = mksobj_at(ROCK, x, y, TRUE);
X
X mondead(mdef);
X
X stackobj(otmp);
X if (cansee(x, y)) newsym(x,y);
X}
X
X/* another monster has killed the monster mdef */
Xvoid
Xmonkilled(mdef, fltxt, how)
Xregister struct monst *mdef;
Xconst char *fltxt;
Xuchar how;
X{
X if (cansee(mdef->mx, mdef->my) && fltxt)
X pline("%s is %s%s%s!", Monnam(mdef),
X (is_demon(mdef->data) || is_undead(mdef->data)) ?
X "destroyed" : "killed",
X *fltxt ? " by the " : "",
X fltxt
X );
X else if(mdef->mtame)
X You("have a sad feeling for a moment, then it passes.");
X
X /* no corpses if digested */
X if(how == AD_DGST)
X mondead(mdef);
X else
X mondied(mdef);
X}
X
Xvoid
Xunstuck(mtmp)
Xregister struct monst *mtmp;
X{
X if(u.ustuck == mtmp) {
X if(u.uswallow){
X u.ux = mtmp->mx;
X u.uy = mtmp->my;
X u.uswallow = 0;
X u.uswldtim = 0;
X if (Punished) placebc();
X vision_full_recalc = 1;
X docrt();
X }
X u.ustuck = 0;
X }
X}
X
Xvoid
Xkilled(mtmp)
Xregister struct monst *mtmp;
X{
X xkilled(mtmp, 1);
X}
X
X/* the player has killed the monster mtmp */
Xvoid
Xxkilled(mtmp, dest)
X register struct monst *mtmp;
X/*
X * Dest=1, normal; dest=0, don't print message; dest=2, don't drop corpse
X * either; dest=3, message but no corpse
X */
X int dest;
X{
X register int tmp, x = mtmp->mx, y = mtmp->my;
X register struct permonst *mdat;
X register struct obj *otmp;
X register struct trap *t;
X boolean chance, redisp = FALSE;
X boolean wasinside = u.uswallow && (u.ustuck == mtmp);
X
X if (dest & 1) {
X if(!canseemon(mtmp) && !sensemon(mtmp)) You("destroy it!");
X else {
X You("destroy %s!",
X mtmp->mtame ? x_monnam(mtmp, 0, "poor", 0)
X : mon_nam(mtmp));
X }
X }
X
X if (mtmp->mtrapped &&
X ((t = t_at(x, y)) && (t->ttyp == PIT || t->ttyp == SPIKED_PIT)) &&
X sobj_at(BOULDER, x, y))
X dest ^= 2; /*
X * Prevent corpses/treasure being created "on top"
X * of the boulder that is about to fall in. This is
X * out of order, but cannot be helped unless this
X * whole routine is rearranged.
X */
X
X /* dispose of monster and make cadaver */
X if(stoned) monstone(mtmp);
X else mondead(mtmp);
X
X mdat = mtmp->data; /* note: mondead can change mtmp->data */
X
X if (stoned) {
X stoned = FALSE;
X goto cleanup;
X }
X
X if((dest & 2)
X#ifdef REINCARNATION
X || Is_rogue_level(&u.uz)
X#endif
X || (mdat == &mons[PM_WRAITH] && Is_valley(&u.uz) && rn2(5)))
X goto cleanup;
X
X#ifdef MAIL
X if(mdat == &mons[PM_MAIL_DAEMON]) {
X (void) mksobj_at(SCR_MAIL, x, y, FALSE);
X stackobj(fobj);
X redisp = TRUE;
X }
X#endif
X if(!accessible(x, y)) {
X /* might be mimic in wall or dead eel or in a pool or lava */
X redisp = TRUE;
X if(wasinside) spoteffects();
X } else if(x != u.ux || y != u.uy) {
X /* might be here after swallowed */
X if (!rn2(6) && !(mdat->geno & G_NOCORPSE)
X#ifdef KOPS
X && mdat->mlet != S_KOP
X#endif
X ) {
X int typ;
X
X otmp = mkobj_at(RANDOM_CLASS, x, y, TRUE);
X /* Don't create large objects from small monsters */
X typ = otmp->otyp;
X if (mdat->msize < MZ_HUMAN && typ != FOOD_RATION
X#ifdef WALKIES
X && typ != LEASH
X#endif
X && typ != FIGURINE
X && (otmp->owt > 3 ||
X (typ >= SPEAR && typ <= LANCE) ||
X (typ >= SCIMITAR && typ <= KATANA) ||
X (typ == MORNING_STAR || typ == QUARTERSTAFF) ||
X (typ >= BARDICHE && typ <= VOULGE) ||
X (typ >= PLATE_MAIL &&
X typ <= YELLOW_DRAGON_SCALE_MAIL) ||
X (typ == LARGE_SHIELD))) {
X delobj(otmp);
X } else redisp = TRUE;
X }
X /* Whether or not it always makes a corpse is, in theory,
X * different from whether or not the corpse is "special";
X * if we want both, we have to specify it explicitly.
X */
X if (bigmonst(mdat) || mdat == &mons[PM_LIZARD]
X || is_golem(mdat)
X || is_mplayer(mdat)
X || is_rider(mdat))
X chance = 1;
X else chance = !rn2((int)
X (2 + ((mdat->geno & G_FREQ)<2) + verysmall(mdat)));
X if (chance)
X (void) make_corpse(mtmp);
X }
X if(redisp) newsym(x,y);
Xcleanup:
X /* punish bad behaviour */
X if(is_human(mdat) && !always_hostile(mdat) &&
X (monsndx(mdat) < PM_ARCHEOLOGIST || monsndx(mdat) > PM_WIZARD) &&
X u.ualign.type != A_CHAOTIC) {
X HTelepat &= ~INTRINSIC;
X change_luck(-2);
X if (Blind && !Telepat)
X see_monsters(); /* Can't sense monsters any more. */
X }
X if((mtmp->mpeaceful && !rn2(2)) || mtmp->mtame) change_luck(-1);
X if (mdat->mlet == S_UNICORN &&
X sgn(u.ualign.type) == sgn(mdat->maligntyp))
X change_luck(-5);
X
X /* give experience points */
X tmp = experience(mtmp, u.nr_killed[monsndx(mdat)] + 1);
X more_experienced(tmp, 0);
X newexplevel(); /* will decide if you go up */
X
X /* adjust alignment points */
X#ifdef MULDGN
X if(mdat->msound == MS_LEADER) /* REAL BAD! */
X adjalign(-(u.ualign.record+(int)ALIGNLIM/2));
X else if(mdat->msound == MS_NEMESIS) /* Real good! */
X adjalign((int)(ALIGNLIM/4));
X else if(mdat->msound == MS_GUARDIAN) /* Bad */
X adjalign(-(int)(ALIGNLIM/8));
X else
X#endif
X if (mtmp->ispriest) {
X adjalign((p_coaligned(mtmp)) ? -2 : 2);
X if(mdat->maligntyp == A_NONE)
X adjalign((int)(ALIGNLIM / 4)); /* BIG bonus */
X } else if(mtmp->mtame)
X adjalign(-15); /* bad!! */
X else if (mtmp->mpeaceful)
X adjalign(-5);
X
X /* malign was already adjusted for u.ualign.type and randomization */
X adjalign(mtmp->malign);
X}
X
X/* changes the monster into a stone monster of the same type */
X/* this should only be called when poly_when_stoned() is true */
Xvoid
Xmon_to_stone(mtmp)
X register struct monst *mtmp;
X{
X if(mtmp->data->mlet == S_GOLEM) {
X /* it's a golem, and not a stone golem */
X if(canseemon(mtmp))
X pline("%s solidifies...", Monnam(mtmp));
X (void) newcham(mtmp, &mons[PM_STONE_GOLEM]);
X if(canseemon(mtmp))
X pline("Now it's %s", a_monnam(mtmp));
X } else
X impossible("Can't polystone %s", a_monnam(mtmp));
X}
X
Xvoid
Xmnexto(mtmp) /* Make monster mtmp next to you (if possible) */
X struct monst *mtmp;
X{
X coord mm;
X
X if(!enexto(&mm, u.ux, u.uy, mtmp->data)) return;
X
X rloc_to(mtmp, mm.x, mm.y);
X}
X
X/* mnearto()
X * Put monster near (or at) location if possible.
X * Returns:
X * 1 - if a monster was moved from x, y to put mtmp at x, y.
X * 0 - in most cases.
X */
Xboolean
Xmnearto(mtmp,x,y,move_other)
Xregister struct monst *mtmp;
Xxchar x, y;
Xboolean move_other; /* make sure mtmp gets to x, y! so move m_at(x, y) */
X{
X struct monst *othermon = (struct monst *)0;
X xchar newx, newy;
X coord mm;
X
X if ((mtmp->mx == x) && (mtmp->my == y)) return(FALSE);
X
X if (move_other && (othermon = m_at(x, y))) {
X if (othermon->wormno)
X remove_worm(othermon);
X else
X remove_monster(x, y);
X }
X
X newx = x;
X newy = y;
X
X if (!goodpos(newx, newy, mtmp, mtmp->data)) {
X /* actually we have real problems if enexto ever fails.
X * migrating_mons that need to be placed will cause
X * no end of trouble.
X */
X if (!enexto(&mm, newx, newy, mtmp->data)) return(FALSE);
X newx = mm.x; newy = mm.y;
X }
X
X rloc_to(mtmp, newx, newy);
X
X if (move_other && othermon) {
X othermon->mx = othermon->my = 0;
X (void) mnearto(othermon, x, y, FALSE);
X if ((othermon->mx != x) || (othermon->my != y))
X return(TRUE);
X }
X
X return(FALSE);
X}
X
X
Xstatic const char *poiseff[] = {
X
X " feel very weak", "r brain is on fire",
X "r judgement is impaired", "r muscles won't obey you",
X " feel very sick", " break out in hives"
X};
X
Xvoid
Xpoisontell(typ)
X
X int typ;
X{
X pline("You%s.", poiseff[typ]);
X}
X
Xvoid
Xpoisoned(string, typ, pname, fatal)
Xregister const char *string, *pname;
Xregister int typ, fatal;
X{
X register int i, plural;
X boolean thrown_weapon = !strncmp(string, "poison", 6);
X /* admittedly a kludge... */
X
X if(strcmp(string, "blast") && !thrown_weapon) {
X /* 'blast' has already given a 'poison gas' message */
X /* so have "poison arrow", "poison dart", etc... */
X plural = (string[strlen(string) - 1] == 's')? 1 : 0;
X /* avoid "The" Orcus's sting was poisoned... */
X pline("%s%s %s poisoned!", isupper(*string) ? "" : "The ",
X string, plural ? "were" : "was");
X }
X
X if(Poison_resistance) {
X if(!strcmp(string, "blast")) shieldeff(u.ux, u.uy);
X pline("The poison doesn't seem to affect you.");
X return;
X }
X i = rn2(fatal + 20*thrown_weapon);
X if(i == 0 && typ != A_CHA) {
X u.uhp = -1;
X pline("The poison was deadly...");
X } else if(i <= 5) {
X pline("You%s!", poiseff[typ]);
X (void) adjattrib(typ, thrown_weapon ? -1 : -rn1(3,3), TRUE);
X } else {
X i = thrown_weapon ? rnd(6) : rn1(10,6);
X if(Half_physical_damage) i = (i+1) / 2;
X losehp(i, pname, KILLED_BY_AN);
X }
X if(u.uhp < 1) {
X killer_format = KILLED_BY_AN;
X killer = pname;
X done(POISONING);
X }
X}
X
X/* monster responds to player action; not the same as a passive attack */
X/* assumes reason for response has been tested, and response _must_ be made */
Xvoid
Xm_respond(mtmp)
Xregister struct monst *mtmp;
X{
X if(mtmp->data->msound == MS_SHRIEK) {
X if(flags.soundok)
X pline("%s shrieks.", Monnam(mtmp));
X aggravate();
X }
X}
X
X#endif /* OVLB */
X#ifdef OVL2
X
Xvoid
Xsetmangry(mtmp)
Xregister struct monst *mtmp;
X{
X mtmp->data->mflags3 &= ~M3_WAITMASK;
X if(!mtmp->mpeaceful) return;
X if(mtmp->mtame) return;
X mtmp->mpeaceful = 0;
X if(mtmp->ispriest) {
X if(p_coaligned(mtmp)) adjalign(-5); /* very bad */
X else adjalign(2);
X } else
X adjalign(-1); /* attacking peaceful monsters is bad */
X if(humanoid(mtmp->data) || mtmp->isshk || mtmp->isgd)
X pline("%s gets angry!", Monnam(mtmp));
X#ifdef SOUNDS
X else if (flags.verbose && flags.soundok) growl(mtmp);
X#endif
X}
X
Xvoid
Xwakeup(mtmp)
Xregister struct monst *mtmp;
X{
X mtmp->msleep = 0;
X mtmp->meating = 0; /* assume there's no salvagable food left */
X setmangry(mtmp);
X if(mtmp->m_ap_type) seemimic(mtmp);
X}
X
X/* Wake up nearby monsters. */
Xvoid
Xwake_nearby()
X{
X register struct monst *mtmp;
X
X for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
X if (distu(mtmp->mx,mtmp->my) < u.ulevel*20) {
X if(mtmp->msleep) mtmp->msleep = 0;
X if(mtmp->mtame) EDOG(mtmp)->whistletime = moves;
X }
X }
X}
X
X/* NOTE: we must check for mimicry before calling this routine */
Xvoid
Xseemimic(mtmp)
Xregister struct monst *mtmp;
X{
X /*
X * Discovered mimics don't block light.
X */
X if ((mtmp->m_ap_type == M_AP_FURNITURE &&
X (mtmp->mappearance==S_hcdoor || mtmp->mappearance==S_vcdoor))||
X (mtmp->m_ap_type == M_AP_OBJECT && mtmp->mappearance == BOULDER))
X unblock_point(mtmp->mx,mtmp->my);
X
X mtmp->m_ap_type = M_AP_NOTHING;
X mtmp->mappearance = 0;
X newsym(mtmp->mx,mtmp->my);
X}
X
X/* force all chameleons to become normal */
Xvoid
Xrescham()
X{
X register struct monst *mtmp;
X
X for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
X if(mtmp->cham) {
X mtmp->cham = 0;
X (void) newcham(mtmp, &mons[PM_CHAMELEON]);
X }
X if(is_were(mtmp->data) && mtmp->data->mlet != S_HUMAN)
X new_were(mtmp);
X if(mtmp->m_ap_type && cansee(mtmp->mx, mtmp->my)) {
X seemimic(mtmp);
X /* we pretend that the mimic doesn't */
X /* know that it has been unmasked. */
X mtmp->msleep = 1;
X }
X }
X}
X
X/* Let the chameleons change again -dgk */
Xvoid
Xrestartcham()
X{
X register struct monst *mtmp;
X
X for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
X if (mtmp->data == &mons[PM_CHAMELEON])
X mtmp->cham = 1;
X if(mtmp->data->mlet == S_MIMIC && mtmp->msleep &&
X cansee(mtmp->mx, mtmp->my)) {
X set_mimic_sym(mtmp);
X newsym(mtmp->mx,mtmp->my);
X }
X }
X}
X
X/* unwatched hiders may hide again; if so, a 1 is returned. */
XSTATIC_OVL boolean
Xrestrap(mtmp)
Xregister struct monst *mtmp;
X{
X if(mtmp->cham || mtmp->mcan || mtmp->m_ap_type ||
X cansee(mtmp->mx, mtmp->my) || rn2(3) || (mtmp == u.ustuck))
X return(FALSE);
X
X if(mtmp->data->mlet == S_MIMIC) {
X set_mimic_sym(mtmp);
X return(TRUE);
X } else
X if(levl[mtmp->mx][mtmp->my].typ == ROOM) {
X mtmp->mundetected = 1;
X return(TRUE);
X }
X
X return(FALSE);
X}
X
X/* make a chameleon look like a new monster; returns 1 if it actually changed */
Xint
Xnewcham(mtmp, mdat)
Xregister struct monst *mtmp;
Xregister struct permonst *mdat;
X{
X register int mhp, hpn, hpd;
X int tryct;
X struct permonst *olddata = mtmp->data;
X
X /* mdat = 0 -> caller wants a random monster shape */
X tryct = 0;
X if(mdat == 0) {
X while (++tryct < 100) {
X mdat = &mons[rn2(NUMMONS)];
X /* polyok rules out all M2_PNAME and M2_WERE's */
X if (!is_human(mdat) && polyok(mdat)
X && !(mdat->geno & G_GENOD))
X break;
X }
X if (tryct >= 100) return(0); /* Should never happen */
X }
X
X if(is_male(mdat)) {
X if(mtmp->female) mtmp->female = FALSE;
X } else if (is_female(mdat)) {
X if(!mtmp->female) mtmp->female = TRUE;
X } else if (!is_neuter(mdat)) {
X if(!rn2(10)) mtmp->female = !mtmp->female;
X }
X
X if(mdat == mtmp->data) return(0); /* still the same monster */
X
X if(mtmp->wormno) { /* throw tail away */
X wormgone(mtmp);
X place_monster(mtmp, mtmp->mx, mtmp->my);
X }
X
X hpn = mtmp->mhp;
X hpd = (mtmp->m_lev < 50) ? ((int)mtmp->m_lev)*8 : mdat->mlevel;
X if(!hpd) hpd = 4;
X
X mtmp->m_lev = adj_lev(mdat); /* new monster level */
X
X mhp = (mtmp->m_lev < 50) ? ((int)mtmp->m_lev)*8 : mdat->mlevel;
X if(!mhp) mhp = 4;
X
X /* new hp: same fraction of max as before */
X#ifndef LINT
X mtmp->mhp = (int)(((long)hpn*(long)mhp)/(long)hpd);
X#endif
X if(mtmp->mhp < 0) mtmp->mhp = hpn; /* overflow */
X/* Unlikely but not impossible; a 1HD creature with 1HP that changes into a
X 0HD creature will require this statement */
X if (!mtmp->mhp) mtmp->mhp = 1;
X
X/* and the same for maximum hit points */
X hpn = mtmp->mhpmax;
X#ifndef LINT
X mtmp->mhpmax = (int)(((long)hpn*(long)mhp)/(long)hpd);
X#endif
X if(mtmp->mhpmax < 0) mtmp->mhpmax = hpn; /* overflow */
X if (!mtmp->mhpmax) mtmp->mhpmax = 1;
X
X mtmp->data = mdat;
X mtmp->minvis = !!(mdat->mlet == S_STALKER);
X if (!hides_under(mdat) || !OBJ_AT(mtmp->mx, mtmp->my))
X mtmp->mundetected = 0;
X if (u.ustuck == mtmp) {
X if(u.uswallow) {
X if(!attacktype(mdat,AT_ENGL)) {
X /* Does mdat care? */
X if (!noncorporeal(mdat) && !amorphous(mdat) &&
X !is_whirly(mdat) &&
X (mdat != &mons[PM_YELLOW_LIGHT])) {
X You("break out of %s%s!", mon_nam(mtmp),
X (is_animal(mdat)?
X "'s stomach" : ""));
X mtmp->mhp = 1; /* almost dead */
X }
X expels(mtmp, olddata, FALSE);
X }
X } else {
X if(!sticks(mdat)
X#ifdef POLYSELF
X && !sticks(uasmon)
X#endif
X )
X unstuck(mtmp);
X }
X }
X
X if ( (mdat == &mons[PM_LONG_WORM]) && (mtmp->wormno = get_wormno()) ) {
X /* we can now create worms with tails - 11/91 */
X initworm(mtmp, rn2(5));
X if (count_wsegs(mtmp))
X place_worm_tail_randomly(mtmp, mtmp->mx, mtmp->my);
X }
X
X newsym(mtmp->mx,mtmp->my);
X#ifdef MUSE
X mon_break_armor(mtmp);
X possibly_unwield(mtmp);
X#endif
X return(1);
X}
X
X#endif /* OVL2 */
X#ifdef OVLB
X
Xvoid
Xgolemeffects(mon, damtype, dam)
Xregister struct monst *mon;
Xint damtype, dam;
X{
X int heal=0, slow=0;
X
X if (mon->data != &mons[PM_FLESH_GOLEM]
X && mon->data != &mons[PM_IRON_GOLEM])
X return;
X
X if (mon->data == &mons[PM_FLESH_GOLEM]) {
X if (damtype == AD_ELEC) heal = dam / 6;
X else if (damtype == AD_FIRE || damtype == AD_COLD) slow = 1;
X } else {
X if (damtype == AD_ELEC) slow = 1;
X else if (damtype == AD_FIRE) heal = dam;
X }
X if (slow) {
X if (mon->mspeed != MSLOW) {
X if (mon->mspeed == MFAST) mon->mspeed = 0;
X else mon->mspeed = MSLOW;
X if (cansee(mon->mx, mon->my))
X pline("%s seems to be moving slower.",
X Monnam(mon));
X }
X }
X if (heal) {
X if (mon->mhp < mon->mhpmax) {
X mon->mhp += dam;
X if (mon->mhp > mon->mhpmax) mon->mhp = mon->mhpmax;
X if (cansee(mon->mx, mon->my))
X pline("%s seems healthier.", Monnam(mon));
X }
X }
X}
X
Xboolean
Xangry_guards(silent)
Xregister boolean silent;
X{
X register struct monst *mtmp;
X register int ct = 0, nct = 0, sct = 0, slct = 0;
X
X for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
X if((mtmp->data == &mons[PM_WATCHMAN] ||
X mtmp->data == &mons[PM_WATCH_CAPTAIN])
X && mtmp->mpeaceful) {
X ct++;
X if(cansee(mtmp->mx, mtmp->my) && mtmp->mcanmove) {
X if (distu(mtmp->mx, mtmp->my) == 2) nct++;
X else sct++;
X }
X if(mtmp->msleep || mtmp->mfrozen) {
X slct++;
X mtmp->msleep = mtmp->mfrozen = 0;
X }
X mtmp->mpeaceful = 0;
X }
X }
X if(ct) {
X if(!silent) { /* do we want pline msgs? */
X if(slct) pline("The guard%s wake%s up!",
X slct > 1 ? "s" : "", slct == 1 ? "s" : "");
X if(nct || sct) {
X if(nct) pline("The guard%s get%s angry!",
X nct == 1 ? "" : "s", nct == 1 ? "s" : "");
X else if(!Blind)
X You("see %sangry guard%s approaching!",
X sct == 1 ? "an " : "", sct > 1 ? "s" : "");
X } else if(flags.soundok)
X You("hear the shrill sound of a guard's whistle.");
X }
X return(TRUE);
X }
X return(FALSE);
X}
X
Xvoid
Xpacify_guards()
X{
X register struct monst *mtmp;
X
X for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
X if (mtmp->data == &mons[PM_WATCHMAN] ||
X mtmp->data == &mons[PM_WATCH_CAPTAIN])
X mtmp->mpeaceful = 1;
X }
X}
X#endif /* OVLB */
X
X/*mon.c*/
END_OF_FILE
if test 42736 -ne `wc -c <'src/mon.c'`; then
echo shar: \"'src/mon.c'\" unpacked with wrong size!
fi
# end of 'src/mon.c'
fi
echo shar: End of archive 21 \(of 108\).
cp /dev/null ark21isdone
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 40 \
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 \
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 \
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 \
101 102 103 104 105 106 107 108 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 108 archives.
echo "Now execute 'rebuild.sh'"
rm -f ark10[0-8]isdone 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