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

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

/*	SCCS Id: @(#)dokick.c	3.0	89/6/9
/* Copyright (c) Izchak Miller, Mike Stephenson, Steve Linhart, 1989. */
/* NetHack may be freely redistributed.  See license for details. */

#include	"hack.h"
#include	"eshk.h"

#define martial()	((pl_character[0] == 'S' || pl_character[0] == 'P'))

static struct rm *maploc;

#ifdef KICK

# ifdef WORM
extern boolean notonhead;
# endif

static void FDECL(kickdmg, (struct monst *, BOOLEAN_P));
static void FDECL(kick_monster, (int, int));
static int FDECL(kick_object, (int, int));

static struct obj *obj = (struct obj *) 0;

static void
kickdmg(mon, clumsy)
register struct monst *mon;
register boolean clumsy;
{
	register int mdx, mdy;
	register int dmg = (((uarmg && 
				uarmg->otyp == GAUNTLETS_OF_POWER) ? 
				25 : ACURR(A_STR) > 18 ? 18 : ACURR(A_STR))+
				ACURR(A_DEX)+ACURR(A_CON))/15;

	/* excessive wt affects dex, so it affects dmg */
	if(clumsy) dmg = dmg/2;

	/* kicking a dragon or an elephant will not harm it */
	if(thick_skinned(mon->data)) dmg = 0;
	

	/* squeeze some guilt feelings... */
	if(mon->mtame) {
# ifdef SOUNDS
	    if (rn2(10)) yelp(mon);
	    else growl(mon); /* give them a moment's worry */
# endif
	    mon->mtame--;
	    mon->mflee = mon->mtame ? 1 : 0;
# ifdef HISX
	    mon->mfleetim = mon->mfleetim + (dmg ? rnd(dmg) : 1);
# else
	    mon->mfleetim += (dmg ? rnd(dmg) : 1);
# endif
	}
	
	if (dmg)
		mon->mhp -= (!martial() ? rnd(dmg) :
			rnd(dmg)+rnd(ACURR(A_DEX)/2));  
	if(mon->mhp < 1) {
		(void) passive(mon, TRUE, 0, TRUE);
		killed(mon);
		return;
	}
	if(martial() && !bigmonst(mon->data) && !rn2(3) && mon->mcanmove) {
	    	/* see if the monster has a place to move into */
	    	mdx = mon->mx + u.dx;
	    	mdy = mon->my + u.dy;
	    	if(goodpos(mdx, mdy, mon->data)) {
			kludge("%s reels from the blow.", Monnam(mon));
			remove_monster(mon->mx, mon->my);
			place_monster(mon, mdx, mdy);
			pmon(mon);
			set_apparxy(mon);
	    	}
	}
	(void) passive(mon, FALSE, 1, TRUE);

/*	it is unchivalrous to attack the defenseless or from behind */
	if (pl_character[0] == 'K' && u.ualigntyp == U_LAWFUL && 
		u.ualign > -10 && (!mon->mcanmove || mon->msleep || mon->mflee))
	    	adjalign(-1);

}

static void
kick_monster(x, y)
register int x, y;
{
	register boolean clumsy = FALSE;
	register struct monst *mon = m_at(x, y);
	register int i, j;

	if(special_case(mon)) return;
	setmangry(mon);
#ifdef POLYSELF
	/* Kick attacks by kicking monsters are normal attacks, not special.
	 * If you have >1 kick attack, you get all of them.
	 */
	if (attacktype(uasmon, AT_KICK)) {
	    schar tmp = find_roll_to_hit(mon);
	    for(i=0; i<NATTK; i++) {
		int sum = 0;
		if (uasmon->mattk[i].aatyp == AT_KICK && multi >= 0) {
		    /* check multi; maybe they had 2 kicks and the first */
		    /* was a kick against a floating eye */
		    j = 1;
		    if (tmp > rnd(20)) {
			kludge("You kick %s.", mon_nam(mon));
			sum = damageum(mon, &(uasmon->mattk[i]));
			if (sum == 2)
				(void)passive(mon, 1, 0, TRUE);
			else (void)passive(mon, sum, 1, TRUE);
		    } else {
			missum(mon, &(uasmon->mattk[i]));
			(void)passive(mon, 0, 1, TRUE);
		    }
		}
	    }
	    return;
	}
#endif

	/* no need to check POLYSELF since only ghosts, which you can't turn */
	/* into, are noncorporeal */
	if(noncorporeal(mon->data)) {
		Your("kick passes through!");
		return;
	}

	if(Levitation && !rn2(3) && verysmall(mon->data) &&
	   !is_flyer(mon->data)) {
		pline("Floating in the air, you miss wildly!");
		(void) passive(mon, FALSE, 1, TRUE);
		return;
	}

	i = abs(inv_weight());
	j = weight_cap();

	if(i < (j*3)/10) {
		if(!rn2((i < j/10) ? 2 : (i < j/5) ? 3 : 4)) {
			if(martial() && !rn2(2)) goto doit;
			Your("clumsy kick does no damage.");
			(void) passive(mon, FALSE, 1, TRUE);
			return;
		}
		if(i < j/10) clumsy = TRUE;
		else if(!rn2((i < j/5) ? 2 : 3)) clumsy = TRUE;  
	} 

	if(Fumbling) clumsy = TRUE;

	else if(uarm && objects[uarm->otyp].oc_bulky && ACURR(A_DEX) < rnd(25))
		clumsy = TRUE;
doit:
	kludge("You kick %s.", mon_nam(mon));
	if(!rn2(clumsy ? 3 : 4) && (clumsy || !bigmonst(mon->data)) && 
	   mon->mcansee && !mon->mtrapped && !thick_skinned(mon->data) && 
	   mon->data->mlet != S_EEL && haseyes(mon->data) && mon->mcanmove && 
	   !mon->mstun && !mon->mconf && !mon->msleep &&
	   mon->data->mmove >= 12) {
		if(!nohands(mon->data) && !rn2(martial() ? 5 : 3)) {
		    kludge("%s blocks your %skick.", Monnam(mon), 
				clumsy ? "clumsy " : "");
		    (void) passive(mon, FALSE, 1, TRUE);
		    return;
		} else {
		    mnexto(mon);
		    if(mon->mx != x || mon->my != y) {
		        pline("%s %s, %s evading your %skick.", 
				Blind ? "It" : Monnam(mon),
				(can_teleport(mon->data) ? "teleports" :
				 is_floater(mon->data) ? "floats" :
				 is_flyer(mon->data) ? "flutters" :
				 nolimbs(mon->data) ? "slides" :
				 "jumps"),
				clumsy ? "easily" : "nimbly",
				clumsy ? "clumsy " : "");
			(void) passive(mon, FALSE, 1, TRUE);
		        return;
		    } 
		}
	}
	kickdmg(mon, clumsy);
}
#endif /* KICK */

/* return TRUE if caught, FALSE otherwise */
boolean
ghitm(mtmp, amount)
register struct monst *mtmp;
register long amount;
{
	if(!likes_gold(mtmp->data) && !mtmp->isshk 
#if defined(ALTARS) && defined(THEOLOGY)
		&& !mtmp->ispriest
#endif
		) 
		wakeup(mtmp);
	else {
		mtmp->msleep = 0;
		mtmp->meating = 0;
		if(!rn2(4)) setmangry(mtmp); /* not always pleasing */
		
		/* greedy monsters catch gold */
		kludge("%s catches the gold.", Monnam(mtmp));
		mtmp->mgold += amount;
		if (mtmp->isshk) {
			long robbed = ESHK(mtmp)->robbed;

			if (robbed) {
				robbed -= amount;
				if (robbed < 0) robbed = 0;
				pline("The amount %scovers %s recent losses.",
					!robbed ? "" : "partially ", 
					ESHK(mtmp)->ismale ? "his" : "her");
				ESHK(mtmp)->robbed = robbed;
				if(!robbed)
					make_happy_shk(mtmp);
			} else {
				if(mtmp->mpeaceful) {
				    ESHK(mtmp)->credit += amount;
				    You("have %ld zorkmid%s in credit.",
					ESHK(mtmp)->credit, 
					plur(ESHK(mtmp)->credit));
				} else verbalize("Thanks, scum!");
			}
		}
#if defined(ALTARS) && defined(THEOLOGY)
		else if(mtmp->ispriest) {
			if(mtmp->mpeaceful)
			    verbalize("Thank you for your contribution.");
			else verbalize("Thanks, scum!");
		}
#endif
		return(1);
	}
	return(0);

}

boolean
bad_kick_throw_pos(x,y)
xchar x,y;
{
	return(!accessible(x, y) || levl[x][y].typ == SDOOR);
}

struct monst *
ghit(ddx, ddy, range)
register int ddx, ddy, range; 
{
	register struct monst *mtmp = (struct monst *) 0;

	bhitpos.x = u.ux;
	bhitpos.y = u.uy;

	tmp_at(-1, GOLD_SYM);	/* open call */
	tmp_at(-3, (int)AT_GLD);
	while(range-- > 0) {
		bhitpos.x += ddx;
		bhitpos.y += ddy;
		if(MON_AT(bhitpos.x, bhitpos.y)) {
			mtmp = m_at(bhitpos.x,bhitpos.y);
			tmp_at(-1, -1); /* close call */
			return(mtmp);
		}
		/* stop on a zorkmid */
		if(levl[bhitpos.x][bhitpos.y].gmask ||
		     	    OBJ_AT(bhitpos.x, bhitpos.y)) {
			tmp_at(-1, -1); /* close call */
			return (struct monst *)0;
		}
		if(bad_kick_throw_pos(bhitpos.x,bhitpos.y)) {
			bhitpos.x -= ddx;
			bhitpos.y -= ddy;
			break;
		}
		tmp_at(bhitpos.x, bhitpos.y);
	}
	tmp_at(-1, -1);
	return(struct monst *)0;
}

#ifdef KICK
static int
kick_object(x, y)
int x, y;
{
	int range, odx, ody, cnt = 0;
	register struct monst *mon;
	struct gold *gold;
	register struct obj *otmp;
	boolean costly = FALSE;

	/* if a pile, the "top" object gets kicked */
	for (otmp = level.objects[x][y]; otmp; otmp = otmp->nexthere)
		if(!otmp->cobj) {
			cnt++;
			if(cnt == 1) obj = otmp;
		}

	/* range < 2 means the object will not move.	*/
	/* maybe dexterity should also figure here.     */
	if(cnt) range = (int)((ACURR(A_STR) > 18 ? 20 : 
				ACURR(A_STR))/2 - obj->owt/4);
	else range = rnd((int)ACURR(A_STR));

	if(martial()) range = range + rnd(3);
	if(range < 1) range = 1; /* safety... */

	/* see if the object has a place to move into */
	odx = x + u.dx;
	ody = y + u.dy;
	if(bad_kick_throw_pos(odx,ody))
	    range = 1;

	if(Fumbling && !rn2(3)) {
		Your("clumsy kick missed.");
		return(1);
	}

	if(!cnt && levl[x][y].gmask) {
		long zm;
		gold = g_at(x, y);
		zm = gold->amount;
		if(IS_ROCK(levl[x][y].typ)) {
			if ((!martial() && rn2(20) > ACURR(A_DEX))
#ifdef POLYSELF
				|| IS_ROCK(levl[u.ux][u.uy].typ)
#endif
								) {
				pline("%s doesn't come loose.",
					Blind ? "It" : "The gold");
				return(!rn2(3) || martial());
			}
			pline("%s comes loose.", Blind ? "It" : "The gold");
			freegold(gold);
			newsym(x, y);
			mkgold(zm, u.ux, u.uy);
			if (Invisible
#ifdef POLYSELF
					&& !u.uundetected
#endif
						) newsym(u.ux, u.uy);
			return(1);
		}
		if(range < 2 || zm > 300L) /* arbitrary */
		    return(0);
		freegold(gold);
		newsym(x, y);
		if(mon = ghit(u.dx, u.dy, range)) {
			setmangry(mon); /* not a means for payment to shk */
			if(ghitm(mon, zm)) /* was it caught? */
			    return(1);
		}
		mkgold(zm, bhitpos.x, bhitpos.y);
		if(cansee(bhitpos.x, bhitpos.y)) prl(bhitpos.x,bhitpos.y);
		return(1);
	}

	/* cnt should always be >= 1 here (meaning obj is set) due to
	 * conditions of call */
	if(!cnt || obj->otyp == BOULDER || obj == uball || obj == uchain)
		return(0);

	/* a box gets a chance of breaking open here */
	if(Is_box(obj)) {
		boolean otrp = obj->otrapped;

		if (!obj->olocked && (!rn2(3) ||
					(martial() && !rn2(2)))) {
		    pline("The lid slams open, then falls shut.");
		    if(otrp) chest_trap(obj, LEG);
		    return(1);
		} else if (obj->olocked && 
				(!rn2(5) || (martial() && !rn2(2)))) {
		    You("break open the lock!");
		    obj->olocked = 0;
	            if(otrp) chest_trap(obj, LEG);
		    return(1);
		}
		/* let it fall through to the next cases... */
	}

	if(Levitation && !rn2(3)) {
		You("miss."); /* do not identify the object */
		return(1);
	}

	/* fragile objects should not be kicked */
	if (breaks(obj, FALSE)) return(1);

	costly = costly_spot(x, y);

	/* potions get a chance of breaking here */
	if(obj->olet == POTION_SYM) {
		if(rn2(2)) {
		    You("smash %s %s!", obj->quan==1 ? "the" : "a", xname(obj));
		    potionbreathe(obj);
		    useupf(obj);
		    return(1);
		}
	}

	if(IS_ROCK(levl[x][y].typ)) {
		if ((!martial() && rn2(20) > ACURR(A_DEX))
#ifdef POLYSELF
				|| IS_ROCK(levl[u.ux][u.uy].typ)
#endif
								) {
			if (Blind) pline("It doesn't come loose.");
			else pline("The %s do%sn't come loose.",
				distant_name(obj, xname),
				(obj->quan==1) ? "es" : "");
			return(!rn2(3) || martial());
		}
		if (Blind) pline("It comes loose.");
		else pline("The %s come%s loose.", distant_name(obj, xname),
			(obj->quan==1) ? "s" : "");
		move_object(obj, u.ux, u.uy);
		newsym(x, y);
		stackobj(obj);
		if (Invisible
#ifdef POLYSELF
				&& !u.uundetected
#endif
						) newsym(u.ux, u.uy);
		if (costly && !costly_spot(u.ux, u.uy)) addtobill(obj, FALSE);
		return(1);
	}

	/* too heavy to move. make sure not to call bhit  */
	/* in this function when range < 2 (a display bug */
	/* results otherwise).  			  */
	if(range <= 2) {
	    if(Is_box(obj)) pline("THUD!");
	    else pline("Thump!");
	    if(!rn2(3) || martial()) return(1);
	    return(0);
	}

	if (obj->quan > 1) (void) splitobj(obj, 1);

	/* Needed to fool bhit's display-cleanup to show immediately	*/
	/* the next object in the pile.  We know here that the object	*/
	/* will move, so there is no need to worry about the location,	*/
	/* which merely needs to be something other than ox, oy.	*/
	move_object(obj, u.ux, u.uy);
	if(cnt == 1 && !MON_AT(x, y))
	    newsym(x, y);

	mon = bhit(u.dx, u.dy, range, obj->olet,
			(int (*)()) 0, (int (*)()) 0, obj);
	freeobj(obj);
	if(mon) {
# ifdef WORM
		if (mon->mx != bhitpos.x || mon->my != bhitpos.y)
			notonhead = TRUE;
# endif
		/* awake monster if sleeping */
		wakeup(mon);
		if(thitmonst(mon, obj)) return(1);
	}
	if(costly && !costly_spot(bhitpos.x,bhitpos.y)) addtobill(obj, FALSE);
	move_object(obj, bhitpos.x, bhitpos.y);
	obj->nobj = fobj;
	fobj = obj;
	stackobj(obj);
	if(!MON_AT(obj->ox, obj->oy))
	    newsym(obj->ox, obj->oy);
	return(1);
}
#endif /* KICK */

char *
kickstr() {
	static char buf[BUFSIZ];

#ifdef KICK
	if (obj) Sprintf(buf, "kicking %s", doname(obj));
	else
#endif
	if (IS_STWALL(maploc->typ)) Strcpy(buf, "kicking a wall");
	else if (IS_ROCK(maploc->typ)) Strcpy(buf, "kicking a rock");
#ifdef THRONES
	else if (IS_THRONE(maploc->typ)) Strcpy(buf, "kicking a throne");
#endif
#ifdef SINKS
	else if (IS_SINK(maploc->typ)) Strcpy(buf, "kicking a sink");
#endif
#ifdef ALTARS
	else if (IS_ALTAR(maploc->typ)) Strcpy(buf, "kicking an altar");
#endif
#ifdef STRONGHOLD
	else if (IS_DRAWBRIDGE(maploc->typ))
		Strcpy(buf, "kicking the drawbridge");
#endif
	else {
		switch (maploc->typ) {
		case STAIRS:	
			Strcpy(buf, "kicking the stairs");
			break;
#ifdef STRONGHOLD
		case LADDER:
			Strcpy(buf, "kicking a ladder");
			break;
#endif
		}
	}

	return buf;
}

int
dokick() {		/* try to kick the door down - noisy! */
        register int x, y;
	register int avrg_attrib = (ACURR(A_STR)+ACURR(A_DEX)+ACURR(A_CON))/3;

#ifdef POLYSELF
	if(nolimbs(uasmon)) {
		You("have no legs to kick with.");
		return(0);
	}
	if(verysmall(uasmon)) {
		You("are too small to do any kicking.");
		return(0);
	}
#endif
	if(Wounded_legs) {
		Your("%s %s in no shape for kicking.",
		      ((Wounded_legs & BOTH_SIDES)==BOTH_SIDES)
			? makeplural(body_part(LEG)) : body_part(LEG),
		      ((Wounded_legs & BOTH_SIDES)==BOTH_SIDES) ? "are" : "is");
		return(0);
	}

	if(inv_weight() > 0) {
		Your("load is too heavy to balance yourself for a kick.");
		return(0);
	}

        if(u.utrap) {
		switch (u.utraptype) {
		    case TT_PIT:
			pline("There's nothing to kick down here.");
		    case TT_WEB:
		    case TT_BEARTRAP:
			You("can't move your %s!", body_part(LEG));
		}
		return(0);
	}

	if(!getdir(1)) return(0);
	if(!u.dx && !u.dy) return(0);

	x = u.ux + u.dx;
	y = u.uy + u.dy;

	if(u.uswallow) {
		switch(rn2(3)) {
		case 0:  You("can't move your %s!", body_part(LEG));
			 break;
		case 1:  if (is_animal(u.ustuck->data)) {
			 	pline("%s burps loudly.", Monnam(u.ustuck)); 
			       	break; 
                         }
		default: Your("feeble kick has no effect."); break;
		}
		return(1);
	}

	wake_nearby();
	u_wipe_engr(2);

	maploc = &levl[x][y];

#ifdef KICK
	/* The next four main loops should stay in */
	/* their present order: monsters, objects, */
	/* non-doors, doors.			   */ 

	if(MON_AT(x, y)) {
		kick_monster(x, y);
		return(1);
	}

	if((OBJ_AT(x, y) || maploc->gmask) && !Levitation) {
		if(kick_object(x, y)) return(1);
		else goto ouch;
	}

	if(!IS_DOOR(maploc->typ)) {
		if(maploc->typ == SDOOR) {
		    if(rn2(30) < avrg_attrib) { 
			pline("Crash!  You kick open a secret door!");
			maploc->typ = DOOR;
			if(maploc->doormask & D_TRAPPED) {
			    b_trapped("door");
			    maploc->doormask = D_NODOOR;
			} else
			    maploc->doormask = D_ISOPEN;
			mnewsym(x,y);
			prl(x,y);
			return(1);
		    } else goto ouch;
		}
		if(maploc->typ == SCORR) {
		    if(rn2(30) < avrg_attrib) { 
			pline("Crash!  You kick open a secret passage!");
			maploc->typ = CORR;
			mnewsym(x,y);
			prl(x,y);
			return(1);
		    } else goto ouch;
		}
# ifdef THRONES
		if(IS_THRONE(maploc->typ)) {
		    register int i;
		    if((Luck < 0 || maploc->doormask) && !rn2(3)) {
			pline("CRASH!  You destroy the throne.");
			maploc->typ = ROOM;
			maploc->doormask = 0; /* don't leave loose ends.. */
			mkgold((long)rnd(200), x, y);
			prl(x, y);
			return(1);
		    } else if(Luck > 0 && !rn2(3) && !maploc->looted) {
			You("kick loose some ornamental coins and gems!");
			mkgold((300L+(long)rn2(201)), x, y);
			i = Luck + 1;
			if(i > 6) i = 6;
			while(i--) (void) mkobj_at(GEM_SYM, x, y);
			prl(x, y);
			/* prevent endless milking */
			maploc->looted = T_LOOTED;
			return(1);
		    } else if (!rn2(4)) {
			register struct trap *ttmp = 
					maketrap(u.ux,u.uy,TRAPDOOR);
			dotrap(ttmp);
			return(1);
		    }
		    goto ouch;
		}
# endif
# ifdef ALTARS
		if(IS_ALTAR(maploc->typ)) {
		    You("kick the altar.");
		    if(!rn2(3)) goto ouch; 
#  ifdef THEOLOGY
		    altar_wrath(x, y);
#  endif
		    return(1);
		}
# endif
# ifdef SINKS
		if(IS_SINK(maploc->typ)) {
		    if(rn2(5)) {
			if(flags.soundok)
			    pline("Klunk!  The pipes vibrate noisily.");
			else pline("Klunk!");
		        return(1);
		    } else if(!rn2(3) &&
			      !(mons[PM_BLACK_PUDDING].geno & G_GENOD)) {
			pline("A %s ooze gushes up from the drain!",
			      Hallucination ? hcolor() : black);
			pmon(makemon(&mons[PM_BLACK_PUDDING], x, y));
			return(1);
#  ifdef INFERNO
		    } else if(!rn2(3) &&
#   ifndef POLYSELF
			      poly_gender() != 2 &&
#   endif
			      !(mons[poly_gender() == 1 ? PM_INCUBUS : PM_SUCCUBUS].geno & G_GENOD)) {
			/* can't resist... */
			pline("The dish washer returns!");
			pmon(makemon(&mons[poly_gender() == 1 ? PM_INCUBUS : PM_SUCCUBUS], x, y));
			return(1);
#  endif
		    } else if(!rn2(3)) {
			pline("Flupp!  Muddy waste pops up from the drain.");
			if(!maploc->looted) { /* only once per sink */
			    if(!Blind) 
				You("see a ring shining in its midst.");
			    (void) mkobj_at(RING_SYM, x, y);
			    prl(x, y);
			    maploc->looted = T_LOOTED;
			}
			return(1);
		    }
		    goto ouch;
		}
# endif
		if(maploc->typ == STAIRS 
# ifdef STRONGHOLD
					|| maploc->typ == LADDER
# endif
		  ) goto ouch;
		if(IS_STWALL(maploc->typ)) {
ouch:
		    pline("Ouch!  That hurts!");
		    if(!rn2(3)) set_wounded_legs(RIGHT_SIDE, 5 + rnd(5));
		    losehp(rnd(ACURR(A_CON) > 15 ? 3 : 5), kickstr(),
			KILLED_BY);
		    return(1);
		}
# ifdef STRONGHOLD
		if (is_drawbridge_wall(x,y) >= 0) {
		    pline("The drawbridge is unaffected.");
		    return(1);
		}
# endif
		goto dumb;
	}
#endif /* KICK */

	if(maploc->doormask == D_ISOPEN ||
	   maploc->doormask == D_BROKEN ||
	   maploc->doormask == D_NODOOR) {
#ifdef KICK
dumb:
#endif
		if (martial() || ACURR(A_DEX) >= 16 || rn2(3)) {
			You("kick at empty space.");
		} else {
			pline("Dumb move!  You strain a muscle.");
			set_wounded_legs(RIGHT_SIDE, 5 + rnd(5));
		}
		return(0);
	}

	/* door is known to be CLOSED or LOCKED */
	if(rnl(35) < avrg_attrib + (!martial() ? 0 : ACURR(A_DEX))) {
		/* break the door */
		if(maploc->doormask & D_TRAPPED) {
		    pline("As you kick the door, it explodes!");
		    b_trapped("door");
		    maploc->doormask = D_NODOOR;
		} else if(ACURR(A_STR) > 18 && !rn2(5) && !in_shop(x, y)) {
		    pline("As you kick the door, it shatters to pieces!");
		    maploc->doormask = D_NODOOR;
		} else {
		    pline("As you kick the door, it crashes open!");
		    maploc->doormask = D_BROKEN;
		    if(in_shop(x, y))
			pay_for_door(x, y, "break");
		}
		mnewsym(x,y);
		prl(x,y);
	} else	pline("WHAMMM!!!");

	return(1);
}

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