home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 January
/
usenetsourcesnewsgroupsinfomagicjanuary1994.iso
/
sources
/
games
/
volume16
/
nethack31
/
part31
< prev
next >
Wrap
Internet Message Format
|
1993-02-01
|
58KB
Path: uunet!news.tek.com!master!saab!billr
From: billr@saab.CNA.TEK.COM (Bill Randle)
Newsgroups: comp.sources.games
Subject: v16i031: nethack31 - display oriented dungeons & dragons (Ver. 3.1), Part31/108
Message-ID: <4319@master.CNA.TEK.COM>
Date: 29 Jan 93 20:46:17 GMT
Sender: news@master.CNA.TEK.COM
Lines: 1960
Approved: billr@saab.CNA.TEK.COM
Xref: uunet comp.sources.games:1588
Submitted-by: izchak@linc.cis.upenn.edu (Izchak Miller)
Posting-number: Volume 16, Issue 31
Archive-name: nethack31/Part31
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 31 (of 108)."
# Contents: dat/Elf.des src/makemon.c
# Wrapped by billr@saab on Wed Jan 27 16:08:58 1993
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'dat/Elf.des' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'dat/Elf.des'\"
else
echo shar: Extracting \"'dat/Elf.des'\" \(12738 characters\)
sed "s/^X//" >'dat/Elf.des' <<'END_OF_FILE'
X# SCCS Id: @(#)Elf.des 3.1 91/12/24
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, Earendil/Elwing
X# and receive your quest assignment.
X#
XMAZE: "E-start",' '
XFLAGS: noteleport,hardfloor
XGEOMETRY:center,center
XMAP
X.................................... . .....................................
X................................... ... ....................................
X.................................... . .....................................
X................................... ... ....................................
X.................................... . .....................................
X..............................}}}}}}}.}}}}}}}...............................
X............................}}}|----...----|}}}.............................
X...........................}}|--...........--|}}............................
X.................... . . . }|-...............-|} . . . .....................
X................... . . . .}|.................|}. . . . ....................
X............................................................................
X................... . . . .}|.................|}. . . . ....................
X.................... . . . }|-...............-|} . . . .....................
X...........................}}|--...........--|}}............................
X............................}}}|----...----|}}}.............................
X..............................}}}}}}}.}}}}}}}...............................
X.................................... . .....................................
X................................... ... ....................................
X.................................... . .....................................
X................................... ... ....................................
XENDMAP
X# Random Monsters
XRANDOM_MONSTERS: 'o', 'O'
X# Dungeon Description
XREGION:(00,00,75,19),lit,"ordinary"
X# Stairs
XSTAIR:(40,13),down
X# Portal arrival point
XBRANCH:(00,14,00,14),(0,0,0,0)
X# Altar
XALTAR:(37,10),chaos,altar
X# Earendil/Elwing
XMONSTER:'@',"Earendil",(37,10)
X# The treasure of Earendil/Elwing
XOBJECT:'(',"chest",(37,10)
X# elf guards for the audience chamber
XMONSTER:'@',"High-elf",(38,09)
XMONSTER:'@',"High-elf",(38,10)
XMONSTER:'@',"High-elf",(38,11)
XMONSTER:'@',"High-elf",(36,09)
XMONSTER:'@',"High-elf",(36,10)
XMONSTER:'@',"High-elf",(36,11)
XMONSTER:'@',"High-elf",(37,09)
XMONSTER:'@',"High-elf",(37,11)
X# Non diggable walls
XNON_DIGGABLE:(00,00,75,19)
X# traps
X# One pit at each cardinal point.
XTRAP:"pit",(37,05)
XTRAP:"pit",(46,10)
XTRAP:"pit",(37,15)
XTRAP:"pit",(28,10)
XTRAP:random,random
XTRAP:random,random
X# Monsters on siege duty.
XMONSTER: 'o',"Uruk-hai",(35,04),hostile
XMONSTER: 'o',"Uruk-hai",(36,03),hostile
XMONSTER: 'o',"goblin",(37,03),hostile
XMONSTER: 'o',"goblin",(38,03),hostile
XMONSTER: 'o',"goblin",(39,04),hostile
XMONSTER: 'o',"Uruk-hai",(48,09),hostile
XMONSTER: 'o',"goblin",(48,10),hostile
XMONSTER: 'o',"goblin",(48,11),hostile
XMONSTER: 'o',"Uruk-hai",(35,16),hostile
XMONSTER: 'o',"Uruk-hai",(36,17),hostile
XMONSTER: 'o',"goblin",(37,17),hostile
XMONSTER: 'o',"goblin",(38,17),hostile
XMONSTER: 'o',"goblin",(39,16),hostile
XMONSTER: 'o',"Uruk-hai",(26,09),hostile
XMONSTER: 'o',"goblin",(26,10),hostile
XMONSTER: 'o',"goblin",(26,11),hostile
X
X#
X# The "locate" level for the quest.
X#
X# Here you have to infiltrate the Goblins' Cave to go
X# further towards your assigned quest.
X#
X
XMAZE: "E-locate",' '
XFLAGS: hardfloor
XGEOMETRY:center,center
XMAP
X
X .. .... ...... ... ....... ..
X .. ......S... .......... ..... ........ ....
X .. .. ... . ......... .. . ..... ....
X .. .. . ..... .. . .. .....
X .... . .. .. S .. ..
X .... S .. .. .... .. ..
X ..... ... .. .. ........ .. ..
X ...... ...... ... .. ............ ... ...
X .... .. .... .... ........................S....S......
X .. .. .. ... ........................ ..
X .. .. .. ........................ ..
X .... .... .. ........................ ..
X ...... .. .. ... .................... ..
X .... .... .. ..... ............ ..
X .. .. .. .. ... .S ............ .... ...
X .. .. .............. .... ............ .... .. .....
X ... .. .. .... ..... .. ....
X .............. ...... .....
X
XENDMAP
X# Random Monsters
XRANDOM_MONSTERS: 'o', 'O'
X# Dungeon Description
XREGION:(00,00,75,19),unlit,"ordinary"
X# Doors
XDOOR:closed,(15,02)
XDOOR:closed,(18,06)
XDOOR:closed,(35,15)
XDOOR:closed,(45,05)
XDOOR:closed,(59,09)
XDOOR:closed,(64,09)
X# Stairs
XSTAIR:(01,01),up
XSTAIR:(45,01),down
X# Non diggable walls
XNON_DIGGABLE:(00,00,75,19)
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:"pit",(13,10)
XTRAP:"spiked pit",(45,03)
XTRAP:"board",(41,16)
XTRAP:"magic",(60,09)
XTRAP:random,random
XTRAP:random,random
X# Random monsters.
XMONSTER:'o',"Uruk-hai",(40,10),hostile
XMONSTER:'o',"Uruk-hai",(41,10),hostile
XMONSTER:'o',"Uruk-hai",(42,10),hostile
XMONSTER:'o',"Uruk-hai",(43,10),hostile
XMONSTER:'o',"goblin",(44,10),hostile
XMONSTER:'o',"goblin",(45,10),hostile
XMONSTER:'o',"goblin",(40,11),hostile
XMONSTER:'o',"goblin",(41,11),hostile
XMONSTER:'o',"goblin",(42,11),hostile
XMONSTER:'o',"goblin",(43,11),hostile
XMONSTER:'o',"goblin",(44,11),hostile
XMONSTER:'o',"goblin",(45,11),hostile
XMONSTER:'o',"goblin",(41,12),hostile
XMONSTER:'o',"goblin",(42,12),hostile
XMONSTER:'o',"goblin",(43,12),hostile
XMONSTER:'o',"goblin",(44,12),hostile
XMONSTER:'o',"goblin",random,hostile
XMONSTER:'o',random,random,hostile
XMONSTER:'O',random,random,hostile
XMONSTER:'O',"ogre",(42,13),hostile
XMONSTER:'O',"ogre",(43,13),hostile
XMONSTER:'O',"ogre",(44,13),hostile
XMONSTER:'O',"ogre",random,hostile
X
XWALLIFY
X
X#
X# The "goal" level for the quest.
X#
X# Here you meet The Goblin King your nemesis monster. You have to
X# defeat The Goblin King in combat to gain the artifact you have
X# been assigned to retrieve.
X#
X
XMAZE: "E-goal", ' '
XGEOMETRY:center,center
XMAP
X
X ... ...
X ..........................................................................
X ... + ...
X . ............ ....... . ....... .
X . ............................. . ........ .........S.. .
X . ............ . ...... . . . ....... .. .
X . ......... . .... + . ... . .. .
X . S . ......... .S. .S............... .
X . ... . ... . ......... . .
X . ........ .....S.+.......+....\....+........+. .
X . ... ... S ......... .. ..... .
X . .. ......... .. ...... .
X . ....... ... + .... .... .......... .
X . .............. .. . ...... .. ............. .
X . ............. . .......... ...... .
X ... + ...
X ..........................................................................
X ... ...
X
XENDMAP
X# Random Monsters
XRANDOM_MONSTERS: 'o', 'O'
X# Dungeon Description
XREGION:(00,00,75,19),lit,"ordinary"
X# Stairs
XSTAIR:(19,10),up
X# Non diggable walls
XNON_DIGGABLE:(00,00,75,19)
X# Objects
XOBJECT:'(',"crystal ball",(37,10),blessed,0,"The Palantir of Westernesse"
XOBJECT:'(',"chest",(37,10)
XOBJECT:random,random,(36,09)
XOBJECT:random,random,(36,10)
XOBJECT:random,random,(36,11)
XOBJECT:random,random,(37,09)
XOBJECT:random,random,(37,11)
XOBJECT:random,random,(38,09)
XOBJECT:random,random,(38,10)
XOBJECT:random,random,(38,11)
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# doors
XDOOR:locked,(12,08)
XDOOR:closed,(22,10)
XDOOR:locked,(24,10)
XDOOR:closed,(25,11)
XDOOR:closed,(32,10)
XDOOR:closed,(37,03)
XDOOR:closed,(37,07)
XDOOR:closed,(37,13)
XDOOR:closed,(37,16)
XDOOR:closed,(42,10)
XDOOR:locked,(46,08)
XDOOR:closed,(51,10)
XDOOR:locked,(53,08)
XDOOR:closed,(65,05)
X# Random monsters.
XMONSTER:'o',"Goblin King",(37,10),hostile
XMONSTER:'o',"Uruk-hai",(36,09),hostile
XMONSTER:'o',"Uruk-hai",(36,10),hostile
XMONSTER:'o',"Uruk-hai",(36,11),hostile
XMONSTER:'o',"Uruk-hai",(37,09),hostile
XMONSTER:'o',"Uruk-hai",(37,11),hostile
XMONSTER:'o',"Uruk-hai",(38,09),hostile
XMONSTER:'o',"goblin",(38,10),hostile
XMONSTER:'o',"goblin",(38,11),hostile
XMONSTER:'o',"goblin",(02,02),hostile
XMONSTER:'o',"goblin",(71,02),hostile
XMONSTER:'o',"goblin",(02,16),hostile
XMONSTER:'o',"goblin",(71,16),hostile
XMONSTER:'o',"Uruk-hai",random,hostile
XMONSTER:'o',"Uruk-hai",random,hostile
XMONSTER:'o',"goblin",random,hostile
XMONSTER:'o',"goblin",random,hostile
XMONSTER:'o',random,random,hostile
XMONSTER:'o',random,random,hostile
XMONSTER:'O',"ogre",(03,02),hostile
XMONSTER:'O',"ogre",(72,02),hostile
XMONSTER:'O',"ogre",(03,17),hostile
XMONSTER:'O',"ogre",(72,17),hostile
XMONSTER:'O',"ogre",(41,10),hostile
XMONSTER:'O',"ogre",(33,09),hostile
XMONSTER:'O',"ogre",random,hostile
XMONSTER:'O',"ogre",random,hostile
XMONSTER:'O',random,random,hostile
X
XWALLIFY
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: "E-filla" , ' '
XINIT_MAP: '.' , ' ', true, true, random, true
XNOMAP
X# Random Monsters
XRANDOM_MONSTERS: 'o', 'O'
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
X#
XTRAP: random, random
XTRAP: random, random
XTRAP: random, random
XTRAP: random, random
X#
XMONSTER: 'o', "goblin", random, hostile
XMONSTER: 'o', "goblin", random, hostile
XMONSTER: 'o', "goblin", random, hostile
XMONSTER: 'o', "goblin", random, hostile
XMONSTER: 'o', "Uruk-hai", random, hostile
XMONSTER: 'o', random, random, hostile
XMONSTER: 'O', "ogre", random, hostile
X
XMAZE: "E-fillb" , ' '
XINIT_MAP: '.' , ' ', true, true, random, true
XNOMAP
X# Random Monsters
XRANDOM_MONSTERS: 'o', 'O'
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#
XTRAP: random, random
XTRAP: random, random
XTRAP: random, random
XTRAP: random, random
X#
XMONSTER: 'o', "goblin", random, hostile
XMONSTER: 'o', "Uruk-hai", random, hostile
XMONSTER: 'o', "Uruk-hai", random, hostile
XMONSTER: 'o', "Uruk-hai", random, hostile
XMONSTER: 'o', random, random, hostile
XMONSTER: 'O', "ogre", random, hostile
XMONSTER: 'O', "ogre", random, hostile
END_OF_FILE
if test 12738 -ne `wc -c <'dat/Elf.des'`; then
echo shar: \"'dat/Elf.des'\" unpacked with wrong size!
fi
# end of 'dat/Elf.des'
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'\" \(40817 characters\)
sed "s/^X//" >'src/makemon.c' <<'END_OF_FILE'
X/* SCCS Id: @(#)makemon.c 3.1 92/11/01 */
X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
X/* NetHack may be freely redistributed. See license for details. */
X
X#include "hack.h"
X#include "epri.h"
X#include "emin.h"
X#ifdef REINCARNATION
X# include <ctype.h>
X#endif
X
XSTATIC_VAR struct monst NEARDATA zeromonst;
X
X#define uncommon(ptr) \
X (((ptr)->geno & (G_GENOD | G_EXTINCT | G_NOGEN | G_UNIQ)) || \
X (!Inhell ? ((ptr)->geno & G_HELL) : ((ptr)->maligntyp > A_NEUTRAL)))
X
X#ifdef OVL0
Xstatic boolean NDECL(cmavail);
Xstatic int FDECL(align_shift, (struct permonst *));
X#endif /* OVL0 */
XSTATIC_DCL boolean FDECL(is_home_elemental,(struct permonst *));
XSTATIC_DCL boolean FDECL(wrong_elem_type, (struct permonst *));
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 *));
X#ifdef OVL1
Xstatic void FDECL(m_initinv,(struct monst *));
X#endif /* OVL1 */
X
Xextern int monstr[];
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
XSTATIC_OVL boolean
Xis_home_elemental(ptr)
Xregister struct permonst *ptr;
X{
X if (ptr->mlet != S_ELEMENTAL) return FALSE;
X if (!In_endgame(&u.uz)) return FALSE;
X switch(monsndx(ptr)) {
X case PM_AIR_ELEMENTAL: return Is_airlevel(&u.uz);
X case PM_FIRE_ELEMENTAL: return Is_firelevel(&u.uz);
X case PM_EARTH_ELEMENTAL: return Is_earthlevel(&u.uz);
X case PM_WATER_ELEMENTAL: return Is_waterlevel(&u.uz);
X }
X return FALSE; /* shouldn't be reached */
X}
X
X/*
X * Return true if the given monster cannot exist on this elemental level.
X */
XSTATIC_OVL boolean
Xwrong_elem_type(ptr)
X register struct permonst *ptr;
X{
X if (Is_earthlevel(&u.uz)) {
X /* no restrictions? */
X } else if (Is_waterlevel(&u.uz)) {
X /* just monsters that can swim */
X if(!is_swimmer(ptr)) return TRUE;
X } else if (Is_firelevel(&u.uz)) {
X if(!resists_fire(ptr)) return TRUE;
X } else if (Is_airlevel(&u.uz)) {
X if(!(is_flyer(ptr) && ptr->mlet != S_TRAPPER) && !is_floater(ptr)
X && !amorphous(ptr) && !noncorporeal(ptr) && !is_whirly(ptr))
X return TRUE;
X }
X return FALSE;
X}
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 = FALSE;
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, TRUE, FALSE);
X otmp->quan = (long) rn1(oquan, 3);
X otmp->owt = weight(otmp);
X if (otyp == ORCISH_ARROW) otmp->opoisoned = TRUE;
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 (Is_rogue_level(&u.uz)) 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 int w1 = 0, w2 = 0;
X switch (mm) {
X
X case PM_WATCHMAN:
X#ifdef ARMY
X case PM_SOLDIER:
X#endif
X if (!rn2(3)) {
X w1 = rn1(BEC_DE_CORBIN - PARTISAN + 1, PARTISAN);
X w2 = rn2(2) ? DAGGER : KNIFE;
X } else w1 = rn2(2) ? SPEAR : SHORT_SWORD;
X break;
X#ifdef ARMY
X case PM_SERGEANT:
X w1 = rn2(2) ? FLAIL : MACE;
X break;
X case PM_LIEUTENANT:
X w1 = rn2(2) ? BROADSWORD : LONG_SWORD;
X break;
X case PM_CAPTAIN:
X#endif
X case PM_WATCH_CAPTAIN:
X w1 = rn2(2) ? LONG_SWORD : SILVER_SABER;
X break;
X default:
X if (!rn2(4)) w1 = DAGGER;
X if (!rn2(7)) w2 = SPEAR;
X break;
X }
X if (w1) (void)mongets(mtmp, w1);
X if (!w2 && w1 != DAGGER && !rn2(4)) w2 = KNIFE;
X if (w2) (void)mongets(mtmp, w2);
X } else if (is_elf(ptr)) {
X if (rn2(2))
X (void) mongets(mtmp,
X rn2(2) ? ELVEN_MITHRIL_COAT : ELVEN_CLOAK);
X if (rn2(2)) (void)mongets(mtmp, ELVEN_LEATHER_HELM);
X else if (!rn2(4)) (void)mongets(mtmp, ELVEN_BOOTS);
X if (rn2(2)) (void)mongets(mtmp, ELVEN_DAGGER);
X switch (rn2(3)) {
X case 0:
X if (!rn2(4)) (void)mongets(mtmp, ELVEN_SHIELD);
X if (rn2(3)) (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 if (rn2(2)) {
X (void)mongets(mtmp, ELVEN_SPEAR);
X (void)mongets(mtmp, ELVEN_SHIELD);
X }
X break;
X }
X if(mtmp->data == &mons[PM_ELVENKING])
X (void)mongets(mtmp, PICK_AXE);
X }
X break;
X
X case S_ANGEL:
X {
X int spe2;
X /* create minion stuff; can't use mongets */
X struct obj *otmp = mksobj(LONG_SWORD, FALSE, FALSE);
X
X /* maybe make it special */
X if(!rn2(20) || is_lord(mtmp->data))
X otmp = oname(otmp, artiname(
X rn2(2) ? ART_DEMONBANE : ART_SUNSWORD), 0);
X bless(otmp);
X otmp->oerodeproof = TRUE;
X spe2 = rn2(4);
X otmp->spe = max(otmp->spe, spe2);
X mpickobj(mtmp, otmp);
X
X otmp = mksobj(!rn2(4) || is_lord(mtmp->data) ?
X SHIELD_OF_REFLECTION : LARGE_SHIELD,
X FALSE, FALSE);
X otmp->cursed = FALSE;
X otmp->oerodeproof = TRUE;
X otmp->spe = 0;
X mpickobj(mtmp, otmp);
X }
X break;
X
X case S_HUMANOID:
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 if (!rn2(10)) (void)mongets(mtmp, DWARVISH_CLOAK);
X } else if (is_dwarf(ptr)) {
X if (rn2(7)) (void)mongets(mtmp, DWARVISH_CLOAK);
X if (rn2(7)) (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, !rn2(3) ? PICK_AXE : DAGGER);
X }
X }
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 switch (mm != PM_ORC_CAPTAIN ? mm :
X rn2(2) ? PM_MORDOR_ORC : PM_URUK_HAI) {
X case PM_MORDOR_ORC:
X if(!rn2(3)) (void)mongets(mtmp, SCIMITAR);
X if(!rn2(3)) (void)mongets(mtmp, ORCISH_SHIELD);
X if(!rn2(3)) (void)mongets(mtmp, KNIFE);
X if(!rn2(3)) (void)mongets(mtmp, ORCISH_CHAIN_MAIL);
X break;
X case PM_URUK_HAI:
X if(!rn2(3)) (void)mongets(mtmp, ORCISH_CLOAK);
X if(!rn2(3)) (void)mongets(mtmp, ORCISH_SHORT_SWORD);
X if(!rn2(3)) (void)mongets(mtmp, IRON_SHOES);
X if(!rn2(3)) {
X (void)mongets(mtmp, ORCISH_BOW);
X m_initthrow(mtmp, ORCISH_ARROW, 12);
X }
X if(!rn2(3)) (void)mongets(mtmp, URUK_HAI_SHIELD);
X break;
X default:
X if (mm != PM_ORC_SHAMAN && rn2(2))
X (void)mongets(mtmp, (mm == PM_GOBLIN || rn2(2) == 0)
X ? ORCISH_DAGGER : SCIMITAR);
X }
X break;
X case S_OGRE:
X if (!rn2(mm == PM_OGRE_KING ? 3 : mm == PM_OGRE_LORD ? 6 : 12))
X (void) mongets(mtmp, BATTLE_AXE);
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 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 /* 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#ifdef MUSE
X if ((int) mtmp->m_lev > rn2(70))
X (void) mongets(mtmp, rnd_offensive_item(mtmp));
X#endif
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 (Is_rogue_level(&u.uz)) 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(ptr->mlet) {
X
X case S_HUMAN:
X if(is_mercenary(ptr)) {
X register int mac;
X#ifdef MUSE
X switch(monsndx(ptr)) {
X case PM_GUARD: mac = -1; break;
X# ifdef ARMY
X case PM_SOLDIER: mac = 3; break;
X case PM_SERGEANT: mac = 0; break;
X case PM_LIEUTENANT: mac = -2; break;
X case PM_CAPTAIN: mac = -3; break;
X# endif
X case PM_WATCHMAN: mac = 3; break;
X case PM_WATCH_CAPTAIN: mac = -2; break;
X default: impossible("odd mercenary %d?", monsndx(ptr));
X mac = 0;
X break;
X }
X#else
X mac = ptr->ac;
X#endif
X
X if (mac < -1 && rn2(5))
X mac += 7 + mongets(mtmp, (rn2(5)) ?
X PLATE_MAIL : CRYSTAL_PLATE_MAIL);
X else if (mac < 3 && rn2(5))
X mac += 6 + mongets(mtmp, (rn2(3)) ?
X SPLINT_MAIL : BANDED_MAIL);
X else if (rn2(5))
X mac += 3 + mongets(mtmp, (rn2(3)) ?
X RING_MAIL : STUDDED_LEATHER_ARMOR);
X else
X mac += 2 + mongets(mtmp, LEATHER_ARMOR);
X
X if (mac < 10 && rn2(3))
X mac += 1 + mongets(mtmp, HELMET);
X else if (mac < 10 && rn2(2))
X mac += 1 + mongets(mtmp, DENTED_POT);
X if (mac < 10 && rn2(3))
X mac += 1 + mongets(mtmp, SMALL_SHIELD);
X else if (mac < 10 && rn2(2))
X mac += 2 + mongets(mtmp, LARGE_SHIELD);
X if (mac < 10 && rn2(3))
X mac += 1 + mongets(mtmp, LOW_BOOTS);
X else if (mac < 10 && rn2(2))
X mac += 2 + mongets(mtmp, HIGH_BOOTS);
X if (mac < 10 && rn2(3))
X mac += 1 + mongets(mtmp, LEATHER_GLOVES);
X else if (mac < 10 && rn2(2))
X mac += 1 + mongets(mtmp, ELVEN_CLOAK);
X
X#ifndef MUSE
X if (mac != 10 && rn2(5)) { /* make up the difference */
X otmp = mksobj(RIN_PROTECTION, FALSE, FALSE);
X otmp->spe = (10 - mac + rn2(3) - rn2(3));
X if(otmp->spe < 0) curse(otmp);
X mpickobj(mtmp, otmp);
X }
X#endif
X#ifdef ARMY
X if(ptr != &mons[PM_GUARD] &&
X ptr != &mons[PM_WATCHMAN] &&
X ptr != &mons[PM_WATCH_CAPTAIN]) {
X if (!rn2(3)) (void) mongets(mtmp, K_RATION);
X if (!rn2(2)) (void) mongets(mtmp, C_RATION);
X# ifdef MUSE
X if (ptr != &mons[PM_SOLDIER] && !rn2(3))
X (void) mongets(mtmp, BUGLE);
X# endif
X } else
X#endif
X if (ptr == &mons[PM_WATCHMAN] && rn2(3))
X (void) mongets(mtmp, TIN_WHISTLE);
X } else if (ptr == &mons[PM_SHOPKEEPER]) {
X (void) mongets(mtmp,SKELETON_KEY);
X }
X break;
X
X case S_NYMPH:
X if(!rn2(2)) (void) mongets(mtmp, MIRROR);
X if(!rn2(2)) (void) mongets(mtmp, POT_OBJECT_DETECTION);
X break;
X
X case S_GIANT:
X if (ptr == &mons[PM_MINOTAUR])
X (void) mongets(mtmp, WAN_DIGGING);
X else if (is_giant(ptr)) {
X for(cnt = rn2((int)(mtmp->m_lev / 2)); cnt; cnt--) {
X otmp = mksobj(rnd_class(DILITHIUM_CRYSTAL,LUCKSTONE-1),FALSE,FALSE);
X otmp->quan = (long) rn1(2, 3);
X otmp->owt = weight(otmp);
X mpickobj(mtmp, otmp);
X }
X }
X break;
X case S_WRAITH:
X if (ptr == &mons[PM_NAZGUL]) {
X otmp = mksobj(RIN_INVISIBILITY, FALSE, FALSE);
X curse(otmp);
X mpickobj(mtmp, otmp);
X }
X break;
X case S_QUANTMECH:
X if (!rn2(20)) {
X struct obj *cat;
X
X otmp = mksobj(LARGE_BOX, FALSE, FALSE);
X /* actually, whether this is a corpse or a live cat shouldn't
X really be decided until the box is opened... */
X cat = mksobj(CORPSE, FALSE, FALSE);
X cat->corpsenm = PM_HOUSECAT;
X cat->owt = weight(cat);
X cat = oname(cat, "Schroedinger's Cat", FALSE);
X cat->nobj = otmp->cobj;
X otmp->cobj = cat;
X otmp->owt = weight(otmp);
X mpickobj(mtmp, otmp);
X }
X break;
X case S_LEPRECHAUN:
X mtmp->mgold = (long) d(level_difficulty(), 30);
X break;
X default:
X break;
X }
X
X#ifdef ARMY /* ordinary soldiers rarely have access to magic (or gold :-) */
X if (ptr == &mons[PM_SOLDIER] && rn2(13)) return;
X#endif
X#ifdef MUSE
X if ((int) mtmp->m_lev > rn2(30))
X (void) mongets(mtmp, rnd_defensive_item(mtmp));
X if ((int) mtmp->m_lev > rn2(100))
X (void) mongets(mtmp, rnd_misc_item(mtmp));
X#endif
X if (likes_gold(ptr) && !mtmp->mgold && !rn2(5))
X mtmp->mgold =
X (long) d(level_difficulty(), mtmp->minvent ? 5 : 10);
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 tryct = 0; /* careful with bigrooms */
X do {
X x = rn1(COLNO-3,2);
X y = rn2(ROWNO);
X } while(!goodpos(x, y, (struct monst *)0, ptr) ||
X (!in_mklev && tryct++ < 50 && cansee(x, y)));
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 that can survive here.
X * (the special levels ask for random monsters at specific
X * positions, causing mass drowning on the medusa level,
X * for instance.)
X */
X int tryct = 0; /* maybe there are no good choices */
X do {
X if(!(ptr = rndmonst())) {
X#ifdef DEBUG
X pline("Warning: no monster.");
X#endif
X return((struct monst *) 0); /* no more monsters! */
X }
X } while(!goodpos(x, y, (struct monst *)0, ptr) && tryct++ < 50);
X }
X /* if it's unique, don't ever make it again */
X if (ptr->geno & G_UNIQ) ptr->geno |= G_EXTINCT;
X
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 if (is_golem(ptr))
X mtmp->mhpmax = mtmp->mhp = golemhp(monsndx(ptr));
X else if (is_rider(ptr)) {
X /* We want low HP, but a high mlevel so they can attack well */
X mtmp->mhpmax = mtmp->mhp = d(10,8);
X } else 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 = mtmp->m_lev*8;
X else if(!mtmp->m_lev) mtmp->mhpmax = mtmp->mhp = rnd(4);
X else if(is_home_elemental(ptr))
X mtmp->mhpmax = mtmp->mhp = 3 * d((int)mtmp->m_lev, 8);
X else mtmp->mhpmax = mtmp->mhp = d((int)mtmp->m_lev, 8);
X
X if (is_female(ptr)) mtmp->female = TRUE;
X else if (is_male(ptr)) mtmp->female = FALSE;
X else mtmp->female = rn2(2); /* ignored for neuters */
X
X place_monster(mtmp, x, y);
X mtmp->mcansee = mtmp->mcanmove = TRUE;
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 if(in_mklev)
X if(x && y)
X (void) mkobj_at(0, x, y, TRUE);
X if(hides_under(ptr) && OBJ_AT(x, y))
X mtmp->mundetected = TRUE;
X break;
X case S_STALKER:
X case S_EEL:
X mtmp->minvis = TRUE;
X break;
X case S_LEPRECHAUN:
X mtmp->msleep = TRUE;
X break;
X case S_JABBERWOCK:
X case S_NYMPH:
X if(rn2(5) && !u.uhave.amulet) mtmp->msleep = TRUE;
X break;
X case S_ORC:
X if(pl_character[0] == 'E') mtmp->mpeaceful = FALSE;
X break;
X case S_UNICORN:
X if (sgn(u.ualign.type) == sgn(ptr->maligntyp))
X mtmp->mpeaceful = TRUE;
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 = FALSE;
X else {
X mtmp->cham = TRUE;
X (void) newcham(mtmp, rndmonst());
X }
X } else if (ptr == &mons[PM_WIZARD_OF_YENDOR]) {
X mtmp->iswiz = TRUE;
X flags.no_of_wizards++;
X } else if (ptr == &mons[PM_VLAD_THE_IMPALER])
X (void) mongets(mtmp, CANDELABRUM_OF_INVOCATION);
X#ifdef MULDGN
X else if (ptr->msound == MS_NEMESIS)
X (void) mongets(mtmp, BELL_OF_OPENING);
X#else
X else if (ptr == &mons[PM_MEDUSA])
X (void) mongets(mtmp, BELL_OF_OPENING);
X#endif
X
X if(in_mklev) {
X if(((is_ndemon(ptr)) ||
X (ptr == &mons[PM_WUMPUS]) ||
X (ptr == &mons[PM_LONG_WORM]) ||
X (ptr == &mons[PM_GIANT_EEL])) && !u.uhave.amulet && rn2(5))
X mtmp->msleep = TRUE;
X } else {
X if(byyou) {
X newsym(mtmp->mx,mtmp->my);
X set_apparxy(mtmp);
X }
X }
X if(is_dprince(ptr)) {
X mtmp->mpeaceful = mtmp->minvis = TRUE;
X if (uwep && uwep->oartifact == ART_EXCALIBUR)
X mtmp->mpeaceful = mtmp->mtame = FALSE;
X }
X if ( (ptr == &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)) place_worm_tail_randomly(mtmp, x, y);
X }
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 / armor */
X m_initinv(mtmp); /* add on a few special items incl. more armor */
X#ifdef MUSE
X m_dowear(mtmp, TRUE);
X#endif
X
X if (!in_mklev)
X newsym(mtmp->mx,mtmp->my); /* make sure the mon shows up */
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(1, xx-range);
X xmax = min(COLNO-1, xx+range);
X ymin = max(0, yy-range);
X ymax = min(ROWNO-1, yy+range);
X
X for(x = xmin; x <= xmax; x++)
X if(goodpos(x, ymin, (struct monst *)0, mdat)) {
X tfoo->x = x;
X#ifdef MAC_MPW32
X ( tfoo ) -> y = ymin ;
X tfoo ++ ;
X#else
X (tfoo++)->y = ymin;
X#endif
X if(tfoo == &foo[15]) goto foofull;
X }
X for(x = xmin; x <= xmax; x++)
X if(goodpos(x, ymax, (struct monst *)0, mdat)) {
X tfoo->x = x;
X#ifdef MAC_MPW32
X ( tfoo ) -> y = ymax ;
X tfoo ++ ;
X#else
X (tfoo++)->y = ymax;
X#endif
X if(tfoo == &foo[15]) goto foofull;
X }
X for(y = ymin+1; y < ymax; y++)
X if(goodpos(xmin, y, (struct monst *)0, mdat)) {
X tfoo->x = xmin;
X#ifdef MAC_MPW32
X ( tfoo ) -> y = y ;
X tfoo ++ ;
X#else
X (tfoo++)->y = y;
X#endif
X if(tfoo == &foo[15]) goto foofull;
X }
X for(y = ymin+1; y < ymax; y++)
X if(goodpos(xmax, y, (struct monst *)0, mdat)) {
X tfoo->x = xmax;
X#ifdef MAC_MPW32
X ( tfoo ) -> y = y ;
X tfoo ++ ;
X#else
X (tfoo++)->y = y;
X#endif
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, mtmp, mdat)
Xint x,y;
Xstruct monst *mtmp; /* existing monster being moved, if any */
Xstruct permonst *mdat;
X{
X struct monst *mtmp2;
X
X if (x < 1 || x > COLNO-2 || y < 1 || y > ROWNO-2 || MON_AT(x, y))
X return 0;
X
X /* in many cases, we're trying to create a new monster, which
X * can't go on top of the player or any existing monster.
X * however, occasionally we are relocating engravings or objects,
X * which could be colocated and thus get restricted a bit too much.
X * oh well.
X */
X if (x == u.ux && y == u.uy) return 0;
X if ((mtmp2 = m_at(x, y)) && mtmp != mtmp2) return 0;
X
X if (mdat) {
X if (IS_POOL(levl[x][y].typ))
X if (mdat == &playermon &&
X (HLevitation || Wwalking || Magical_breathing))
X return 1;
X else return (is_flyer(mdat) || is_swimmer(mdat));
X if (levl[x][y].typ == LAVAPOOL)
X if (mdat == &playermon && (HLevitation))
X return 1;
X else return
X (is_flyer(mdat) || (mdat == &mons[PM_FIRE_ELEMENTAL]));
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
X/*
X * rloc_to()
X *
X * Pulls a monster from its current position and places a monster at
X * a new x and y. If oldx is 0, then the monster was not in the levels.monsters
X * array. However, if oldx is 0, oldy may still have a value because mtmp is a
X * migrating_mon. Worm tails are always placed randomly around the head of
X * the worm.
X */
X
Xvoid
Xrloc_to(mtmp, x, y)
X struct monst *mtmp;
X register int x, y;
X{
X register int oldx = mtmp->mx, oldy = mtmp->my;
X
X if(x == mtmp->mx && y == mtmp->my) /* that was easy */
X return;
X
X if (oldx) { /* "pick up" monster */
X if(mtmp->wormno)
X remove_worm(mtmp);
X else {
X remove_monster(oldx, oldy);
X newsym(oldx, oldy); /* update old location */
X }
X }
X
X place_monster(mtmp, x, y); /* put monster down */
X
X if(mtmp->wormno) /* now put down tail */
X place_worm_tail_randomly(mtmp, x, y);
X
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
X newsym(x, y); /* update new location */
X set_apparxy(mtmp); /* orient monster */
X}
X
X#endif /* OVLB */
X#ifdef OVL2
X
Xvoid
Xrloc(mtmp)
X struct monst *mtmp;
X{
X register int x = xupstair, y = yupstair, trycount;
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, y, mtmp, mtmp->data)) {
X trycount = 0;
X do {
X x = rn1(COLNO-3,2);
X y = rn2(ROWNO);
X } while(!goodpos(x,y,mtmp,mtmp->data) && ++trycount < 1000);
X /* last ditch attempt to find a good place */
X if (trycount >= 1000) {
X for (x = 2; x < COLNO - 1; x++)
X for (y = 0; y < ROWNO; y++)
X if (goodpos(x,y,mtmp,mtmp->data))
X goto found_atlast;
X /* level either full of monsters or somehow faulty */
X impossible("rloc(): couldn't relocate monster");
X return;
X }
X }
Xfound_atlast:;
X rloc_to(mtmp, x, y);
X}
X
Xvoid
Xrloc_shk(mtmp) /* to be used when teleporting a shopkeeper */
Xstruct monst *mtmp;
X{
X register int x, y, ox, oy, trycount;
X
X if(!mtmp->isshk) return;
X trycount = 0;
X do {
X x = rn1(COLNO-3,2);
X y = rn2(ROWNO);
X } while(!goodpos(x,y,mtmp,mtmp->data) && ++trycount < 1000);
X /* last ditch attempt to find a good place */
X if (trycount >= 1000) {
X for (x = 2; x < COLNO - 1; x++)
X for (y = 0; y < ROWNO; y++)
X if (goodpos(x,y,mtmp,mtmp->data))
X goto found_ok;
X /* this really shouldn't happen - after all, shopkeeper's
X original position should always be available */
X impossible("rloc_shk(): couldn't relocate shopkeeper");
X return;
X }
Xfound_ok:;
X ox = mtmp->mx;
X oy = mtmp->my;
X rloc_to(mtmp, x, y);
X make_angry_shk(mtmp, ox, oy);
X}
X
X#endif /* OVL2 */
X#ifdef OVLB
X
Xvoid
Xvloc(mtmp)
Xstruct monst *mtmp;
X{
X register struct mkroom *croom = search_special(VAULT);
X coord c;
X
X if(croom && somexy(croom, &c) && goodpos(c.x, c.y, mtmp, mtmp->data)) {
X rloc_to(mtmp, c.x, c.y);
X return;
X }
X rloc(mtmp);
X}
X
X#endif /* OVLB */
X#ifdef OVL0
X
Xstatic boolean
Xcmavail() /* return TRUE if "common" monsters can be generated */
X{
X struct permonst *ptr;
X
X for(ptr = &mons[0]; ptr != &mons[NUMMONS]; ptr++)
X if(!uncommon(ptr)) return TRUE;
X
X return FALSE;
X}
X
X/*
X * shift the probability of a monster's generation by
X * comparing the dungeon alignment and monster alignment.
X * return an integer in the range of 0-5.
X */
Xstatic int
Xalign_shift(ptr)
Xregister struct permonst *ptr;
X{
X static long NEARDATA oldmoves = 0L; /* != 1, starting value of moves */
X static s_level NEARDATA *lev;
X register int alshift;
X
X if(oldmoves != moves) {
X lev = Is_special(&u.uz);
X oldmoves = moves;
X }
X switch((lev) ? lev->flags.align : dungeons[u.uz.dnum].flags.align) {
X default: /* just in case */
X case AM_NONE: alshift = 0;
X break;
X case AM_LAWFUL: alshift = (ptr->maligntyp+20)/(2*ALIGNWEIGHT);
X break;
X case AM_NEUTRAL: alshift = (20 - abs(ptr->maligntyp))/ALIGNWEIGHT;
X break;
X case AM_CHAOTIC: alshift = (-(ptr->maligntyp-20))/(2*ALIGNWEIGHT);
X break;
X }
X return alshift;
X}
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#endif
X static boolean NEARDATA elemlevel;
X
X#ifdef MULDGN
X if(u.uz.dnum == quest_dnum && (ptr = qt_montype())) return(ptr);
X#endif
X if(oldmoves != moves) { /* must recalculate accept */
X oldmoves = moves;
X zlevel = level_difficulty();
X if(!cmavail()) {
X#ifdef DEBUG
X pline("cmavail() 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#ifdef REINCARNATION
X upper = Is_rogue_level(&u.uz);
X#endif
X elemlevel = In_endgame(&u.uz) && !Is_astralevel(&u.uz);
X/*
X * Find out how many monsters exist in the range we have selected.
X */
X accept = 0;
X for(ct = 0, ptr = &mons[0] ; ptr != &mons[NUMMONS]; ct++, ptr++) {
X if(tooweak(ct, minmlev) || toostrong(ct, maxmlev))
X continue;
X#ifdef REINCARNATION
X if(upper && !isupper(def_monsyms[ptr->mlet])) continue;
X#endif
X if(elemlevel && wrong_elem_type(ptr)) continue;
X if(uncommon(ptr)) continue;
X accept += (ptr->geno & G_FREQ);
X accept += align_shift(ptr);
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 for(i = 0,ptr = &mons[0]; ptr != &mons[NUMMONS] && ct > 0; i++,ptr++) {
X if(tooweak(i, minmlev) || toostrong(i, maxmlev))
X continue;
X#ifdef REINCARNATION
X if(upper & !isupper(def_monsyms[ptr->mlet])) continue;
X#endif
X if(elemlevel && wrong_elem_type(ptr)) continue;
X if(uncommon(ptr)) continue;
X ct -= (ptr->geno & G_FREQ);
X ct -= align_shift(ptr);
X }
X if(ct > 0) {
X#ifdef DEBUG
X pline("no count!");
X#endif
X return((struct permonst *) 0);
X }
X return(--ptr); /* subtract extra increment */
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. The second parameter specifies a
X * special casing bit mask to allow any of the normal genesis
X * masks to be deactivated. Returns 0 if no monsters
X * in that class can be made.
X */
X
Xstruct permonst *
Xmkclass(class,spc)
Xchar class;
Xint spc;
X{
X register int first, last, num = 0;
X int maxmlev, mask = (G_GENOD | G_EXTINCT | G_NOGEN | G_UNIQ) & ~spc;
X
X maxmlev = level_difficulty() >> 1;
X if(class < 1 || class >= MAXMCLASSES) {
X impossible("mkclass called with bad class!");
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; first < NUMMONS; first++)
X if (mons[first].mlet == class) break;
X if (first == NUMMONS) return((struct permonst *) 0);
X
X for(last = first; last < NUMMONS && mons[last].mlet == class; last++)
X if(!(mons[last].geno & mask)) {
X /* consider it */
X if(num && toostrong(last, maxmlev) && rn2(2)) break;
X num += mons[last].geno & G_FREQ;
X }
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 & mask)) {
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 u.uz 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 = (level_difficulty() - tmp);
X if(tmp2 < 0) tmp--; /* if mlevel > u.uz 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 * ((int) 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,victim) /* mon mtmp "grows up" to a bigger version. */
Xregister struct monst *mtmp;
Xregister struct monst *victim;
X{
X register int newtype;
X register struct permonst *ptr = mtmp->data;
X
X if (ptr->mlevel >= 50 || is_golem(ptr) || is_home_elemental(ptr)
X || is_mplayer(ptr))
X /* doesn't grow up, has strange hp calculation so might be
X * weakened by tests below */
X return ptr;
X
X if (victim) {
X mtmp->mhpmax = mtmp->mhpmax + (1 + rn2((int)victim->m_lev+1));
X if (mtmp->mhpmax <= (8 * (int)mtmp->m_lev)
X || (mtmp->m_lev == 0 && mtmp->mhpmax <= 4))
X /* not ready to grow up */
X return ptr;
X }
X#ifdef MUSE
X /* else it's a gain level potion; always go up a level */
X else {
X int foo=rnd(8);
X
X mtmp->mhp += foo;
X mtmp->mhpmax += foo;
X }
X#endif
X
X newtype = little_to_big(monsndx(ptr));
X if ((int) (++mtmp->m_lev) >= mons[newtype].mlevel
X && newtype != monsndx(ptr)) {
X if (mons[newtype].geno & G_GENOD) { /* allow G_EXTINCT */
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 (newtype == monsndx(ptr) && victim &&
X (int) mtmp->m_lev > (3*(int)mtmp->data->mlevel) / 2)
X mtmp->m_lev = (3*(int)mtmp->data->mlevel) / 2;
X if (mtmp->m_lev > 0) {
X if (mtmp->mhp > (int) mtmp->m_lev * 8)
X mtmp->mhp = mtmp->m_lev * 8;
X if (mtmp->mhpmax > (int) mtmp->m_lev * 8)
X mtmp->mhpmax = mtmp->m_lev * 8;
X }
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#ifdef MUSE
X if (!otyp) return 0;
X#endif
X if((otmp = (otyp) ? mksobj(otyp,TRUE,FALSE) : mkobj((char)otyp,FALSE))) {
X if (mtmp->data->mlet == S_DEMON) {
X /* demons always get cursed objects */
X curse(otmp);
X } else if(is_lminion(mtmp->data)) {
X /* lawful minions don't get cursed, bad, or rusting objects */
X otmp->cursed = FALSE;
X if(otmp->spe < 0) otmp->spe = 0;
X otmp->oerodeproof = TRUE;
X } else if(is_mplayer(mtmp->data) && is_sword(otmp))
X otmp->spe = (3 + rn2(4));
X if(otmp->otyp == CANDELABRUM_OF_INVOCATION) {
X otmp->spe = 0;
X otmp->age = 0L;
X otmp->lamplit = FALSE;
X otmp->blessed = otmp->cursed = FALSE;
X }
X mpickobj(mtmp, otmp);
X return(otmp->spe);
X } else return(0);
X}
X
X#endif /* OVL1 */
X#ifdef OVLB
X
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
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 aligntyp mal = ptr->maligntyp, ual = u.ualign.type;
X
X if (always_peaceful(ptr)) return TRUE;
X if (always_hostile(ptr)) return FALSE;
X#ifdef MULDGN
X if (ptr->msound == MS_LEADER || ptr->msound == MS_GUARDIAN)
X return TRUE;
X if (ptr->msound == MS_NEMESIS) return FALSE;
X#endif
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 < A_NEUTRAL && u.uhave.amulet) return FALSE;
X
X /* minions are hostile to players that have strayed at all */
X if (is_minion(ptr)) return(u.ualign.record >= 0);
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.record negative) or the monster is not strongly aligned.
X */
X return !!rn2(16 + (u.ualign.record < -15 ? -15 : u.ualign.record)) &&
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;
X
X if (mtmp->ispriest || mtmp->isminion) {
X /* some monsters have individual alignments; check them */
X if (mtmp->ispriest)
X mal = EPRI(mtmp)->shralign;
X else if (mtmp->isminion)
X mal = EMIN(mtmp)->min_align;
X /* unless alignment is none, set mal to -5,0,5 */
X /* (see align.h for valid aligntyp values) */
X if(mal != A_NONE)
X mal *= 5;
X }
X
X coaligned = (sgn(mal) == sgn(u.ualign.type));
X#ifdef MULDGN
X if (mtmp->data->msound == MS_LEADER) {
X mtmp->malign = -20;
X } else
X#endif
X if (mal == A_NONE) {
X if (mtmp->mpeaceful)
X mtmp->malign = 0;
X else
X mtmp->malign = 20; /* really hostile */
X } else if (always_peaceful(mtmp->data)) {
X if (mtmp->mpeaceful)
X mtmp->malign = -3*max(5,abs(mal));
X else
X mtmp->malign = 3*max(5,abs(mal)); /* renegade */
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[] = {
X MAXOCLASSES, MAXOCLASSES+1, RING_CLASS, WAND_CLASS, WEAPON_CLASS,
X FOOD_CLASS, GOLD_CLASS, SCROLL_CLASS, POTION_CLASS, ARMOR_CLASS,
X AMULET_CLASS, TOOL_CLASS, ROCK_CLASS, GEM_CLASS, SPBOOK_CLASS,
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 typ, 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 typ = levl[mx][my].typ;
X /* only valid for INSIDE of room */
X roomno = levl[mx][my].roomno - ROOMOFFSET;
X if (roomno >= 0)
X rt = rooms[roomno].rtype;
X#ifdef SPECIALIZATION
X else if (IS_ROOM(typ))
X rt = OROOM, roomno = 0;
X#endif
X else rt = 0; /* roomno < 0 case for GCC_WARN */
X
X if (OBJ_AT(mx, my)) {
X ap_type = M_AP_OBJECT;
X appear = level.objects[mx][my]->otyp;
X } else if (IS_DOOR(typ) || IS_WALL(typ) ||
X typ == SDOOR || typ == SCORR) {
X ap_type = M_AP_FURNITURE;
X /*
X * If there is a wall to the left that connects to this
X * location, then the mimic mimics a horizontal closed door.
X * This does not allow doors to be in corners of rooms.
X */
X if (mx != 0 &&
X (levl[mx-1][my].typ == HWALL ||
X levl[mx-1][my].typ == TLCORNER ||
X levl[mx-1][my].typ == TRWALL ||
X levl[mx-1][my].typ == BLCORNER ||
X levl[mx-1][my].typ == TDWALL ||
X levl[mx-1][my].typ == CROSSWALL||
X levl[mx-1][my].typ == TUWALL ))
X appear = S_hcdoor;
X else
X appear = S_vcdoor;
X
X if(!mtmp->minvis || See_invisible)
X block_point(mx,my); /* vision */
X } else if (level.flags.is_maze_lev && rn2(2)) {
X ap_type = M_AP_OBJECT;
X appear = STATUE;
X } else if (roomno < 0) {
X ap_type = M_AP_OBJECT;
X appear = BOULDER;
X if(!mtmp->minvis || See_invisible)
X block_point(mx,my); /* vision */
X } else if (rt == ZOO || rt == VAULT) {
X ap_type = M_AP_OBJECT;
X appear = GOLD_PIECE;
X } else if (rt == DELPHI) {
X if (rn2(2)) {
X ap_type = M_AP_OBJECT;
X appear = STATUE;
X } else {
X ap_type = M_AP_FURNITURE;
X appear = S_fountain;
X }
X } else if (rt == TEMPLE) {
X ap_type = M_AP_FURNITURE;
X appear = S_altar;
X /*
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 } else {
X if (s_sym == RANDOM_CLASS)
X s_sym = syms[rn2((int)sizeof(syms)-2) + 2];
X goto assign_sym;
X }
X } else {
X s_sym = syms[rn2((int)sizeof(syms))];
Xassign_sym:
X if (s_sym >= MAXOCLASSES) {
X ap_type = M_AP_FURNITURE;
X appear = s_sym == MAXOCLASSES ? S_upstair : S_dnstair;
X } else if (s_sym == GOLD_CLASS) {
X ap_type = M_AP_OBJECT;
X appear = GOLD_PIECE;
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 /* make sure container contents are free'ed */
X obfree(otmp, (struct obj *) 0);
X }
X }
X }
X mtmp->m_ap_type = ap_type;
X mtmp->mappearance = appear;
X}
X
X#endif /* OVLB */
X
X/*makemon.c*/
END_OF_FILE
if test 40817 -ne `wc -c <'src/makemon.c'`; then
echo shar: \"'src/makemon.c'\" unpacked with wrong size!
fi
# end of 'src/makemon.c'
fi
echo shar: End of archive 31 \(of 108\).
cp /dev/null ark31isdone
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