ftp.nice.ch/pub/next/games/strategic/NetHack.s.tar.gz#/NetHackSource/src/dog.c

This is dog.c in view mode; [Download] [Up]

/*	SCCS Id: @(#)dog.c	3.0	89/11/20
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed.  See license for details. */

#include "hack.h"
#include "edog.h"

#ifdef OVLB

char dogname[63] = DUMMY;
char catname[63] = DUMMY;

#endif /* OVLB */

#define domestic(mtmp)	(mtmp->data->msound == MS_BARK || mtmp->data->msound == MS_MEW)

#ifdef OVLB

void
initedog(mtmp)
register struct monst *mtmp;
{
	mtmp->mtame = domestic(mtmp) ? 10 : 5;
	mtmp->mpeaceful = 1;
	mtmp->mleashed = 0;
	mtmp->meating = 0;
	EDOG(mtmp)->droptime = 0;
	EDOG(mtmp)->dropdist = 10000;
	EDOG(mtmp)->apport = 10;
	EDOG(mtmp)->whistletime = 0;
	EDOG(mtmp)->hungrytime = 1000 + moves;
}

void
make_familiar(otmp)
register struct obj *otmp;
{
	register struct monst *mtmp;
	register struct permonst *pm;

top:
	if (otmp) pm = &mons[otmp->corpsenm]; /* Figurine; otherwise spell */
	else if (rn2(3)) {
	    if (!(pm = rndmonst())) {
		pline("There seems to be nothing available for a familiar.");
		return;
	    }
	}
	else if ((pl_character[0]=='W' || rn2(2)) && pl_character[0]!='C')
		pm = &mons[PM_KITTEN];
	else pm = &mons[PM_LITTLE_DOG];

	pm->pxlth += sizeof(struct edog);
	mtmp = makemon(pm, u.ux, u.uy);
	pm->pxlth -= sizeof(struct edog);
	if (!mtmp) { /* monster was genocided */
	    if (otmp)
		pline("The figurine writhes and then shatters into pieces!");
	    else goto top;
		/* rndmonst() returns something not genocided always, so this
		 * means it was a cat or dog; loop back to try again until
		 * either rndmonst() is called, or if only one of cat/dog
		 * was genocided, they get the other.
		 */
	    return;
	}
	initedog(mtmp);
	mtmp->msleep = 0;
	if (otmp && otmp->cursed) { /* cursed figurine */
		You("get a bad feeling about this.");
		mtmp->mtame = mtmp->mpeaceful = 0;
	}
}

struct monst *
makedog() {
	register struct monst *mtmp;
	register char *petname;

	if (pl_character[0]=='C' || (pl_character[0] != 'W' && rn2(2))) {
		mons[PM_LITTLE_DOG].pxlth = sizeof(struct edog);
		mtmp = makemon(&mons[PM_LITTLE_DOG], u.ux, u.uy);
		mons[PM_LITTLE_DOG].pxlth = 0;
		petname = dogname;
	} else {
		mons[PM_KITTEN].pxlth = sizeof(struct edog);
		mtmp = makemon(&mons[PM_KITTEN], u.ux, u.uy);
		mons[PM_KITTEN].pxlth = 0;
		petname = catname;
	}

	if(!mtmp) return((struct monst *) 0); /* dogs were genocided */

	if (petname[0]) {
		mtmp = christen_monst(mtmp, petname);
#ifndef MACOS
		petname[0] = '\0'; /* name first only; actually unnecessary */
#endif
	}
	initedog(mtmp);
	return(mtmp);
}

/* attach the monsters that went down (or up) together with @ */
struct monst *mydogs = 0;
/* monsters that fell through a trap door or stepped on a tele-trap. */
/* 'down' is now true only of trap door falling, not for tele-trap. */
struct monst *fallen_down = 0;
				
void
losedogs(){
	register struct monst *mtmp,*mtmp0,*mtmp2;

	while(mtmp = mydogs){
		mydogs = mtmp->nmon;
		mtmp->nmon = fmon;
		fmon = mtmp;
		mnexto(mtmp);
	}
#if defined(LINT) || defined(__GNULINT__)
	mtmp0 = (struct monst *)0;
#endif
	for(mtmp = fallen_down; mtmp; mtmp = mtmp2) {
		mtmp2 = mtmp->nmon;
		if(mtmp->mx == dlevel) {
		    mtmp->mx = 0;
		    if(mtmp == fallen_down)
			fallen_down = mtmp->nmon;
		    else
			mtmp0->nmon = mtmp->nmon;
		    mtmp->nmon = fmon;
		    fmon = mtmp;
		    if (mtmp->data->geno & G_GENOD) {
#ifdef KOPS
			allow_kops = FALSE;
#endif
			mondead(mtmp);	/* must put in fmon list first */
#ifdef KOPS
			allow_kops = TRUE;
#endif
		    } else if (mtmp->isshk)
			home_shk(mtmp);
		    else
			rloc(mtmp);
		} else
		    mtmp0 = mtmp;
	}
}

void
keepdogs(){
register struct monst *mtmp;
	for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
	    if(((monnear(mtmp, u.ux, u.uy) && levl_follower(mtmp)) ||
		/* the wiz will level t-port from anywhere to chase
		   the amulet; if you don't have it, will chase you
		   only if in range. -3. */
			(u.uhave_amulet && mtmp->iswiz))
			&& !mtmp->msleep && mtmp->mcanmove) {
#ifdef WORM
		/* Bug "fix" for worm changing levels collapsing dungeon
		 */
		if (mtmp->data == &mons[PM_LONG_WORM]) {
			if (showmon(mtmp))
				pline("The worm can't fit down the stairwell.");
# ifdef WALKIES
			if (mtmp->mleashed) {
				pline("The leash slides off the slimy worm.");
				m_unleash(mtmp);
			}
# endif
			continue;
		}
#endif
		if (mon_has_amulet(mtmp)) {
			pline("%s seems very disoriented for a moment.",
				Monnam(mtmp));
#ifdef WALKIES
			if (mtmp->mleashed) {
				pline("%s leash suddenly comes loose.",
					is_female(mtmp) ? "Her" :
					humanoid(mtmp->data) ? "His" : "Its");
				m_unleash(mtmp);
			}
#endif
			continue;
		}
		relmon(mtmp);
		mtmp->mx = mtmp->my = 0; /* avoid mnexto()/MON_AT() problem */
		mtmp->nmon = mydogs;
		mydogs = mtmp;
		unpmon(mtmp);
		keepdogs();	/* we destroyed the link, so use recursion */
		return;		/* (admittedly somewhat primitive) */
	}
}

void
fall_down(mtmp, tolev) 
register struct monst *mtmp; 
register int tolev;
{
	relmon(mtmp);
	mtmp->nmon = fallen_down;
	fallen_down = mtmp;
#ifdef WALKIES
	if (mtmp->mleashed)  {
		pline("The leash comes off!");
		m_unleash(mtmp);
	}
#endif
	unpmon(mtmp);
	mtmp->mtame = 0;
	mtmp->mx = tolev; 
	mtmp->my = 0;
		/* make sure to reset mtmp->mx to 0 when releasing, */
		/* so rloc() on next level doesn't affect MON_AT() state */
}

#endif /* OVLB */
#ifdef OVL1

/* return quality of food; the lower the better */
/* fungi will eat even tainted food */
int
dogfood(mon,obj)
struct monst *mon;
register struct obj *obj;
{
	boolean carni = carnivorous(mon->data);
	boolean herbi = herbivorous(mon->data);

	switch(obj->olet) {
	case FOOD_SYM:
	    if (obj->otyp == CORPSE && obj->corpsenm == PM_COCKATRICE &&
		!resists_ston(mon->data))
		    return TABU;

	    if (!carni && !herbi)
		    return (obj->cursed ? UNDEF : APPORT);

	    switch (obj->otyp) {
		case TRIPE_RATION:
		    return (carni ? DOGFOOD : MANFOOD);
		case EGG:
		    if (obj->corpsenm == PM_COCKATRICE &&
						!resists_ston(mon->data))
			return POISON;
		    return (carni ? CADAVER : MANFOOD);
		case CORPSE:
		    if ((obj->age+50 <= monstermoves
					    && obj->corpsenm != PM_LIZARD
					    && mon->data->mlet != S_FUNGUS) ||
			(acidic(&mons[obj->corpsenm]) &&
						!resists_acid(mon->data)) ||
			(poisonous(&mons[obj->corpsenm]) &&
						!resists_poison(mon->data)))
			return POISON;
		    else if (mon->data->mlet == S_FUNGUS)
			return (herbi ? CADAVER : MANFOOD);
		    else return (carni ? CADAVER : MANFOOD);
		case CLOVE_OF_GARLIC:
		    return (is_undead(mon->data) ? TABU :
			    (herbi ? ACCFOOD : MANFOOD));
		case TIN:
		    return MANFOOD;
		case APPLE:
		case CARROT:
		    return (herbi ? DOGFOOD : MANFOOD);
		default:
#ifdef TUTTI_FRUTTI
		    return (obj->otyp > SLIME_MOLD ?
#else
		    return (obj->otyp > CLOVE_OF_GARLIC ?
#endif
			    (carni ? ACCFOOD : MANFOOD) :
			    (herbi ? ACCFOOD : MANFOOD));
	    }
	default:
	    if(!obj->cursed) return(APPORT);
	    /* fall into next case */
	case BALL_SYM:
	case CHAIN_SYM:
	case ROCK_SYM:
	    return(UNDEF);
	}
}

#endif /* OVL1 */
#ifdef OVL0

/* return roomnumber or -1 */
int
inroom(x,y) xchar x,y; {
	register struct mkroom *croom = &rooms[0];
	while(croom->hx >= 0){
		if(croom->hx >= x-1 && croom->lx <= x+1 &&
		   croom->hy >= y-1 && croom->ly <= y+1)
			return(croom - rooms);
		croom++;
	}
	return(-1);	/* not in room or on door */
}

#endif /* OVL0 */
#ifdef OVLB

int
tamedog(mtmp, obj)
register struct monst *mtmp;
register struct obj *obj;
{
	register struct monst *mtmp2;

	/* worst case, at least he'll be peaceful. */
	mtmp->mpeaceful = 1;
	if(flags.moonphase == FULL_MOON && night() && rn2(6) && obj
						&& mtmp->data->mlet == S_DOG)
		return(0);

	/* If we cannot tame him, at least he's no longer afraid. */
	mtmp->mflee = 0;
	mtmp->mfleetim = 0;
	if(mtmp->mtame || !mtmp->mcanmove ||
#ifdef MEDUSA
	   mtmp->data == &mons[PM_MEDUSA] ||
#endif
	   mtmp->isshk || mtmp->isgd ||
#if defined(ALTARS) && defined(THEOLOGY)
	   mtmp->ispriest ||
#endif
#ifdef POLYSELF
	   is_human(mtmp->data) || (is_demon(mtmp->data) && !is_demon(uasmon)))
#else
	   is_human(mtmp->data) || is_demon(mtmp->data))
#endif
		return(0);
	if(obj) {
		if(dogfood(mtmp, obj) >= MANFOOD) return(0);
		if(cansee(mtmp->mx,mtmp->my))
			pline("%s devours the %s.", Monnam(mtmp), xname(obj));
		obfree(obj, (struct obj *)0);
	}
	mtmp2 = newmonst(sizeof(struct edog) + mtmp->mnamelth);
	*mtmp2 = *mtmp;
	mtmp2->mxlth = sizeof(struct edog);
	if(mtmp->mnamelth) Strcpy(NAME(mtmp2), NAME(mtmp));
	initedog(mtmp2);
	replmon(mtmp,mtmp2);
	return(1);
}

#endif /* OVLB */

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.