[comp.sources.games] v10i046: nethack3p9 - display oriented dungeons & dragons

billr@saab.CNA.TEK.COM (Bill Randle) (07/12/90)

Submitted-by: Izchak Miller <izchak@linc.cis.upenn.edu>
Posting-number: Volume 10, Issue 46
Archive-name: nethack3p9/Part01
Supersedes: NetHack3: Volume 7, Issue 56-93

	[Here is a post of the NetHack3 source with all of the
	 patches applied (1-9). It will be posted over a period
	 of several days, so don't expect to get it all at once. -br]

#! /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 1 (of 56)."
# Contents:  README MANIFEST amiga auxil include mac others src
#   src/makemon.c vms
# Wrapped by billr@saab on Wed Jul 11 17:10:49 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'README' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'README'\"
else
echo shar: Extracting \"'README'\" \(6961 characters\)
sed "s/^X//" >'README' <<'END_OF_FILE'
X
X		NetHack 3.0 -- General information
X
XNetHack 3.0 is a new generation of the dungeon exploration game NetHack.
XIt is a distant descendent of Hack, and a direct descendent of NetHack 2.3.
XIt is the product of a year-long, very intensive, international team
Xeffort.  Many parts of 2.3 were rewritten for NetHack 3.0, and many new
Xfeatures were added.  Judged by size alone, with all options enabled,
XNetHack 3.0 is twice as big as 2.3.
X
XWhile aiming at retaining the general atmosphere of NetHack 2.3, we sought
Xto open up new directions of development for the game.  Alignment, both for
Xplayer characters and for monsters, was introduced.  Player character
Xattributes were added and integrated into the game.  Special compiled
Xlevels were added, and these open up endless future possibilities.  An
Xendgame was written, for a climactic ending.  The code for monsters and
Xobjects was massively rewritten, and many new creatures and items were
Xadded.  The self-polymorph code was debugged and greatly enriched.  Shops,
Xtoo, were enhanced.  There are now doors in doorways and chests that may
Xcontain valuables, both of which may be closed or locked.  New commands to
Xopen or kick doors and force locks on chests were added.  You can also use
Xkicking as an attack mode, and you can kick objects around if it pleases
Xyou.  You will discover the rest for yourselves...
X
XTo compensate for the massive additions, we rewrote the code around some
Xnew map fields for an increase in speed up to, if not beyond, that of 2.3.
XThe code is now organized, and nearly lint-free.
X
XWe dedicate the game to the many unknown hackers, both past and future, who
Xcontribute so much to the game.
X
X			- - - - - - - - - - -
X
XPlease read items (1), (2) and (3) BEFORE doing anything with your new code.
X
X1.  Unpack the code in a dedicated new directory.  We will refer to that
X    directory as the 'Top' directory.  It makes no difference what you
X    call it.
X
X2.  If there is no flaw in the packaging, SEVEN sub-directories will be
X    automatically created, and files will be deposited in them: 
X
X    a.  A 'src' directory, which will contain general *.c files.
X    b.  An 'include' directory, which will contain general *.h files.
X    c.  An 'auxil' directory, which will contain a variety of data files.
X    d.  An 'amiga' directory, which will contain the Amiga-specific files.
X    e.  An 'others' directory, which will contain MSDOS and TOS files.
X    f.  A 'vms' directory, which will contain VMS files.
X    g.  A 'mac' directory, which will contain Macintosh files.
X
X    The names of these directories should not be changed, unless you are
X    ready to go through the makefiles and the makedefs program and change
X    all the directory references in them.
X
X3.  Having unpacked, you should have a file called 'Files' in your Top
X    directory.  This file contains the list of all the files you now SHOULD 
X    have in each directory.  Please check the files in each directory 
X    against this list to make sure that you have a complete set.
X
X4.  Before you do anything else, please read carefully the file called
X    'license' in the auxil subdirectory.  It is expected that you comply
X    with the terms of that license, and we are very serious about it.  In
X    particular, you are prohibited by the terms of the license from using
X    NetHack 3.0 for gainful purposes.   
X
X5.  If everything is in order, you can now turn to trying to get the program
X    to compile and run on your particular system.  It is worth mentioning
X    that the default configuration is Ultrix (simply because the code was
X    housed on such a system).  It is also worth mentioning here that NetHack
X    3.0 is a huge program by comparison with 2.3.  If you intend to run it
X    on a small machine, you'll have to make hard choices among the options
X    available in config.h.
X
X    The files Install.* were written to guide you in configuring the program
X    for your operating system.  Reading them, and the man page, should answer
X    most of your questions.
X
X    At the time of this release, NetHack 3.0 is known to run on:
X
X        AT&T 3B1 running System V (3.51)
X        AT&T 3B2/600 & 3B2/622 running System V R3.2.1
X        AT&T 3B2/1000 Model 80 running System V R3.2.2
X        AT&T 3B4000 running System V
X        Bull DPX/2 200 running System V R3.1
X        Bull XPS100 running System V R2.2 or R3.1
X        Data General AViiON systems running DG/UX
X        DEC vaxen running Ultrix and BSD
X        Decstation 5400 running Ultrix 3.1
X        Encore Multimax running UMAX 4.2
X        Gould NP1 running UTX 3/2
X        H-P 9000s300 running HP-UX
X        IBM PC/RT running AIX
X        Mips M2000 running RiscOS 4.1
X        Pyramid 9820x running OSx 4.4c
X        SGI Iris running IRIX
X        Stride 460 running UniStride 2.1
X        Sun-3s and -4s running SunOS 3.x and 4.0.x
X        Valid Logic Systems SCALD-System
X        286 box running Microport SysV/AT (not extensively tested)
X
X        Apple Macintosh running MacOS
X        Atari 1040ST running TOS
X        Commodore Amiga running AmigaDOS 1.3 (WorkBench 1.3,
X                KickStart 1.2 or 1.3) with Lattice or Manx/Aztec C
X        DEC vaxen running VMS
X        IBM PC compatibles running MS-DOS with MicroSoft C or Turbo C
X        IBM PS/2 and AT compatibles running OS/2 with MicroSoft C
X
X			- - - - - - - - - - -
X
XIf you have problems building the game, or you find bugs in it, the 
Xdevelopment team may be reached as
X 
X		    nethack-bugs@linc.cis.upenn.edu.  
X
XPlease be sure to include your machine type, OS, and patchlevel.
X
XPatches especially should be directed to this address.  If you've changed 
Xsomething to get NetHack to run on your system, it's likely that others have
Xdone it by making slightly different modifications.  By routing your patches
Xthrough the development team, we should be able to avoid making everyone else
Xchoose among variant patches claiming to do the same thing, to keep most of
Xthe copies of 3.0 synchronized by means of official patches, and to maintain
Xthe painfully-created file organization.  (Remember the mess when everybody
Xjust posted their own patches to 2.3?  There were no archived bug-fixes to
Xgive people who got 2.3 after its initial release, so the same bugs kept being
Xdiscovered by new batches of people.  Please cooperate to keep this from
Xhappening to 3.0.)
X
XIt is inevitable that we will reject some proposed additions of new features
Xeither because they do not fit our conception of the game, or because they 
Xrequire more code than we consider they're worth.  If we reject your feature,
Xyou are free, of course, to post the patches to the net yourself and let the
Xmarketplace decide its worth.
X
XAll of this amounts to the following:  If you decide to apply a free-lanced
Xpatch to your 3.0 code, you are on your own.  In our own patches, including
Xthose which will update to 3.1, we will assume that your code is synchronized
Xwith ours.
X
X		  -- Good luck, and happy Hacking --
X
END_OF_FILE
if test 6961 -ne `wc -c <'README'`; then
    echo shar: \"'README'\" unpacked with wrong size!
fi
# end of 'README'
fi
if test -f 'MANIFEST' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'MANIFEST'\"
else
echo shar: Extracting \"'MANIFEST'\" \(8360 characters\)
sed "s/^X//" >'MANIFEST' <<'END_OF_FILE'
X   File Name		Archive #	Description
X-----------------------------------------------------------
X Files                     53	
X Install.ami               12	
X Install.dos               42	
X Install.mac               41	
X Install.ovl               42	
X Install.unix              51	
X Install.vms               46	
X MANIFEST                   1	This shipping list
X Makefile.top              53	
X Porting                   40	
X README                     1	
X READ_1ST                  56	
X UPDATE1                   56	
X UPDATE2                   56	
X UPDATE3                   56	
X UPDATE4                   56	
X UPDATE5                   38	
X UPDATE6                   48	
X UPDATE7                   56	
X UPDATE8                   56	
X UPDATE9                   56	
X amiga                      1	
X amiga/GBinfo.uu           55	
X amiga/Makefile.ami        35	
X amiga/NHScore.uu          55	
X amiga/NHinfo.uu           55	
X amiga/NetHack.cnf         55	
X amiga/NewGame.uu          55	
X amiga/ami.lnk             55	
X amiga/amidos.c            39	
X amiga/amifont.uu          56	
X amiga/amifont8.uu         54	
X amiga/amimenu.c           51	
X amiga/amitcap.c           52	
X amiga/amitty.c            56	
X amiga/amiunix.c           50	
X amiga/amiwbench.c         43	
X amiga/amiwind.c           38	
X amiga/compact.lat         51	
X amiga/dflticon.uu         55	
X auxil                      1	
X auxil/Guidebook.mn         6	
X auxil/Guidebook.mss        4	
X auxil/Guidebook.tex        2	
X auxil/MacHelp             39	
X auxil/Makefile.auxil      31	
X auxil/castle.des          50	
X auxil/cmdhelp             52	
X auxil/data.base           23	
X auxil/endgame.des         54	
X auxil/help                 4	
X auxil/hh                  54	
X auxil/history             54	
X auxil/lev_comp.6          53	
X auxil/license             52	
X auxil/nethack.6           51	
X auxil/nethack.sh          56	
X auxil/opthelp             53	
X auxil/oracles             53	
X auxil/rumors.fal          36	
X auxil/rumors.tru          16	
X auxil/tmac.n              25	
X auxil/tower.des            2	
X include                    1	
X include/MacAlert.h        56	
X include/amiconf.h         54	
X include/artifact.h        30	
X include/attrib.h          56	
X include/color.h           56	
X include/config.h          46	
X include/coord.h           56	
X include/decl.h            51	
X include/def_os2.h         33	
X include/edog.h            56	
X include/epri.h            56	
X include/eshk.h            56	
X include/extern.h          10	
X include/flag.h            55	
X include/func_tab.h        55	
X include/global.h          53	
X include/gold.h            56	
X include/hack.h            51	
X include/lev.h             56	
X include/lev_comp.h        56	
X include/macconf.h         53	
X include/mfndpos.h         56	
X include/mkroom.h          55	
X include/monattk.h         54	
X include/mondata.h         53	
X include/monflag.h         51	
X include/monst.h           54	
X include/monsym.h          46	
X include/msdos.h           29	
X include/obj.h             54	
X include/objclass.h        54	
X include/patchlevel.h      47	
X include/pcconf.h          55	
X include/permonst.h        55	
X include/prop.h            54	
X include/rm.h              49	
X include/sp_lev.h          55	
X include/spell.h           56	
X include/system.h          50	
X include/termcap.h         56	
X include/tosconf.h         56	
X include/tradstdc.h        53	
X include/trampoli.h        51	
X include/trap.h            56	
X include/unixconf.h        51	
X include/vault.h           56	
X include/vmsconf.h         54	
X include/wseg.h            56	
X include/you.h             53	
X include/youprop.h         52	
X mac                        1	
X mac/MD.proj.hqx           13	
X mac/MD.rsrc.hqx           56	
X mac/MacAlert.c            30	
X mac/NH.proj.hqx           30	
X mac/NH.rsrc.hqx           22	
X mac/SL.proj.hqx           29	
X mac/Segments.mac          55	
X mac/mac.c                 33	
X mac/macfile.c             55	
X mac/macinit.c             45	
X others                     1	
X others/Makefile.lib       56	
X others/Makefile.msc       41	
X others/Makefile.os2       39	
X others/Makefile.ovl       33	
X others/Makefile.pc         5	
X others/Makefile.st        48	
X others/Makefile.tcc       37	
X others/NetHack.cnf        54	
X others/atari.cnf          55	
X others/atarifnt.uue       50	
X others/exesmurf.c         52	
X others/exesmurf.uu        22	
X others/lev_lex.c          25	
X others/maintain.ovl       39	
X others/msdos.c            27	
X others/ovlmgr.asm         12	
X others/ovlmgr.doc         43	
X others/ovlmgr.uu          50	
X others/pcmain.c           37	
X others/pctty.c            56	
X others/pcunix.c            3	
X others/random.c            9	
X others/splitf.c           52	
X others/splitf.uu          16	
X others/suputils.ovl       43	
X others/termcap            52	
X others/termcap.uu         26	
X others/trampoli.c         47	
X src                        1	
X src/Makefile.src          41	
X src/allmain.c             52	
X src/alloc.c               53	
X src/apply.c               20	
X src/artifact.c            48	
X src/attrib.c              44	
X src/bones.c               47	
X src/cmd.c                 21	
X src/dbridge.c             34	
X src/decl.c                47	
X src/demon.c               54	
X src/do.c                  28	
X src/do_name.c             42	
X src/do_wear.c             19	
X src/dog.c                 48	
X src/dogmove.c              7	
X src/dokick.c              18	
X src/dothrow.c             44	
X src/eat.c                 15	
X src/end.c                 40	
X src/engrave.c             41	
X src/exper.c               52	
X src/extralev.c            47	
X src/fountain.c            46	
X src/getline.c             49	
X src/hack.c                35	
X src/invent.c              24	
X src/ioctl.c               55	
X src/lev_comp.c            23	
X src/lev_comp.l            54	
X src/lev_comp.y            31	
X src/lev_lex.c             24	
X src/lev_main.c            53	
X src/lock.c                14	
X src/mail.c                48	
X src/makedefs.c            15	
X src/makemon.c              1	
X src/mcastu.c              48	
X src/mhitm.c               17	
X src/mhitu.c                5	
X src/mklev.c               32	
X src/mkmaze.c              46	
X src/mkobj.c               10	
X src/mkroom.c              44	
X src/mon.c                 17	
X src/mondata.c             40	
X src/monmove.c             32	
X src/monst.c1              14	
X src/monst.c2               7	
X src/mthrowu.c             44	
X src/music.c               45	
X src/o_init.c              45	
X src/objects.c             21	
X src/objnam.c              13	
X src/options.c             28	
X src/pager.c               34	
X src/panic.c               19	
X src/pickup.c              11	
X src/polyself.c            20	
X src/potion.c              26	
X src/pray.c                18	
X src/pri.c                 31	
X src/priest.c              36	
X src/prisym.c               8	
X src/read.c                29	
X src/restore.c             27	
X src/rip.c                 32	
X src/rnd.c                 55	
X src/rumors.c              50	
X src/save.c                37	
X src/search.c              52	
X src/shk.c                  9	
X src/shknam.c              43	
X src/sit.c                 34	
X src/sounds.c              40	
X src/sp_lev.c              42	
X src/spell.c               45	
X src/steal.c               44	
X src/termcap.c             38	
X src/timeout.c             50	
X src/topl.c                49	
X src/topten.c              36	
X src/track.c               56	
X src/trap.c                 8	
X src/u_init.c              38	
X src/uhitm.c               11	
X src/unixmain.c            46	
X src/unixtty.c             52	
X src/unixunix.c            49	
X src/vault.c               43	
X src/version.c             54	
X src/weapon.c              47	
X src/were.c                55	
X src/wield.c               35	
X src/wizard.c              48	
X src/worm.c                50	
X src/worn.c                53	
X src/write.c               54	
X src/zap.c                  3	
X vms                        1	
X vms/install.com           24	
X vms/lev_lex.h             56	
X vms/oldcrtl.c             51	
X vms/spec_lev.com          56	
X vms/vmsbuild.com          49	
X vms/vmsmain.c              6	
X vms/vmsmisc.c             56	
X vms/vmstermcap.c          19	
X vms/vmstparam.c           45	
X vms/vmstty.c              49	
X vms/vmsunix.c             49	
END_OF_FILE
if test 8360 -ne `wc -c <'MANIFEST'`; then
    echo shar: \"'MANIFEST'\" unpacked with wrong size!
fi
# end of 'MANIFEST'
fi
if test ! -d 'amiga' ; then
    echo shar: Creating directory \"'amiga'\"
    mkdir 'amiga'
fi
if test ! -d 'auxil' ; then
    echo shar: Creating directory \"'auxil'\"
    mkdir 'auxil'
fi
if test ! -d 'include' ; then
    echo shar: Creating directory \"'include'\"
    mkdir 'include'
fi
if test ! -d 'mac' ; then
    echo shar: Creating directory \"'mac'\"
    mkdir 'mac'
fi
if test ! -d 'others' ; then
    echo shar: Creating directory \"'others'\"
    mkdir 'others'
fi
if test ! -d 'src' ; then
    echo shar: Creating directory \"'src'\"
    mkdir 'src'
fi
if test -f 'src/makemon.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'src/makemon.c'\"
else
echo shar: Extracting \"'src/makemon.c'\" \(31716 characters\)
sed "s/^X//" >'src/makemon.c' <<'END_OF_FILE'
X/*	SCCS Id: @(#)makemon.c	3.0	89/11/22
X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
X/* NetHack may be freely redistributed.  See license for details. */
X
X#include "hack.h"
X#ifdef REINCARNATION
X# include <ctype.h>
X#endif
X
XSTATIC_VAR struct monst NEARDATA zeromonst;
X
X#ifdef OVL0
Xstatic int NDECL(cmnum);
Xstatic int FDECL(uncommon, (struct permonst *));
X#endif /* OVL0 */
XSTATIC_DCL void FDECL(m_initgrp,(struct monst *,int,int,int));
XSTATIC_DCL void FDECL(m_initthrow,(struct monst *,int,int));
XSTATIC_DCL void FDECL(m_initweap,(struct monst *));
XSTATIC_DCL void FDECL(rloc_to,(struct monst *,int,int));
X#ifdef OVL1
Xstatic void FDECL(m_initinv,(struct monst *));
Xstatic int FDECL(mstrength,(struct permonst *));
X#endif /* OVL1 */
X
Xextern int monstr[];
X
X#ifdef OVLB
X
Xint monstr[NUMMONS];
X
X#endif /* OVLB */
X
X#define m_initsgrp(mtmp, x, y)	m_initgrp(mtmp, x, y, 3)
X#define m_initlgrp(mtmp, x, y)	m_initgrp(mtmp, x, y, 10)
X#define toostrong(monindx, lev) (monstr[monindx] > lev)
X#define tooweak(monindx, lev)	(monstr[monindx] < lev)
X
X#ifdef OVLB
X
XSTATIC_OVL void
Xm_initgrp(mtmp, x, y, n)	/* make a group just like mtmp */
Xregister struct monst *mtmp;
Xregister int x, y, n;
X{
X	coord mm;
X	register int cnt = rnd(n);
X	struct monst *mon;
X
X/*
X *	Temporary kludge to cut down on swarming at lower character levels
X *	till we can get this game a little more balanced. [mrs]
X */
X	cnt /= (u.ulevel < 3) ? 4 : (u.ulevel < 5) ? 2 : 1;
X	if(!cnt) cnt++;
X
X	mm.x = x;
X	mm.y = y;
X	while(cnt--) {
X		if (peace_minded(mtmp->data)) continue;
X		/* Don't create groups of peaceful monsters since they'll get
X		 * in our way.  If the monster has a percentage chance so some
X		 * are peaceful and some are not, the result will just be a
X		 * smaller group.
X		 */
X		if (enexto(&mm, mm.x, mm.y, mtmp->data)) {
X		    mon = makemon(mtmp->data, mm.x, mm.y);
X		    mon->mpeaceful = 0;
X		    set_malign(mon);
X		    /* Undo the second peace_minded() check in makemon(); if the
X		     * monster turned out to be peaceful the first time we
X		     * didn't create it at all; we don't want a second check.
X		     */
X		}
X	}
X}
X
XSTATIC_OVL
Xvoid
Xm_initthrow(mtmp,otyp,oquan)
Xstruct monst *mtmp;
Xint otyp,oquan;
X{
X	register struct obj *otmp;
X
X	otmp = mksobj(otyp,FALSE);
X	otmp->quan = 2 + rnd(oquan);
X	otmp->owt = weight(otmp);
X#ifdef TOLKIEN
X	if (otyp == ORCISH_ARROW) otmp->opoisoned = 1;
X#endif
X	mpickobj(mtmp, otmp);
X}
X
X#endif /* OVLB */
X#ifdef OVL2
X
XSTATIC_OVL void
Xm_initweap(mtmp)
Xregister struct monst *mtmp;
X{
X	register struct permonst *ptr = mtmp->data;
X	register int mm = monsndx(ptr);
X#ifdef REINCARNATION
X	if (dlevel==rogue_level) return;
X#endif
X/*
X *	first a few special cases:
X *
X *		giants get a boulder to throw sometimes.
X *		ettins get clubs
X *		kobolds get darts to throw
X *		centaurs get some sort of bow & arrows or bolts
X *		soldiers get all sorts of things.
X *		kops get clubs & cream pies.
X */
X	switch (mtmp->data->mlet) {
X	    case S_GIANT:
X		if (rn2(2)) (void)mongets(mtmp, (ptr != &mons[PM_ETTIN]) ?
X				    BOULDER : CLUB);
X		break;
X	    case S_HUMAN:
X		if(is_mercenary(ptr))
X		    switch (mm) {
X
X#ifdef ARMY
X			case PM_SOLDIER:
X			  (void) mongets(mtmp, rn2(2) ? SPEAR : SHORT_SWORD);
X			  break;
X			case PM_SERGEANT:
X			  (void) mongets(mtmp, rn2(2) ? FLAIL : MACE);
X			  break;
X			case PM_LIEUTENANT:
X			  (void) mongets(mtmp, rn2(2) ? GLAIVE : LONG_SWORD);
X			  break;
X			case PM_CAPTAIN:
X			  (void) mongets(mtmp, rn2(2) ? LONG_SWORD : SCIMITAR);
X			  break;
X#endif
X			default:    if (!rn2(4)) (void) mongets(mtmp, DAGGER);
X				    if (!rn2(7)) (void) mongets(mtmp, SPEAR);
X				    break;
X		    }
X		    break;
X
X	    case S_HUMANOID:
X#ifdef TOLKIEN
X		if (mm == PM_HOBBIT) {
X		    switch (rn2(3)) {
X			case 0:
X			    (void)mongets(mtmp, DAGGER);
X			    break;
X			case 1:
X			    (void)mongets(mtmp, ELVEN_DAGGER);
X			    break;
X			case 2:
X			    (void)mongets(mtmp, SLING);
X			    break;
X		      }
X		    if (!rn2(10)) (void)mongets(mtmp, ELVEN_MITHRIL_COAT);
X		} else if (is_dwarf(ptr)) {
X		    (void)mongets(mtmp, DWARVISH_CLOAK);
X		    (void)mongets(mtmp, IRON_SHOES);
X		    if (!rn2(4)) {
X			(void)mongets(mtmp, DWARVISH_SHORT_SWORD);
X			/* note: you can't use a mattock with a shield */
X			if (rn2(2)) (void)mongets(mtmp, DWARVISH_MATTOCK);
X			else {
X				(void)mongets(mtmp, AXE);
X				(void)mongets(mtmp, DWARVISH_ROUNDSHIELD);
X			}
X			(void)mongets(mtmp, DWARVISH_IRON_HELM);
X			if (!rn2(3))
X			    (void)mongets(mtmp, DWARVISH_MITHRIL_COAT);
X		    } else {
X			(void)mongets(mtmp, PICK_AXE);
X		    }
X		} else if (is_elf(ptr)) {
X		    (void)mongets(mtmp,
X			rn2(2) ? ELVEN_MITHRIL_COAT : ELVEN_CLOAK);
X		    if (rn2(2)) (void)mongets(mtmp, ELVEN_LEATHER_HELM);
X		    if (rn2(3)) (void)mongets(mtmp, ELVEN_DAGGER);
X		    switch (rn2(3)) {
X			case 0:
X			    if (!rn2(4)) (void)mongets(mtmp, ELVEN_SHIELD);
X			    (void)mongets(mtmp, ELVEN_SHORT_SWORD);
X			    (void)mongets(mtmp, ELVEN_BOW);
X			    m_initthrow(mtmp, ELVEN_ARROW, 12);
X			    break;
X			case 1:
X			    (void)mongets(mtmp, ELVEN_BROADSWORD);
X			    if (rn2(2)) (void)mongets(mtmp, ELVEN_SHIELD);
X			    break;
X			case 2:
X			    (void)mongets(mtmp, ELVEN_SPEAR);
X			    (void)mongets(mtmp, ELVEN_SHIELD);
X			    break;
X		    }
X		}
X#else /* TOLKIEN */
X		if (is_dwarf(ptr)) {
X		    (void)mongets(mtmp, IRON_SHOES);
X		    if (rn2(4) == 0) {
X			(void)mongets(mtmp, SHORT_SWORD);
X			if (rn2(2)) (void)mongets(mtmp, TWO_HANDED_SWORD);
X			else {
X				(void)mongets(mtmp, AXE);
X				(void)mongets(mtmp, LARGE_SHIELD);
X			}
X			if (rn2(3) == 0)
X			    (void)mongets(mtmp, DWARVISH_MITHRIL_COAT);
X		    } else {
X			(void)mongets(mtmp, PICK_AXE);
X		    }
X		} else if (is_elf(ptr)) {
X		    (void)mongets(mtmp, ELVEN_CLOAK);
X		    if (rn2(3)) (void)mongets(mtmp, DAGGER);
X		    switch (rn2(3)) {
X			case 0:
X			    if (!rn2(4)) (void)mongets(mtmp, SMALL_SHIELD);
X			    (void)mongets(mtmp, SHORT_SWORD);
X			    (void)mongets(mtmp, BOW);
X			    m_initthrow(mtmp, ARROW, 12);
X			    break;
X			case 1:
X			    (void)mongets(mtmp, BROADSWORD);
X			    if (rn2(2)) (void)mongets(mtmp, SMALL_SHIELD);
X			    break;
X			case 2:
X			    (void)mongets(mtmp, SPEAR);
X			    (void)mongets(mtmp, SMALL_SHIELD);
X			    break;
X		    }
X		}
X#endif /* TOLKIEN */
X		break;
X# ifdef KOPS
X	    case S_KOP:		/* create Keystone Kops with cream pies to
X				 * throw. As suggested by KAA.	   [MRS]
X				 */
X		if (!rn2(4)) m_initthrow(mtmp, CREAM_PIE, 2);
X		if (!rn2(3)) (void)mongets(mtmp, (rn2(2)) ? CLUB : RUBBER_HOSE);
X		break;
X#endif
X	    case S_ORC:
X		if(rn2(2)) (void)mongets(mtmp, ORCISH_HELM);
X#ifdef TOLKIEN
X		switch (mm != PM_ORC_CAPTAIN ? mm :
X			rn2(2) ? PM_MORDOR_ORC : PM_URUK_HAI) {
X		    case PM_MORDOR_ORC:
X			if(rn2(2)) (void)mongets(mtmp, SCIMITAR);
X			if(rn2(2)) (void)mongets(mtmp, ORCISH_SHIELD);
X			if(rn2(2)) (void)mongets(mtmp, KNIFE);
X			if(rn2(2)) (void)mongets(mtmp, ORCISH_CHAIN_MAIL);
X			break;
X		    case PM_URUK_HAI:
X			if(rn2(2)) (void)mongets(mtmp, ORCISH_CLOAK);
X			if(rn2(2)) (void)mongets(mtmp, ORCISH_SHORT_SWORD);
X			if(rn2(2)) (void)mongets(mtmp, IRON_SHOES);
X			if(rn2(2)) {
X			    (void)mongets(mtmp, ORCISH_BOW);
X			    m_initthrow(mtmp, ORCISH_ARROW, 12);
X			}
X			if(rn2(2)) (void)mongets(mtmp, URUK_HAI_SHIELD);
X			break;
X		    default:
X			if (mm != PM_ORC_SHAMAN)
X			  (void)mongets(mtmp, (mm == PM_GOBLIN || rn2(2) == 0) ?
X					      ORCISH_DAGGER : SCIMITAR);
X#else /* TOLKIEN */
X		switch (mm) {
X		    case  PM_ORC_CAPTAIN:
X			if(rn2(2)) {
X			    if(rn2(2)) (void)mongets(mtmp, SCIMITAR);
X			    if(rn2(2)) (void)mongets(mtmp, SMALL_SHIELD);
X			    if(rn2(2)) (void)mongets(mtmp, KNIFE);
X			    if(rn2(2)) (void)mongets(mtmp, CHAIN_MAIL);
X			} else {
X			    if(rn2(2)) (void)mongets(mtmp, SHORT_SWORD);
X			    if(rn2(2)) (void)mongets(mtmp, IRON_SHOES);
X			    if(rn2(2)) {
X				(void)mongets(mtmp, BOW);
X				m_initthrow(mtmp, ARROW, 12);
X			    }
X			    if(rn2(2)) (void)mongets(mtmp, SMALL_SHIELD);
X			}
X		    default:
X			if (mm != PM_ORC_SHAMAN)
X			  (void)mongets(mtmp, (mm == PM_GOBLIN || rn2(2) == 0) ?
X					      DAGGER : SCIMITAR);
X#endif /* TOLKIEN */
X		}
X		break;
X	    case S_KOBOLD:
X		if (!rn2(4)) m_initthrow(mtmp, DART, 12);
X		break;
X
X	    case S_CENTAUR:
X		if (rn2(2)) {
X		    if(ptr == &mons[PM_FOREST_CENTAUR]) {
X			(void)mongets(mtmp, BOW);
X			m_initthrow(mtmp, ARROW, 12);
X		    } else {
X			(void)mongets(mtmp, CROSSBOW);
X			m_initthrow(mtmp, CROSSBOW_BOLT, 12);
X		    }
X		}
X		break;
X	    case S_WRAITH:
X		(void)mongets(mtmp, KNIFE);
X		(void)mongets(mtmp, LONG_SWORD);
X		break;
X	    case S_DEMON:
X#ifdef INFERNO
X		switch (mm) {
X		    case PM_BALROG:
X			(void)mongets(mtmp, BULLWHIP);
X			(void)mongets(mtmp, BROADSWORD);
X			break;
X		    case PM_ORCUS:
X			(void)mongets(mtmp, WAN_DEATH); /* the Wand of Orcus */
X			break;
X		    case PM_HORNED_DEVIL:
X			(void)mongets(mtmp, rn2(4) ? TRIDENT : BULLWHIP);
X			break;
X		    case PM_ICE_DEVIL:
X			if (!rn2(4)) (void)mongets(mtmp, SPEAR);
X			break;
X		    case PM_ASMODEUS:
X			(void)mongets(mtmp, WAN_COLD);
X			break;
X		    case PM_DISPATER:
X			(void)mongets(mtmp, WAN_STRIKING);
X			break;
X		    case PM_YEENOGHU:
X			(void)mongets(mtmp, FLAIL);
X			break;
X		}
X#endif
X		/* prevent djinnis and mail daemons from leaving objects when
X		 * they vanish
X		 */
X		if (!is_demon(ptr)) break;
X		/* fall thru */
X/*
X *	Now the general case, ~40% chance of getting some type
X *	of weapon. TODO: Add more weapons types (use bigmonst());
X */
X	    default:
X		switch(rnd(12)) {
X		    case 1:
X			m_initthrow(mtmp, DART, 12);
X			break;
X		    case 2:
X			(void) mongets(mtmp, CROSSBOW);
X			m_initthrow(mtmp, CROSSBOW_BOLT, 12);
X			break;
X		    case 3:
X			(void) mongets(mtmp, BOW);
X			m_initthrow(mtmp, ARROW, 12);
X			break;
X		    case 4:
X			m_initthrow(mtmp, DAGGER, 3);
X			break;
X		    case 5:
X			(void) mongets(mtmp, AKLYS);
X			break;
X		    default:
X			break;
X		}
X		break;
X	}
X}
X
X#endif /* OVL2 */
X#ifdef OVL1
X
Xstatic void
Xm_initinv(mtmp)
Xregister struct	monst	*mtmp;
X{
X	register int cnt;
X	register struct obj *otmp;
X	register struct permonst *ptr = mtmp->data;
X#ifdef REINCARNATION
X	if (dlevel==rogue_level) return;
X#endif
X/*
X *	Soldiers get armour & rations - armour approximates their ac.
X *	Nymphs may get mirror or potion of object detection.
X */
X	switch(mtmp->data->mlet) {
X
X	    case S_HUMAN:
X		if(is_mercenary(ptr)) {
X		    register int mac;
X
X		    if((mac = ptr->ac) < -1)
X			mac += 7 + mongets(mtmp, (rn2(5)) ?
X					   PLATE_MAIL : CRYSTAL_PLATE_MAIL);
X		    else if(mac < 3)
X			mac += 6 + mongets(mtmp, (rn2(3)) ?
X					   SPLINT_MAIL : BANDED_MAIL);
X		    else
X			mac += 3 + mongets(mtmp, (rn2(3)) ?
X					   RING_MAIL : STUDDED_LEATHER_ARMOR);
X
X		    if(mac < 10) {
X			mac += 1 + mongets(mtmp, HELMET);
X			if(mac < 10) {
X			    mac += 1 + mongets(mtmp, SMALL_SHIELD);
X			    if(mac < 10) {
X				mac += 1 + mongets(mtmp, ELVEN_CLOAK);
X				if(mac < 10)
X				    mac += 1 +mongets(mtmp, LEATHER_GLOVES);
X			    }
X			}
X		    }
X
X		    if(mac != 10) {	/* make up the difference */
X			otmp = mksobj(RIN_PROTECTION,FALSE);
X			otmp->spe = (10 - mac);
X			if(otmp->spe < 0) curse(otmp);
X			mpickobj(mtmp, otmp);
X		    }
X#ifdef ARMY
X		    if(ptr != &mons[PM_GUARD]) {
X			if (!rn2(3)) (void) mongets(mtmp, K_RATION);
X			if (!rn2(2)) (void) mongets(mtmp, C_RATION);
X		    }
X#endif
X		} else if (ptr == &mons[PM_SHOPKEEPER]) {
X		    (void) mongets(mtmp,SKELETON_KEY);
X		}
X		break;
X
X	    case S_NYMPH:
X#ifdef MEDUSA
X		if(!rn2(2)) (void) mongets(mtmp, MIRROR);
X#endif
X		if(!rn2(2)) (void) mongets(mtmp, POT_OBJECT_DETECTION);
X		break;
X
X	    case S_GIANT:
X		if(mtmp->data == &mons[PM_MINOTAUR])
X		    (void) mongets(mtmp, WAN_DIGGING);
X		else if (is_giant(mtmp->data)) {
X		    for(cnt = rn2((int)(mtmp->m_lev / 2)); cnt; cnt--) {
X			    do
X				otmp = mkobj(GEM_SYM,FALSE);
X			    while (otmp->otyp >= LAST_GEM+6);
X			    otmp->quan = 2 + rnd(2);
X			    otmp->owt = weight(otmp);
X			    mpickobj(mtmp, otmp);
X		    }
X		}
X		break;
X#ifdef TOLKIEN
X	    case S_WRAITH:
X		if(mtmp->data == &mons[PM_NAZGUL]) {
X			otmp = mksobj(RIN_INVISIBILITY, FALSE);
X			curse(otmp);
X			mpickobj(mtmp, otmp);
X		}
X		break;
X#endif
X	    default:
X		break;
X	}
X}
X
X/*
X * called with [x,y] = coordinates;
X *	[0,0] means anyplace
X *	[u.ux,u.uy] means: near player (if !in_mklev)
X *
X *	In case we make a monster group, only return the one at [x,y].
X */
Xstruct monst *
Xmakemon(ptr, x, y)
Xregister struct permonst *ptr;
Xregister int	x, y;
X{
X	register struct monst *mtmp;
X	register int	ct;
X	boolean anything = (!ptr);
X	boolean byyou = (x == u.ux && y == u.uy);
X
X	/* if caller wants random location, do it here */
X	if(x == 0 && y == 0) {
X		int uroom;
X		int tryct = 0;	/* careful with bigrooms */
X#ifdef __GNULINT__
X		uroom = 0;	/* supress used before set warning */
X#endif
X		if(!in_mklev) uroom = inroom(u.ux, u.uy);
X
X		do {
X			x = rn1(COLNO-3,2);
X			y = rn2(ROWNO);
X		} while(!goodpos(x, y, ptr) ||
X			(!in_mklev && tryct++ < 50 && inroom(x, y) == uroom));
X	} else if (byyou && !in_mklev) {
X		coord bypos;
X
X		if(enexto(&bypos, u.ux, u.uy, ptr)) {
X			x = bypos.x;
X			y = bypos.y;
X		} else
X			return((struct monst *)0);
X	}
X
X	/* if a monster already exists at the position, return */
X	if(MON_AT(x, y))
X		return((struct monst *) 0);
X
X	if(ptr){
X		/* if you are to make a specific monster and it has
X		   already been genocided, return */
X		if(ptr->geno & G_GENOD) return((struct monst *) 0);
X	} else {
X		/* make a random (common) monster. */
X		if(!(ptr = rndmonst()))
X		{
X#ifdef DEBUG
X		    pline("Warning: no monster.");
X#endif
X		    return((struct monst *) 0);	/* no more monsters! */
X		}
X	}
X	/* if it's unique, don't ever make it again */
X	if (ptr->geno & G_UNIQ) ptr->geno |= G_GENOD;
X/* gotmon:	/* label not referenced */
X	mtmp = newmonst(ptr->pxlth);
X	*mtmp = zeromonst;		/* clear all entries in structure */
X	for(ct = 0; ct < ptr->pxlth; ct++)
X		((char *) &(mtmp->mextra[0]))[ct] = 0;
X	mtmp->nmon = fmon;
X	fmon = mtmp;
X	mtmp->m_id = flags.ident++;
X	mtmp->data = ptr;
X	mtmp->mxlth = ptr->pxlth;
X
X	mtmp->m_lev = adj_lev(ptr);
X#ifdef GOLEMS
X	if (is_golem(ptr))
X	    mtmp->mhpmax = mtmp->mhp = golemhp(monsndx(ptr));
X	else
X#endif /* GOLEMS */
X	if(ptr->mlevel > 49) {
X	    /* "special" fixed hp monster
X	     * the hit points are encoded in the mlevel in a somewhat strange
X	     * way to fit in the 50..127 positive range of a signed character
X	     * above the 1..49 that indicate "normal" monster levels */
X	    mtmp->mhpmax = mtmp->mhp = 2*(ptr->mlevel - 6);
X	    mtmp->m_lev = mtmp->mhp / 4;	/* approximation */
X	} else if((ptr->mlet == S_DRAGON) && (ptr >= &mons[PM_GRAY_DRAGON]))
X	    mtmp->mhpmax = mtmp->mhp = 80;
X	else if(!mtmp->m_lev) mtmp->mhpmax = mtmp->mhp = rnd(4);
X	else mtmp->mhpmax = mtmp->mhp = d((int)mtmp->m_lev, 8);
X	place_monster(mtmp, x, y);
X	mtmp->mcansee = mtmp->mcanmove = 1;
X	mtmp->mpeaceful = peace_minded(ptr);
X
X	switch(ptr->mlet) {
X		case S_MIMIC:
X			set_mimic_sym(mtmp);
X			break;
X		case S_SPIDER:
X		case S_SNAKE:
X			mtmp->mhide = 1;
X			if(in_mklev)
X			    if(x && y)
X				(void) mkobj_at(0, x, y, TRUE);
X			if(OBJ_AT(x, y) || levl[x][y].gmask)
X			    mtmp->mundetected = 1;
X			break;
X		case S_STALKER:
X		case S_EEL:
X			mtmp->minvis = 1;
X			break;
X		case S_LEPRECHAUN:
X			mtmp->msleep = 1;
X			break;
X		case S_JABBERWOCK:
X		case S_NYMPH:
X			if(rn2(5) && !u.uhave_amulet) mtmp->msleep = 1;
X			break;
X		case S_UNICORN:
X			if ((ptr==&mons[PM_WHITE_UNICORN] &&
X				u.ualigntyp == U_LAWFUL) ||
X			(ptr==&mons[PM_GRAY_UNICORN] &&
X				u.ualigntyp == U_NEUTRAL) ||
X			(ptr==&mons[PM_BLACK_UNICORN] &&
X				u.ualigntyp == U_CHAOTIC))
X				mtmp->mpeaceful = 1;
X			break;
X	}
X	if (ptr == &mons[PM_CHAMELEON]) {
X		/* If you're protected with a ring, don't create
X		 * any shape-changing chameleons -dgk
X		 */
X		if (Protection_from_shape_changers)
X			mtmp->cham = 0;
X		else {
X			mtmp->cham = 1;
X			(void) newcham(mtmp, rndmonst());
X		}
X	} else if (ptr == &mons[PM_WIZARD_OF_YENDOR]) {
X		mtmp->iswiz = 1;
X		flags.no_of_wizards++;
X	} else if (ptr == &mons[PM_QUANTUM_MECHANIC])
X		mtmp = qname(mtmp);
X
X	if(in_mklev) {
X		if(((is_ndemon(ptr)) ||
X		    (ptr == &mons[PM_WUMPUS]) ||
X#ifdef WORM
X		    (ptr == &mons[PM_LONG_WORM]) ||
X#endif
X		    (ptr == &mons[PM_GIANT_EEL])) && rn2(5))
X			mtmp->msleep = 1;
X	} else {
X		if(byyou) {
X			pmon(mtmp);
X			set_apparxy(mtmp);
X		}
X	}
X#ifdef INFERNO
X	if(is_dprince(ptr)) {
X	    mtmp->mpeaceful = mtmp->minvis = 1;
X# ifdef NAMED_ITEMS
X	    if(uwep)
X		if(!strcmp(ONAME(uwep), "Excalibur"))
X		    mtmp->mpeaceful = mtmp->mtame = 0;
X# endif
X	}
X#endif
X#ifdef WORM
X	if(ptr == &mons[PM_LONG_WORM] && getwn(mtmp))  initworm(mtmp);
X#endif
X	set_malign(mtmp);		/* having finished peaceful changes */
X	if(anything) {
X	    if((ptr->geno & G_SGROUP) && rn2(2))
X		m_initsgrp(mtmp, mtmp->mx, mtmp->my);
X	    else if(ptr->geno & G_LGROUP) {
X			if(rn2(3))  m_initlgrp(mtmp, mtmp->mx, mtmp->my);
X			else	    m_initsgrp(mtmp, mtmp->mx, mtmp->my);
X	    }
X	}
X
X	if(is_armed(ptr))
X		m_initweap(mtmp);	/* equip with weapons / armour */
X	m_initinv(mtmp);		/* add on a few special items */
X
X	return(mtmp);
X}
X
Xboolean
Xenexto(cc, xx, yy, mdat)
Xcoord *cc;
Xregister xchar xx, yy;
Xstruct permonst *mdat;
X{
X	register xchar x,y;
X	coord foo[15], *tfoo;
X	int range, i;
X	int xmin, xmax, ymin, ymax;
X
X	tfoo = foo;
X	range = 1;
X	do {	/* full kludge action. */
X		xmin = max(0, xx-range);
X		xmax = min(COLNO, xx+range);
X		ymin = max(0, yy-range);
X		ymax = min(ROWNO, yy+range);
X
X		for(x = xmin; x <= xmax; x++)
X			if(goodpos(x, ymin, mdat)) {
X				tfoo->x = x;
X				(tfoo++)->y = ymin;
X				if(tfoo == &foo[15]) goto foofull;
X			}
X		for(x = xmin; x <= xmax; x++)
X			if(goodpos(x, ymax, mdat)) {
X				tfoo->x = x;
X				(tfoo++)->y = ymax;
X				if(tfoo == &foo[15]) goto foofull;
X			}
X		for(y = ymin+1; y < ymax; y++)
X			if(goodpos(xmin, y, mdat)) {
X				tfoo->x = xmin;
X				(tfoo++)->y = y;
X				if(tfoo == &foo[15]) goto foofull;
X			}
X		for(y = ymin+1; y < ymax; y++)
X			if(goodpos(xmax, y, mdat)) {
X				tfoo->x = xmax;
X				(tfoo++)->y = y;
X				if(tfoo == &foo[15]) goto foofull;
X			}
X		range++;
X		if(range > ROWNO && range > COLNO) return FALSE;
X	} while(tfoo == foo);
Xfoofull:
X	i = rn2((int)(tfoo - foo));
X	cc->x = foo[i].x;
X	cc->y = foo[i].y;
X	return TRUE;
X}
X
Xint
Xgoodpos(x, y, mdat)
Xint x,y;
Xstruct permonst *mdat;
X{
X	if (x < 1 || x > COLNO-2 || y < 1 || y > ROWNO-2 || MON_AT(x, y))
X		return 0;
X	if (x == u.ux && y == u.uy) return 0;
X	if (mdat) {
X	    if (IS_POOL(levl[x][y].typ))
X		if (mdat == &playermon && (HLevitation || Wwalking))
X			return 1;
X		else	return (is_flyer(mdat) || is_swimmer(mdat));
X	    if (passes_walls(mdat)) return 1;
X	}
X	if (!ACCESSIBLE(levl[x][y].typ)) return 0;
X	if (closed_door(x, y) && (!mdat || !amorphous(mdat)))
X		return 0;
X	if (sobj_at(BOULDER, x, y) && (!mdat || !throws_rocks(mdat)))
X		return 0;
X	return 1;
X}
X
X#endif /* OVL1 */
X#ifdef OVLB
X
XSTATIC_OVL
Xvoid
Xrloc_to(mtmp, x, y)
Xstruct monst *mtmp;
Xregister int x,y;
X{
X#ifdef WORM		/* do not relocate worms */
X	if(mtmp->wormno && mtmp->mx) return;
X#endif
X	if(mtmp->mx != 0 && mtmp->my != 0)
X		remove_monster(mtmp->mx, mtmp->my);
X	place_monster(mtmp, x, y);
X	if(u.ustuck == mtmp){
X		if(u.uswallow) {
X			u.ux = x;
X			u.uy = y;
X			docrt();
X		} else	u.ustuck = 0;
X	}
X	pmon(mtmp);
X	set_apparxy(mtmp);
X}
X
X#endif /* OVLB */
X#ifdef OVL2
X
Xvoid
Xrloc(mtmp)
Xstruct monst *mtmp;
X{
X	register int x, y;
X
X	/* if the wiz teleports away to heal, try the up staircase,
X	   to block the player's escaping before he's healed */
X	if(!mtmp->iswiz || !goodpos(x = xupstair, y = yupstair, mtmp->data))
X	   do {
X		x = rn1(COLNO-3,2);
X		y = rn2(ROWNO);
X	   } while(!goodpos(x,y,mtmp->data));
X	rloc_to(mtmp, x, y);
X}
X
X#endif /* OVL2 */
X#ifdef OVLB
X
Xvoid
Xvloc(mtmp)
Xstruct monst *mtmp;
X{
X	register struct mkroom *croom;
X	register int x, y;
X
X	for(croom = &rooms[0]; croom->hx >= 0; croom++)
X	    if(croom->rtype == VAULT) {
X		x = rn2(2) ? croom->lx : croom->hx;
X		y = rn2(2) ? croom->ly : croom->hy;
X		if(goodpos(x, y, mtmp->data)) {
X		    rloc_to(mtmp, x, y);
X		    return;
X		}
X	    }
X	rloc(mtmp);
X}
X
X#endif /* OVLB */
X#ifdef OVL0
X
Xstatic int
Xcmnum()	{	/* return the number of "common" monsters */
X
X	int	i, count;
X
X	for(i = count = 0; mons[i].mlet; i++)
X	   if(!uncommon(&mons[i]))  count++;
X
X	return(count);
X}
X
Xstatic int
Xuncommon(ptr)
Xstruct	permonst *ptr;
X{
X	return (ptr->geno & (G_GENOD | G_NOGEN | G_UNIQ)) ||
X		(!Inhell ? ptr->geno & G_HELL : ptr->maligntyp > 0);
X}
X
X#endif /* OVL0 */
X#ifdef OVL1
X
X/* This routine is designed to return an integer value which represents
X * an approximation of monster strength.  It uses a similar method of
X * determination as "experience()" to arrive at the strength.
X */
Xstatic int
Xmstrength(ptr)
Xstruct permonst *ptr;
X{
X	int	i, tmp2, n, tmp = ptr->mlevel;
X
X	if(tmp > 49)		/* special fixed hp monster */
X	    tmp = 2*(tmp - 6) / 4;
X
X/*	For creation in groups */
X	n = (!!(ptr->geno & G_SGROUP));
X	n += (!!(ptr->geno & G_LGROUP)) << 1;
X
X/*	For ranged attacks */
X	if (ranged_attk(ptr)) n++;
X
X/*	For higher ac values */
X	n += (ptr->ac < 0);
X
X/*	For very fast monsters */
X	n += (ptr->mmove >= 18);
X
X/*	For each attack and "special" attack */
X	for(i = 0; i < NATTK; i++) {
X
X	    tmp2 = ptr->mattk[i].aatyp;
X	    n += (tmp2 > 0);
X	    n += (tmp2 == AT_MAGC);
X	    n += (tmp2 == AT_WEAP && strongmonst(ptr));
X	}
X
X/*	For each "special" damage type */
X	for(i = 0; i < NATTK; i++) {
X
X	    tmp2 = ptr->mattk[i].adtyp;
X	    if((tmp2 == AD_DRLI) || (tmp2 == AD_STON)
X#ifdef POLYSELF
X					|| (tmp2 == AD_WERE)
X#endif
X								) n += 2;
X	    else if (ptr != &mons[PM_GRID_BUG]) n += (tmp2 != AD_PHYS);
X	    n += ((ptr->mattk[i].damd * ptr->mattk[i].damn) > 23);
X	}
X
X/*	Leprechauns are special cases.  They have many hit dice so they
X	can hit and are hard to kill, but they don't really do much damage. */
X	if (ptr == &mons[PM_LEPRECHAUN]) n -= 2;
X
X/*	Finally, adjust the monster level  0 <= n <= 24 (approx.) */
X	if(n == 0) tmp--;
X	else if(n >= 6) tmp += ( n / 2 );
X	else tmp += ( n / 3 + 1);
X
X	return((tmp >= 0) ? tmp : 0);
X}
X
Xvoid
Xinit_monstr()
X{
X	register int ct;
X
X	for(ct = 0; mons[ct].mlet; ct++)
X		monstr[ct] = mstrength(&(mons[ct]));
X}
X
X#endif /* OVL1 */
X#ifdef OVL0
X
Xstruct	permonst *
Xrndmonst()		/* select a random monster */
X{
X	register struct permonst *ptr;
X	register int i, ct;
X	register int zlevel;
X	static int NEARDATA minmlev, NEARDATA maxmlev, NEARDATA accept;
X	static long NEARDATA oldmoves = 0L;	/* != 1, starting value of moves */
X#ifdef REINCARNATION
X	static boolean NEARDATA upper;
X
X	upper = (dlevel == rogue_level);
X#endif
X
X#ifdef __GNULINT__
X	ptr = (struct permonst *)0; /* suppress "used uninitialized" warning */
X#endif
X	if(oldmoves != moves) {		/* must recalculate accept */
X	    oldmoves = moves;
X	    zlevel = u.uhave_amulet ? MAXLEVEL : dlevel;
X	    if(cmnum() <= 0) {
X#ifdef DEBUG
X		pline("cmnum() fails!");
X#endif
X		return((struct permonst *) 0);
X	    }
X
X	    /* determine the level of the weakest monster to make. */
X	    minmlev = zlevel/6;
X	    /* determine the level of the strongest monster to make. */
X	    maxmlev = (zlevel + u.ulevel)>>1;
X/*
X *	Find out how many monsters exist in the range we have selected.
X */
X	    accept = 0;
X#ifdef REINCARNATION
X	    for(ct = (upper ? PM_APE : 0);
X			upper ? isupper(mons[ct].mlet) : mons[ct].mlet; ct++) {
X#else
X	    for(ct = 0 ; mons[ct].mlet; ct++) {
X#endif
X		ptr = &(mons[ct]);
X		if(uncommon(ptr)) continue;
X		if(tooweak(ct, minmlev) || toostrong(ct, maxmlev))
X		    continue;
X		accept += (ptr->geno & G_FREQ);
X	    }
X	}
X
X	if(!accept) {
X#ifdef DEBUG
X		pline("no accept!");
X#endif
X		return((struct permonst *) 0);
X	}
X/*
X *	Now, select a monster at random.
X */
X	ct = rnd(accept);
X#ifdef REINCARNATION
X	for(i = (upper ? PM_APE : 0);
X	    (upper ? isupper(mons[i].mlet) : mons[i].mlet) && ct > 0; i++) {
X#else
X	for(i = 0; mons[i].mlet && ct > 0; i++) {
X#endif
X		ptr = &(mons[i]);
X		if(uncommon(ptr)) continue;
X		if(tooweak(i, minmlev) || toostrong(i, maxmlev))
X		    continue;
X		ct -= (ptr->geno & G_FREQ);
X	}
X	if(ct > 0) {
X#ifdef DEBUG
X		pline("no count!");
X#endif
X		return((struct permonst *) 0);
X	}
X	return(ptr);
X}
X
X#endif /* OVL0 */
X#ifdef OVL1
X
X/*	The routine below is used to make one of the multiple types
X *	of a given monster class.  It will return 0 if no monsters
X *	in that class can be made.
X */
X
Xstruct permonst *
Xmkclass(mlet)
Xchar	mlet;
X{
X	register int	first, last, num = 0;
X
X	if(!mlet) {
X	    impossible("mkclass called with null arg!");
X	    return((struct permonst *) 0);
X	}
X/*	Assumption #1:	monsters of a given class are contiguous in the
X *			mons[] array.
X */
X	for(first = 0; mons[first].mlet != mlet; first++)
X		if(!mons[first].mlet)	return((struct permonst *) 0);
X
X	for(last = first; mons[last].mlet && mons[last].mlet == mlet; last++)
X	    if(!(mons[last].geno & (G_GENOD | G_NOGEN | G_UNIQ)))
X		num += mons[last].geno & G_FREQ;
X
X	if(!num) return((struct permonst *) 0);
X
X/*	Assumption #2:	monsters of a given class are presented in ascending
X *			order of strength.
X */
X	for(num = rnd(num); num > 0; first++)
X	    if(!(mons[first].geno & (G_GENOD | G_NOGEN | G_UNIQ))) { /* consider it */
X		/* skew towards lower value monsters at lower exp. levels */
X		if(adj_lev(&mons[first]) > (u.ulevel*2)) num--;
X		num -= mons[first].geno & G_FREQ;
X	    }
X	first--; /* correct an off-by-one error */
X
X	return(&mons[first]);
X}
X
Xint
Xadj_lev(ptr)	/* adjust strength of monsters based on dlevel and u.ulevel */
Xregister struct permonst *ptr;
X{
X	int	tmp, tmp2;
X
X	if((tmp = ptr->mlevel) > 49) return(50); /* "special" demons/devils */
X	tmp2 = (dlevel - tmp);
X	if(tmp2 < 0) tmp--;		/* if mlevel > dlevel decrement tmp */
X	else tmp += (tmp2 / 5);		/* else increment 1 per five diff */
X
X	tmp2 = (u.ulevel - ptr->mlevel);	/* adjust vs. the player */
X	if(tmp2 > 0) tmp += (tmp2 / 4);		/* level as well */
X
X	tmp2 = 3 * ptr->mlevel/ 2;		/* crude upper limit */
X	return((tmp > tmp2) ? tmp2 : (tmp > 0 ? tmp : 0)); /* 0 lower limit */
X}
X
X#endif /* OVL1 */
X#ifdef OVLB
X
Xstruct permonst *
Xgrow_up(mtmp)		/* mon mtmp "grows up" to a bigger version. */
Xregister struct monst *mtmp;
X{
X	register int newtype;
X	register struct permonst *ptr = mtmp->data;
X
X	if (ptr->mlevel >= 50 || mtmp->mhpmax <= 8*mtmp->m_lev)
X	    return ptr;
X	newtype = little_to_big(monsndx(ptr));
X	if (++mtmp->m_lev >= mons[newtype].mlevel
X					&& newtype != monsndx(ptr)) {
X		if (mons[newtype].geno & G_GENOD) {
X			pline("As %s grows up into %s, %s dies!",
X				mon_nam(mtmp),
X				an(mons[newtype].mname),
X				mon_nam(mtmp));
X			mondied(mtmp);
X			return (struct permonst *)0;
X		}
X		mtmp->data = &mons[newtype];
X		mtmp->m_lev = mons[newtype].mlevel;
X	}
X	if (mtmp->m_lev > 3*mtmp->data->mlevel / 2)
X		mtmp->m_lev = 3*mtmp->data->mlevel / 2;
X	if (mtmp->mhp > mtmp->m_lev * 8)
X		mtmp->mhp = mtmp->m_lev * 8;
X	return(mtmp->data);
X}
X
X#endif /* OVLB */
X#ifdef OVL1
X
Xint
Xmongets(mtmp, otyp)
Xregister struct monst *mtmp;
Xregister int otyp;
X{
X	register struct obj *otmp;
X
X	if((otmp = (otyp) ? mksobj(otyp,FALSE) : mkobj(otyp,FALSE))) {
X	    if (mtmp->data->mlet == S_DEMON) {
X		/* demons always get cursed objects */
X		curse(otmp);
X	    }
X	    mpickobj(mtmp, otmp);
X	    return(otmp->spe);
X	} else return(0);
X}
X
X#endif /* OVL1 */
X#ifdef OVLB
X
X#ifdef GOLEMS
Xint
Xgolemhp(type)
Xint type;
X{
X	switch(type) {
X		case PM_STRAW_GOLEM: return 20;
X		case PM_ROPE_GOLEM: return 30;
X		case PM_LEATHER_GOLEM: return 40;
X		case PM_WOOD_GOLEM: return 50;
X		case PM_FLESH_GOLEM: return 40;
X		case PM_CLAY_GOLEM: return 50;
X		case PM_STONE_GOLEM: return 60;
X		case PM_IRON_GOLEM: return 80;
X		default: return 0;
X	}
X}
X#endif /* GOLEMS */
X
X#endif /* OVLB */
X#ifdef OVL1
X
X/*
X *	Alignment vs. yours determines monster's attitude to you.
X *	( some "animal" types are co-aligned, but also hungry )
X */
Xboolean
Xpeace_minded(ptr)
Xregister struct permonst *ptr;
X{
X	schar mal = ptr->maligntyp, ual = u.ualigntyp;
X
X	if (always_peaceful(ptr)) return TRUE;
X	if (always_hostile(ptr)) return FALSE;
X
X	/* the monster is hostile if its alignment is different from the
X	 * player's */
X	if (sgn(mal) != sgn(ual)) return FALSE;
X
X	/* Negative monster hostile to player with Amulet. */
X	if (mal < 0 && u.uhave_amulet) return FALSE;
X
X	/* Last case:  a chance of a co-aligned monster being
X	 * hostile.  This chance is greater if the player has strayed
X	 * (u.ualign negative) or the monster is not strongly aligned.
X	 */
X	return !!rn2(16 + (u.ualign < -15 ? -15 : u.ualign)) &&
X		!!rn2(2 + abs(mal));
X}
X
X/* Set malign to have the proper effect on player alignment if monster is
X * killed.  Negative numbers mean it's bad to kill this monster; positive
X * numbers mean it's good.  Since there are more hostile monsters than
X * peaceful monsters, the penalty for killing a peaceful monster should be
X * greater than the bonus for killing a hostile monster to maintain balance.
X * Rules:
X *   it's bad to kill peaceful monsters, potentially worse to kill always-
X *	peaceful monsters
X *   it's never bad to kill a hostile monster, although it may not be good
X */
Xvoid
Xset_malign(mtmp)
Xstruct monst *mtmp;
X{
X	schar mal = mtmp->data->maligntyp;
X	boolean coaligned = (sgn(mal) == sgn(u.ualigntyp));
X
X	if (always_peaceful(mtmp->data))
X		mtmp->malign = -3*max(5,abs(mal));
X	else if (always_hostile(mtmp->data)) {
X		if (coaligned)
X			mtmp->malign = 0;
X		else
X			mtmp->malign = max(5,abs(mal));
X	} else if (coaligned) {
X		if (mtmp->mpeaceful)
X			mtmp->malign = -3*max(3,abs(mal));
X		else	/* renegade */
X			mtmp->malign = max(3,abs(mal));
X	} else	/* not coaligned and therefore hostile */
X		mtmp->malign = abs(mal);
X}
X
X#endif /* OVL1 */
X#ifdef OVLB
X
Xstatic char NEARDATA syms[] = { 0, 1, RING_SYM, WAND_SYM, WEAPON_SYM, FOOD_SYM, GOLD_SYM,
X	SCROLL_SYM, POTION_SYM, ARMOR_SYM, AMULET_SYM, TOOL_SYM, ROCK_SYM,
X	GEM_SYM,
X#ifdef SPELLS
X	SPBOOK_SYM,
X#endif
X	S_MIMIC_DEF, S_MIMIC_DEF, S_MIMIC_DEF,
X};
X
Xvoid
Xset_mimic_sym(mtmp)		/* KAA, modified by ERS */
Xregister struct monst *mtmp;
X{
X	int roomno, rt;
X	unsigned appear, ap_type;
X	int s_sym;
X	struct obj *otmp;
X	int mx, my;
X
X	if (!mtmp) return;
X	mx = mtmp->mx; my = mtmp->my;
X	mtmp->mimic = 1;
X	roomno = inroom(mx, my);
X	if (levl[mx][my].gmask) {
X		ap_type = M_AP_GOLD;
X		if (g_at(mx, my)->amount <= 32767)
X			appear = g_at(mx, my)->amount;
X		else
X			appear = 32000 + rnd(767);
X	}
X	else if (OBJ_AT(mx, my)) {
X		ap_type = M_AP_OBJECT;
X		appear = level.objects[mx][my]->otyp;
X	}
X	else if (IS_DOOR(levl[mx][my].typ) ||
X		 IS_WALL(levl[mx][my].typ) ||
X		 levl[mx][my].typ == SDOOR ||
X		 levl[mx][my].typ == SCORR) {
X		ap_type = M_AP_FURNITURE;
X		appear = S_cdoor;
X	}
X	else if (is_maze_lev && rn2(2)) {
X		ap_type = M_AP_OBJECT;
X		appear = STATUE;
X	}
X	else if (roomno < 0) {
X		ap_type = M_AP_OBJECT;
X		appear = BOULDER;
X	}
X	else if ((rt = rooms[roomno].rtype) == ZOO || rt == VAULT) {
X		ap_type = M_AP_GOLD;
X		appear = rn2(100)+10;	/* number of gold pieces in pile */
X	}
X#ifdef ORACLE
X	else if (rt == DELPHI) {
X		if (rn2(2)) {
X			ap_type = M_AP_OBJECT;
X			appear = STATUE;
X		}
X		else {
X			ap_type = M_AP_FURNITURE;
X			appear = S_fountain;
X		}
X	}
X#endif
X#ifdef ALTARS
X	else if (rt == TEMPLE) {
X		ap_type = M_AP_FURNITURE;
X		appear = S_altar;
X	}
X#endif
X	/* We won't bother with beehives, morgues, barracks, throne rooms
X	 * since they shouldn't contain too many mimics anyway...
X	 */
X	else if (rt >= SHOPBASE) {
X		s_sym = get_shop_item(rt - SHOPBASE);
X		if (s_sym < 0) {
X			ap_type = M_AP_OBJECT;
X			appear = -s_sym;
X		}
X		else {
X			if (s_sym == RANDOM_SYM)
X				s_sym = syms[rn2(sizeof(syms)-2) + 2];
X			goto assign_sym;
X		}
X	}
X	else {
X		s_sym = syms[rn2(sizeof syms)];
Xassign_sym:
X		if (s_sym < 2) {
X			ap_type = M_AP_FURNITURE;
X			appear = s_sym ? S_upstair : S_dnstair;
X		}
X		else if (s_sym == GOLD_SYM) {
X			ap_type = M_AP_GOLD;
X			appear = rn2(100)+100;
X		}
X		else {
X			ap_type = M_AP_OBJECT;
X			if (s_sym == S_MIMIC_DEF)
X				appear = STRANGE_OBJECT;
X			else {
X				otmp = mkobj( (char) s_sym, FALSE );
X				appear = otmp->otyp;
X				free((genericptr_t) otmp);
X			}
X		}
X	}
X	mtmp->m_ap_type = ap_type;
X	mtmp->mappearance = appear;
X}
X
X#endif /* OVLB */
END_OF_FILE
if test 31716 -ne `wc -c <'src/makemon.c'`; then
    echo shar: \"'src/makemon.c'\" unpacked with wrong size!
fi
# end of 'src/makemon.c'
fi
if test ! -d 'vms' ; then
    echo shar: Creating directory \"'vms'\"
    mkdir 'vms'
fi
echo shar: End of archive 1 \(of 56\).
cp /dev/null ark1isdone
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 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 56 archives.
    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