1/*	SCCS Id: @(#)dokick.c	3.4	2003/12/04	*/
2/* Copyright (c) Izchak Miller, Mike Stephenson, Steve Linhart, 1989. */
3/* NetHack may be freely redistributed.  See license for details. */
4
5#include "hack.h"
6#include "eshk.h"
7
8#define is_bigfoot(x)	((x) == &mons[PM_SASQUATCH])
9#define martial()	(martial_bonus() || is_bigfoot(youmonst.data) || \
10		(uarmf && uarmf->otyp == KICKING_BOOTS))
11
12static NEARDATA struct rm *maploc;
13static NEARDATA const char *gate_str;
14
15extern boolean notonhead;	/* for long worms */
16
17STATIC_DCL void FDECL(kickdmg, (struct monst *, BOOLEAN_P));
18STATIC_DCL void FDECL(kick_monster, (XCHAR_P, XCHAR_P));
19STATIC_DCL int FDECL(kick_object, (XCHAR_P, XCHAR_P));
20STATIC_DCL char *FDECL(kickstr, (char *));
21STATIC_DCL void FDECL(otransit_msg, (struct obj *, BOOLEAN_P, long));
22STATIC_DCL void FDECL(drop_to, (coord *,SCHAR_P));
23
24static NEARDATA struct obj *kickobj;
25
26static const char kick_passes_thru[] = "kick passes harmlessly through";
27
28STATIC_OVL void
29kickdmg(mon, clumsy)
30register struct monst *mon;
31register boolean clumsy;
32{
33	register int mdx, mdy;
34	register int dmg = ( ACURRSTR + ACURR(A_DEX) + ACURR(A_CON) )/ 15;
35	int kick_skill = P_NONE;
36	int blessed_foot_damage = 0;
37	boolean trapkilled = FALSE;
38
39	if (uarmf && uarmf->otyp == KICKING_BOOTS)
40	    dmg += 5;
41
42	/* excessive wt affects dex, so it affects dmg */
43	if (clumsy) dmg /= 2;
44
45	/* kicking a dragon or an elephant will not harm it */
46	if (thick_skinned(mon->data)) dmg = 0;
47
48	/* attacking a shade is useless */
49	if (mon->data == &mons[PM_SHADE])
50	    dmg = 0;
51
52	if ((is_undead(mon->data) || is_demon(mon->data)) && uarmf &&
53		uarmf->blessed)
54	    blessed_foot_damage = 1;
55
56	if (mon->data == &mons[PM_SHADE] && !blessed_foot_damage) {
57	    pline_The("%s.", kick_passes_thru);
58	    /* doesn't exercise skill or abuse alignment or frighten pet,
59	       and shades have no passive counterattack */
60	    return;
61	}
62
63	if(mon->m_ap_type) seemimic(mon);
64
65	check_caitiff(mon);
66
67	/* squeeze some guilt feelings... */
68	if(mon->mtame) {
69	    abuse_dog(mon);
70	    if (mon->mtame)
71		monflee(mon, (dmg ? rnd(dmg) : 1), FALSE, FALSE);
72	    else
73		mon->mflee = 0;
74	}
75
76	if (dmg > 0) {
77		/* convert potential damage to actual damage */
78		dmg = rnd(dmg);
79		if (martial()) {
80		    if (dmg > 1) kick_skill = P_MARTIAL_ARTS;
81		    dmg += rn2(ACURR(A_DEX)/2 + 1);
82		}
83		/* a good kick exercises your dex */
84		exercise(A_DEX, TRUE);
85	}
86	if (blessed_foot_damage) dmg += rnd(4);
87	if (uarmf) dmg += uarmf->spe;
88	dmg += u.udaminc;	/* add ring(s) of increase damage */
89	if (dmg > 0)
90		mon->mhp -= dmg;
91	if (mon->mhp > 0 && martial() && !bigmonst(mon->data) && !rn2(3) &&
92	    mon->mcanmove && mon != u.ustuck && !mon->mtrapped) {
93		/* see if the monster has a place to move into */
94		mdx = mon->mx + u.dx;
95		mdy = mon->my + u.dy;
96		if(goodpos(mdx, mdy, mon, 0)) {
97			pline("%s reels from the blow.", Monnam(mon));
98			if (m_in_out_region(mon, mdx, mdy)) {
99			    remove_monster(mon->mx, mon->my);
100			    newsym(mon->mx, mon->my);
101			    place_monster(mon, mdx, mdy);
102			    newsym(mon->mx, mon->my);
103			    set_apparxy(mon);
104			    if (mintrap(mon) == 2) trapkilled = TRUE;
105			}
106		}
107	}
108
109	(void) passive(mon, TRUE, mon->mhp > 0, AT_KICK);
110	if (mon->mhp <= 0 && !trapkilled) killed(mon);
111
112	/* may bring up a dialog, so put this after all messages */
113	if (kick_skill != P_NONE)	/* exercise proficiency */
114	    use_skill(kick_skill, 1);
115}
116
117STATIC_OVL void
118kick_monster(x, y)
119register xchar x, y;
120{
121	register boolean clumsy = FALSE;
122	register struct monst *mon = m_at(x, y);
123	register int i, j;
124
125	bhitpos.x = x;
126	bhitpos.y = y;
127	if (attack_checks(mon, (struct obj *)0)) return;
128	setmangry(mon);
129
130	/* Kick attacks by kicking monsters are normal attacks, not special.
131	 * This is almost always worthless, since you can either take one turn
132	 * and do all your kicks, or else take one turn and attack the monster
133	 * normally, getting all your attacks _including_ all your kicks.
134	 * If you have >1 kick attack, you get all of them.
135	 */
136	if (Upolyd && attacktype(youmonst.data, AT_KICK)) {
137	    struct attack *uattk;
138	    int sum;
139	    schar tmp = find_roll_to_hit(mon);
140
141	    for (i = 0; i < NATTK; i++) {
142		/* first of two kicks might have provoked counterattack
143		   that has incapacitated the hero (ie, floating eye) */
144		if (multi < 0) break;
145
146		uattk = &youmonst.data->mattk[i];
147		/* we only care about kicking attacks here */
148		if (uattk->aatyp != AT_KICK) continue;
149
150		if (mon->data == &mons[PM_SHADE] &&
151			(!uarmf || !uarmf->blessed)) {
152		    /* doesn't matter whether it would have hit or missed,
153		       and shades have no passive counterattack */
154		    Your("%s %s.", kick_passes_thru, mon_nam(mon));
155		    break;	/* skip any additional kicks */
156		} else if (tmp > rnd(20)) {
157		    You("kick %s.", mon_nam(mon));
158		    sum = damageum(mon, uattk);
159		    (void)passive(mon, (boolean)(sum > 0), (sum != 2), AT_KICK);
160		    if (sum == 2)
161			break;		/* Defender died */
162		} else {
163		    missum(mon, uattk);
164		    (void)passive(mon, 0, 1, AT_KICK);
165		}
166	    }
167	    return;
168	}
169
170	if(Levitation && !rn2(3) && verysmall(mon->data) &&
171	   !is_flyer(mon->data)) {
172		pline("Floating in the air, you miss wildly!");
173		exercise(A_DEX, FALSE);
174		(void) passive(mon, FALSE, 1, AT_KICK);
175		return;
176	}
177
178	i = -inv_weight();
179	j = weight_cap();
180
181	if(i < (j*3)/10) {
182		if(!rn2((i < j/10) ? 2 : (i < j/5) ? 3 : 4)) {
183			if(martial() && !rn2(2)) goto doit;
184			Your("clumsy kick does no damage.");
185			(void) passive(mon, FALSE, 1, AT_KICK);
186			return;
187		}
188		if(i < j/10) clumsy = TRUE;
189		else if(!rn2((i < j/5) ? 2 : 3)) clumsy = TRUE;
190	}
191
192	if(Fumbling) clumsy = TRUE;
193
194	else if(uarm && objects[uarm->otyp].oc_bulky && ACURR(A_DEX) < rnd(25))
195		clumsy = TRUE;
196doit:
197	You("kick %s.", mon_nam(mon));
198	if(!rn2(clumsy ? 3 : 4) && (clumsy || !bigmonst(mon->data)) &&
199	   mon->mcansee && !mon->mtrapped && !thick_skinned(mon->data) &&
200	   mon->data->mlet != S_EEL && haseyes(mon->data) && mon->mcanmove &&
201	   !mon->mstun && !mon->mconf && !mon->msleeping &&
202	   mon->data->mmove >= 12) {
203		if(!nohands(mon->data) && !rn2(martial() ? 5 : 3)) {
204		    pline("%s blocks your %skick.", Monnam(mon),
205				clumsy ? "clumsy " : "");
206		    (void) passive(mon, FALSE, 1, AT_KICK);
207		    return;
208		} else {
209		    mnexto(mon);
210		    if(mon->mx != x || mon->my != y) {
211			if(glyph_is_invisible(levl[x][y].glyph)) {
212			    unmap_object(x, y);
213			    newsym(x, y);
214			}
215			pline("%s %s, %s evading your %skick.", Monnam(mon),
216				(can_teleport(mon->data) ? "teleports" :
217				 is_floater(mon->data) ? "floats" :
218				 is_flyer(mon->data) ? "swoops" :
219				 (nolimbs(mon->data) || slithy(mon->data)) ?
220					"slides" : "jumps"),
221				clumsy ? "easily" : "nimbly",
222				clumsy ? "clumsy " : "");
223			(void) passive(mon, FALSE, 1, AT_KICK);
224			return;
225		    }
226		}
227	}
228	kickdmg(mon, clumsy);
229}
230
231/*
232 *  Return TRUE if caught (the gold taken care of), FALSE otherwise.
233 *  The gold object is *not* attached to the fobj chain!
234 */
235boolean
236ghitm(mtmp, gold)
237register struct monst *mtmp;
238register struct obj *gold;
239{
240	boolean msg_given = FALSE;
241
242	if(!likes_gold(mtmp->data) && !mtmp->isshk && !mtmp->ispriest
243			&& !is_mercenary(mtmp->data)) {
244		wakeup(mtmp);
245	} else if (!mtmp->mcanmove) {
246		/* too light to do real damage */
247		if (canseemon(mtmp)) {
248		    pline_The("%s harmlessly %s %s.", xname(gold),
249			      otense(gold, "hit"), mon_nam(mtmp));
250		    msg_given = TRUE;
251		}
252	} else {
253#ifdef GOLDOBJ
254                long value = gold->quan * objects[gold->otyp].oc_cost;
255#endif
256		mtmp->msleeping = 0;
257		mtmp->meating = 0;
258		if(!rn2(4)) setmangry(mtmp); /* not always pleasing */
259
260		/* greedy monsters catch gold */
261		if (cansee(mtmp->mx, mtmp->my))
262		    pline("%s catches the gold.", Monnam(mtmp));
263#ifndef GOLDOBJ
264		mtmp->mgold += gold->quan;
265#endif
266		if (mtmp->isshk) {
267			long robbed = ESHK(mtmp)->robbed;
268
269			if (robbed) {
270#ifndef GOLDOBJ
271				robbed -= gold->quan;
272#else
273				robbed -= value;
274#endif
275				if (robbed < 0) robbed = 0;
276				pline_The("amount %scovers %s recent losses.",
277				      !robbed ? "" : "partially ",
278				      mhis(mtmp));
279				ESHK(mtmp)->robbed = robbed;
280				if(!robbed)
281					make_happy_shk(mtmp, FALSE);
282			} else {
283				if(mtmp->mpeaceful) {
284#ifndef GOLDOBJ
285				    ESHK(mtmp)->credit += gold->quan;
286#else
287				    ESHK(mtmp)->credit += value;
288#endif
289				    You("have %ld %s in credit.",
290					ESHK(mtmp)->credit,
291					currency(ESHK(mtmp)->credit));
292				} else verbalize("Thanks, scum!");
293			}
294		} else if (mtmp->ispriest) {
295			if (mtmp->mpeaceful)
296			    verbalize("Thank you for your contribution.");
297			else verbalize("Thanks, scum!");
298		} else if (is_mercenary(mtmp->data)) {
299		    long goldreqd = 0L;
300
301		    if (rn2(3)) {
302			if (mtmp->data == &mons[PM_SOLDIER])
303			   goldreqd = 100L;
304			else if (mtmp->data == &mons[PM_SERGEANT])
305			   goldreqd = 250L;
306			else if (mtmp->data == &mons[PM_LIEUTENANT])
307			   goldreqd = 500L;
308			else if (mtmp->data == &mons[PM_CAPTAIN])
309			   goldreqd = 750L;
310
311			if (goldreqd) {
312#ifndef GOLDOBJ
313			   if (gold->quan > goldreqd +
314				(u.ugold + u.ulevel*rn2(5))/ACURR(A_CHA))
315#else
316			   if (value > goldreqd +
317				(money_cnt(invent) + u.ulevel*rn2(5))/ACURR(A_CHA))
318#endif
319			    mtmp->mpeaceful = TRUE;
320			}
321		     }
322		     if (mtmp->mpeaceful)
323			    verbalize("That should do.  Now beat it!");
324		     else verbalize("That's not enough, coward!");
325		}
326
327#ifndef GOLDOBJ
328		dealloc_obj(gold);
329#else
330		add_to_minv(mtmp, gold);
331#endif
332		return TRUE;
333	}
334
335	if (!msg_given) miss(xname(gold), mtmp);
336	return FALSE;
337}
338
339/* container is kicked, dropped, thrown or otherwise impacted by player.
340 * Assumes container is on floor.  Checks contents for possible damage. */
341void
342container_impact_dmg(obj)
343struct obj *obj;
344{
345	struct monst *shkp;
346	struct obj *otmp, *otmp2;
347	long loss = 0L;
348	boolean costly, insider;
349	xchar x = obj->ox, y = obj->oy;
350
351	/* only consider normal containers */
352	if (!Is_container(obj) || Is_mbag(obj)) return;
353
354	costly = ((shkp = shop_keeper(*in_rooms(x, y, SHOPBASE))) &&
355		  costly_spot(x, y));
356	insider = (*u.ushops && inside_shop(u.ux, u.uy) &&
357		   *in_rooms(x, y, SHOPBASE) == *u.ushops);
358
359	for (otmp = obj->cobj; otmp; otmp = otmp2) {
360	    const char *result = (char *)0;
361
362	    otmp2 = otmp->nobj;
363	    if (objects[otmp->otyp].oc_material == GLASS &&
364		otmp->oclass != GEM_CLASS && !obj_resists(otmp, 33, 100)) {
365		result = "shatter";
366	    } else if (otmp->otyp == EGG && !rn2(3)) {
367		result = "cracking";
368	    }
369	    if (result) {
370		if (otmp->otyp == MIRROR) change_luck(-2);
371
372		/* eggs laid by you.  penalty is -1 per egg, max 5,
373		 * but it's always exactly 1 that breaks */
374		if (otmp->otyp == EGG && otmp->spe && otmp->corpsenm >= LOW_PM)
375		    change_luck(-1);
376		You_hear("a muffled %s.", result);
377		if (costly)
378		    loss += stolen_value(otmp, x, y,
379					 (boolean)shkp->mpeaceful, TRUE);
380		if (otmp->quan > 1L)
381		    useup(otmp);
382		else {
383		    obj_extract_self(otmp);
384		    obfree(otmp, (struct obj *) 0);
385		}
386	    }
387	}
388	if (costly && loss) {
389	    if (!insider) {
390		You("caused %ld %s worth of damage!", loss, currency(loss));
391		make_angry_shk(shkp, x, y);
392	    } else {
393		You("owe %s %ld %s for objects destroyed.",
394		    mon_nam(shkp), loss, currency(loss));
395	    }
396	}
397}
398
399STATIC_OVL int
400kick_object(x, y)
401xchar x, y;
402{
403	int range;
404	register struct monst *mon, *shkp;
405	struct trap *trap;
406	char bhitroom;
407	boolean costly, isgold, slide = FALSE;
408
409	/* if a pile, the "top" object gets kicked */
410	kickobj = level.objects[x][y];
411
412	/* kickobj should always be set due to conditions of call */
413	if(!kickobj || kickobj->otyp == BOULDER
414			|| kickobj == uball || kickobj == uchain)
415		return(0);
416
417	if ((trap = t_at(x,y)) != 0 &&
418			(((trap->ttyp == PIT ||
419			   trap->ttyp == SPIKED_PIT) && !Passes_walls) ||
420			 trap->ttyp == WEB)) {
421		if (!trap->tseen) find_trap(trap);
422		You_cant("kick %s that's in a %s!", something,
423			 Hallucination ? "tizzy" :
424			 (trap->ttyp == WEB) ? "web" : "pit");
425		return 1;
426	}
427
428	if(Fumbling && !rn2(3)) {
429		Your("clumsy kick missed.");
430		return(1);
431	}
432
433	if(kickobj->otyp == CORPSE && touch_petrifies(&mons[kickobj->corpsenm])
434			&& !Stone_resistance && !uarmf) {
435	    char kbuf[BUFSZ];
436
437	    You("kick the %s with your bare %s.",
438		corpse_xname(kickobj, TRUE), makeplural(body_part(FOOT)));
439	    if (!(poly_when_stoned(youmonst.data) && polymon(PM_STONE_GOLEM))) {
440		You("turn to stone...");
441		killer_format = KILLED_BY;
442		/* KMH -- otmp should be kickobj */
443		Sprintf(kbuf, "kicking %s without boots",
444			an(corpse_xname(kickobj, TRUE)));
445		killer = kbuf;
446		done(STONING);
447	    }
448	}
449
450	/* range < 2 means the object will not move.	*/
451	/* maybe dexterity should also figure here.     */
452	range = (int)((ACURRSTR)/2 - kickobj->owt/40);
453
454	if(martial()) range += rnd(3);
455
456	if (is_pool(x, y)) {
457	    /* you're in the water too; significantly reduce range */
458	    range = range / 3 + 1;	/* {1,2}=>1, {3,4,5}=>2, {6,7,8}=>3 */
459	} else {
460	    if (is_ice(x, y)) range += rnd(3),  slide = TRUE;
461	    if (kickobj->greased) range += rnd(3),  slide = TRUE;
462	}
463
464	/* Mjollnir is magically too heavy to kick */
465	if(kickobj->oartifact == ART_MJOLLNIR) range = 1;
466
467	/* see if the object has a place to move into */
468	if(!ZAP_POS(levl[x+u.dx][y+u.dy].typ) || closed_door(x+u.dx, y+u.dy))
469		range = 1;
470
471	costly = ((shkp = shop_keeper(*in_rooms(x, y, SHOPBASE))) &&
472				    costly_spot(x, y));
473	isgold = (kickobj->oclass == COIN_CLASS);
474
475	if (IS_ROCK(levl[x][y].typ) || closed_door(x, y)) {
476	    if ((!martial() && rn2(20) > ACURR(A_DEX)) ||
477		    IS_ROCK(levl[u.ux][u.uy].typ) || closed_door(u.ux, u.uy)) {
478		if (Blind)
479		    pline("It doesn't come loose.");
480		else
481		    pline("%s %sn't come loose.",
482			  The(distant_name(kickobj, xname)),
483			  otense(kickobj, "do"));
484		return (!rn2(3) || martial());
485	    }
486	    if (Blind)
487		pline("It comes loose.");
488	    else
489		pline("%s %s loose.",
490		      The(distant_name(kickobj, xname)),
491		      otense(kickobj, "come"));
492	    obj_extract_self(kickobj);
493	    newsym(x, y);
494	    if (costly && (!costly_spot(u.ux, u.uy) ||
495		    !index(u.urooms, *in_rooms(x, y, SHOPBASE))))
496		addtobill(kickobj, FALSE, FALSE, FALSE);
497	    if (!flooreffects(kickobj, u.ux, u.uy, "fall")) {
498		place_object(kickobj, u.ux, u.uy);
499		stackobj(kickobj);
500		newsym(u.ux, u.uy);
501	    }
502	    return 1;
503	}
504
505	/* a box gets a chance of breaking open here */
506	if(Is_box(kickobj)) {
507		boolean otrp = kickobj->otrapped;
508
509		if(range < 2) pline("THUD!");
510
511		container_impact_dmg(kickobj);
512
513		if (kickobj->olocked) {
514		    if (!rn2(5) || (martial() && !rn2(2))) {
515			You("break open the lock!");
516			kickobj->olocked = 0;
517			kickobj->obroken = 1;
518			if (otrp) (void) chest_trap(kickobj, LEG, FALSE);
519			return(1);
520		    }
521		} else {
522		    if (!rn2(3) || (martial() && !rn2(2))) {
523			pline_The("lid slams open, then falls shut.");
524			if (otrp) (void) chest_trap(kickobj, LEG, FALSE);
525			return(1);
526		    }
527		}
528		if(range < 2) return(1);
529		/* else let it fall through to the next cases... */
530	}
531
532	/* fragile objects should not be kicked */
533	if (hero_breaks(kickobj, kickobj->ox, kickobj->oy, FALSE)) return 1;
534
535	/* too heavy to move.  range is calculated as potential distance from
536	 * player, so range == 2 means the object may move up to one square
537	 * from its current position
538	 */
539	if(range < 2 || (isgold && kickobj->quan > 300L)) {
540	    if(!Is_box(kickobj)) pline("Thump!");
541	    return(!rn2(3) || martial());
542	}
543
544	if (kickobj->quan > 1L && !isgold) kickobj = splitobj(kickobj, 1L);
545
546	if (slide && !Blind)
547	    pline("Whee!  %s %s across the %s.", Doname2(kickobj),
548		  otense(kickobj, "slide"), surface(x,y));
549
550	obj_extract_self(kickobj);
551	(void) snuff_candle(kickobj);
552	newsym(x, y);
553	mon = bhit(u.dx, u.dy, range, KICKED_WEAPON,
554		   (int FDECL((*),(MONST_P,OBJ_P)))0,
555		   (int FDECL((*),(OBJ_P,OBJ_P)))0,
556		   kickobj);
557
558	if(mon) {
559	    if (mon->isshk &&
560		    kickobj->where == OBJ_MINVENT && kickobj->ocarry == mon)
561		return 1;	/* alert shk caught it */
562	    notonhead = (mon->mx != bhitpos.x || mon->my != bhitpos.y);
563	    if (isgold ? ghitm(mon, kickobj) :	/* caught? */
564		    thitmonst(mon, kickobj))	/* hit && used up? */
565		return(1);
566	}
567
568	/* the object might have fallen down a hole */
569	if (kickobj->where == OBJ_MIGRATING) {
570	    if (costly) {
571		if(isgold)
572		    costly_gold(x, y, kickobj->quan);
573		else (void)stolen_value(kickobj, x, y,
574					(boolean)shkp->mpeaceful, FALSE);
575	    }
576	    return 1;
577	}
578
579	bhitroom = *in_rooms(bhitpos.x, bhitpos.y, SHOPBASE);
580	if (costly && (!costly_spot(bhitpos.x, bhitpos.y) ||
581			*in_rooms(x, y, SHOPBASE) != bhitroom)) {
582	    if(isgold)
583		costly_gold(x, y, kickobj->quan);
584	    else (void)stolen_value(kickobj, x, y,
585				    (boolean)shkp->mpeaceful, FALSE);
586	}
587
588	if(flooreffects(kickobj,bhitpos.x,bhitpos.y,"fall")) return(1);
589	place_object(kickobj, bhitpos.x, bhitpos.y);
590	stackobj(kickobj);
591	newsym(kickobj->ox, kickobj->oy);
592	return(1);
593}
594
595STATIC_OVL char *
596kickstr(buf)
597char *buf;
598{
599	const char *what;
600
601	if (kickobj) what = distant_name(kickobj,doname);
602	else if (IS_DOOR(maploc->typ)) what = "a door";
603	else if (IS_TREE(maploc->typ)) what = "a tree";
604	else if (IS_STWALL(maploc->typ)) what = "a wall";
605	else if (IS_ROCK(maploc->typ)) what = "a rock";
606	else if (IS_THRONE(maploc->typ)) what = "a throne";
607	else if (IS_FOUNTAIN(maploc->typ)) what = "a fountain";
608	else if (IS_GRAVE(maploc->typ)) what = "a headstone";
609#ifdef SINKS
610	else if (IS_SINK(maploc->typ)) what = "a sink";
611#endif
612	else if (IS_ALTAR(maploc->typ)) what = "an altar";
613	else if (IS_DRAWBRIDGE(maploc->typ)) what = "a drawbridge";
614	else if (maploc->typ == STAIRS) what = "the stairs";
615	else if (maploc->typ == LADDER) what = "a ladder";
616	else if (maploc->typ == IRONBARS) what = "an iron bar";
617	else what = "something weird";
618	return strcat(strcpy(buf, "kicking "), what);
619}
620
621int
622dokick()
623{
624	int x, y;
625	int avrg_attrib;
626	register struct monst *mtmp;
627	boolean no_kick = FALSE;
628	char buf[BUFSZ];
629
630	if (nolimbs(youmonst.data) || slithy(youmonst.data)) {
631		You("have no legs to kick with.");
632		no_kick = TRUE;
633	} else if (verysmall(youmonst.data)) {
634		You("are too small to do any kicking.");
635		no_kick = TRUE;
636#ifdef STEED
637	} else if (u.usteed) {
638		if (yn_function("Kick your steed?", ynchars, 'y') == 'y') {
639		    You("kick %s.", mon_nam(u.usteed));
640		    kick_steed();
641		    return 1;
642		} else {
643		    return 0;
644		}
645#endif
646	} else if (Wounded_legs) {
647		/* note: jump() has similar code */
648		long wl = (EWounded_legs & BOTH_SIDES);
649		const char *bp = body_part(LEG);
650
651		if (wl == BOTH_SIDES) bp = makeplural(bp);
652		Your("%s%s %s in no shape for kicking.",
653		     (wl == LEFT_SIDE) ? "left " :
654			(wl == RIGHT_SIDE) ? "right " : "",
655		     bp, (wl == BOTH_SIDES) ? "are" : "is");
656		no_kick = TRUE;
657	} else if (near_capacity() > SLT_ENCUMBER) {
658		Your("load is too heavy to balance yourself for a kick.");
659		no_kick = TRUE;
660	} else if (youmonst.data->mlet == S_LIZARD) {
661		Your("legs cannot kick effectively.");
662		no_kick = TRUE;
663	} else if (u.uinwater && !rn2(2)) {
664		Your("slow motion kick doesn't hit anything.");
665		no_kick = TRUE;
666	} else if (u.utrap) {
667		switch (u.utraptype) {
668		    case TT_PIT:
669			pline("There's not enough room to kick down here.");
670			break;
671		    case TT_WEB:
672		    case TT_BEARTRAP:
673			You_cant("move your %s!", body_part(LEG));
674			break;
675		    default:
676			break;
677		}
678		no_kick = TRUE;
679	}
680
681	if (no_kick) {
682		/* ignore direction typed before player notices kick failed */
683		display_nhwindow(WIN_MESSAGE, TRUE);	/* --More-- */
684		return 0;
685	}
686
687	if(!getdir((char *)0)) return(0);
688	if(!u.dx && !u.dy) return(0);
689
690	x = u.ux + u.dx;
691	y = u.uy + u.dy;
692
693	/* KMH -- Kicking boots always succeed */
694	if (uarmf && uarmf->otyp == KICKING_BOOTS)
695	    avrg_attrib = 99;
696	else
697	    avrg_attrib = (ACURRSTR+ACURR(A_DEX)+ACURR(A_CON))/3;
698
699	if(u.uswallow) {
700		switch(rn2(3)) {
701		case 0:  You_cant("move your %s!", body_part(LEG));
702			 break;
703		case 1:  if (is_animal(u.ustuck->data)) {
704				pline("%s burps loudly.", Monnam(u.ustuck));
705				break;
706			 }
707		default: Your("feeble kick has no effect."); break;
708		}
709		return(1);
710	}
711	if (Levitation) {
712		int xx, yy;
713
714		xx = u.ux - u.dx;
715		yy = u.uy - u.dy;
716		/* doors can be opened while levitating, so they must be
717		 * reachable for bracing purposes
718		 * Possible extension: allow bracing against stuff on the side?
719		 */
720		if (isok(xx,yy) && !IS_ROCK(levl[xx][yy].typ) &&
721			!IS_DOOR(levl[xx][yy].typ) &&
722			(!Is_airlevel(&u.uz) || !OBJ_AT(xx,yy))) {
723		    You("have nothing to brace yourself against.");
724		    return(0);
725		}
726	}
727
728	wake_nearby();
729	u_wipe_engr(2);
730
731	maploc = &levl[x][y];
732
733	/* The next five tests should stay in    */
734	/* their present order: monsters, pools, */
735	/* objects, non-doors, doors.		 */
736
737	if(MON_AT(x, y)) {
738		struct permonst *mdat;
739
740		mtmp = m_at(x, y);
741		mdat = mtmp->data;
742		if (!mtmp->mpeaceful || !canspotmon(mtmp))
743		    flags.forcefight = TRUE; /* attack even if invisible */
744		kick_monster(x, y);
745		flags.forcefight = FALSE;
746		/* see comment in attack_checks() */
747		if (!DEADMONSTER(mtmp) &&
748		    !canspotmon(mtmp) &&
749		    /* check x and y; a monster that evades your kick by
750		       jumping to an unseen square doesn't leave an I behind */
751		    mtmp->mx == x && mtmp->my == y &&
752		    !glyph_is_invisible(levl[x][y].glyph) &&
753		    !(u.uswallow && mtmp == u.ustuck))
754			map_invisible(x, y);
755		if((Is_airlevel(&u.uz) || Levitation) && flags.move) {
756		    int range;
757
758		    range = ((int)youmonst.data->cwt + (weight_cap() + inv_weight()));
759		    if (range < 1) range = 1; /* divide by zero avoidance */
760		    range = (3*(int)mdat->cwt) / range;
761
762		    if(range < 1) range = 1;
763		    hurtle(-u.dx, -u.dy, range, TRUE);
764		}
765		return(1);
766	}
767	if (glyph_is_invisible(levl[x][y].glyph)) {
768		unmap_object(x, y);
769		newsym(x, y);
770	}
771	if (is_pool(x, y) ^ !!u.uinwater) {
772		/* objects normally can't be removed from water by kicking */
773		You("splash some water around.");
774		return 1;
775	}
776
777	kickobj = (struct obj *)0;
778	if (OBJ_AT(x, y) &&
779	    (!Levitation || Is_airlevel(&u.uz) || Is_waterlevel(&u.uz)
780	     || sobj_at(BOULDER,x,y))) {
781		if(kick_object(x, y)) {
782		    if(Is_airlevel(&u.uz))
783			hurtle(-u.dx, -u.dy, 1, TRUE); /* assume it's light */
784		    return(1);
785		}
786		goto ouch;
787	}
788
789	if(!IS_DOOR(maploc->typ)) {
790		if(maploc->typ == SDOOR) {
791		    if(!Levitation && rn2(30) < avrg_attrib) {
792			cvt_sdoor_to_door(maploc);	/* ->typ = DOOR */
793			pline("Crash!  %s a secret door!",
794			      /* don't "kick open" when it's locked
795				 unless it also happens to be trapped */
796			(maploc->doormask & (D_LOCKED|D_TRAPPED)) == D_LOCKED ?
797			      "Your kick uncovers" : "You kick open");
798			exercise(A_DEX, TRUE);
799			if(maploc->doormask & D_TRAPPED) {
800			    maploc->doormask = D_NODOOR;
801			    b_trapped("door", FOOT);
802			} else if (maploc->doormask != D_NODOOR &&
803				   !(maploc->doormask & D_LOCKED))
804			    maploc->doormask = D_ISOPEN;
805			if (Blind)
806			    feel_location(x,y);	/* we know it's gone */
807			else
808			    newsym(x,y);
809			if (maploc->doormask == D_ISOPEN ||
810			    maploc->doormask == D_NODOOR)
811			    unblock_point(x,y);	/* vision */
812			return(1);
813		    } else goto ouch;
814		}
815		if(maploc->typ == SCORR) {
816		    if(!Levitation && rn2(30) < avrg_attrib) {
817			pline("Crash!  You kick open a secret passage!");
818			exercise(A_DEX, TRUE);
819			maploc->typ = CORR;
820			if (Blind)
821			    feel_location(x,y);	/* we know it's gone */
822			else
823			    newsym(x,y);
824			unblock_point(x,y);	/* vision */
825			return(1);
826		    } else goto ouch;
827		}
828		if(IS_THRONE(maploc->typ)) {
829		    register int i;
830		    if(Levitation) goto dumb;
831		    if((Luck < 0 || maploc->doormask) && !rn2(3)) {
832			maploc->typ = ROOM;
833			maploc->doormask = 0; /* don't leave loose ends.. */
834			(void) mkgold((long)rnd(200), x, y);
835			if (Blind)
836			    pline("CRASH!  You destroy it.");
837			else {
838			    pline("CRASH!  You destroy the throne.");
839			    newsym(x, y);
840			}
841			exercise(A_DEX, TRUE);
842			return(1);
843		    } else if(Luck > 0 && !rn2(3) && !maploc->looted) {
844			(void) mkgold((long) rn1(201, 300), x, y);
845			i = Luck + 1;
846			if(i > 6) i = 6;
847			while(i--)
848			    (void) mksobj_at(rnd_class(DILITHIUM_CRYSTAL,
849					LUCKSTONE-1), x, y, FALSE, TRUE);
850			if (Blind)
851			    You("kick %s loose!", something);
852			else {
853			    You("kick loose some ornamental coins and gems!");
854			    newsym(x, y);
855			}
856			/* prevent endless milking */
857			maploc->looted = T_LOOTED;
858			return(1);
859		    } else if (!rn2(4)) {
860			if(dunlev(&u.uz) < dunlevs_in_dungeon(&u.uz)) {
861			    fall_through(FALSE);
862			    return(1);
863			} else goto ouch;
864		    }
865		    goto ouch;
866		}
867		if(IS_ALTAR(maploc->typ)) {
868		    if(Levitation) goto dumb;
869		    You("kick %s.",(Blind ? something : "the altar"));
870		    if(!rn2(3)) goto ouch;
871		    altar_wrath(x, y);
872		    exercise(A_DEX, TRUE);
873		    return(1);
874		}
875		if(IS_FOUNTAIN(maploc->typ)) {
876		    if(Levitation) goto dumb;
877		    You("kick %s.",(Blind ? something : "the fountain"));
878		    if(!rn2(3)) goto ouch;
879		    /* make metal boots rust */
880		    if(uarmf && rn2(3))
881			if (!rust_dmg(uarmf, "metal boots", 1, FALSE, &youmonst)) {
882				Your("boots get wet.");
883				/* could cause short-lived fumbling here */
884			}
885		    exercise(A_DEX, TRUE);
886		    return(1);
887		}
888		if(IS_GRAVE(maploc->typ) || maploc->typ == IRONBARS)
889		    goto ouch;
890		if(IS_TREE(maploc->typ)) {
891		    struct obj *treefruit;
892		    /* nothing, fruit or trouble? 75:23.5:1.5% */
893		    if (rn2(3)) {
894			if ( !rn2(6) && !(mvitals[PM_KILLER_BEE].mvflags & G_GONE) )
895			    You_hear("a low buzzing."); /* a warning */
896			goto ouch;
897		    }
898		    if (rn2(15) && !(maploc->looted & TREE_LOOTED) &&
899			  (treefruit = rnd_treefruit_at(x, y))) {
900			long nfruit = 8L-rnl(7), nfall;
901			short frtype = treefruit->otyp;
902			treefruit->quan = nfruit;
903			if (is_plural(treefruit))
904			    pline("Some %s fall from the tree!", xname(treefruit));
905			else
906			    pline("%s falls from the tree!", An(xname(treefruit)));
907			nfall = scatter(x,y,2,MAY_HIT,treefruit);
908			if (nfall != nfruit) {
909			    /* scatter left some in the tree, but treefruit
910			     * may not refer to the correct object */
911			    treefruit = mksobj(frtype, TRUE, FALSE);
912			    treefruit->quan = nfruit-nfall;
913			    pline("%ld %s got caught in the branches.",
914				nfruit-nfall, xname(treefruit));
915			    dealloc_obj(treefruit);
916			}
917			exercise(A_DEX, TRUE);
918			exercise(A_WIS, TRUE);	/* discovered a new food source! */
919			newsym(x, y);
920			maploc->looted |= TREE_LOOTED;
921			return(1);
922		    } else if (!(maploc->looted & TREE_SWARM)) {
923		    	int cnt = rnl(4) + 2;
924			int made = 0;
925		    	coord mm;
926		    	mm.x = x; mm.y = y;
927			while (cnt--) {
928			    if (enexto(&mm, mm.x, mm.y, &mons[PM_KILLER_BEE])
929				&& makemon(&mons[PM_KILLER_BEE],
930					       mm.x, mm.y, MM_ANGRY))
931				made++;
932			}
933			if ( made )
934			    pline("You've attracted the tree's former occupants!");
935			else
936			    You("smell stale honey.");
937			maploc->looted |= TREE_SWARM;
938			return(1);
939		    }
940		    goto ouch;
941		}
942#ifdef SINKS
943		if(IS_SINK(maploc->typ)) {
944		    int gend = poly_gender();
945		    short washerndx = (gend == 1 || (gend == 2 && rn2(2))) ?
946					PM_INCUBUS : PM_SUCCUBUS;
947
948		    if(Levitation) goto dumb;
949		    if(rn2(5)) {
950			if(flags.soundok)
951			    pline("Klunk!  The pipes vibrate noisily.");
952			else pline("Klunk!");
953			exercise(A_DEX, TRUE);
954			return(1);
955		    } else if(!(maploc->looted & S_LPUDDING) && !rn2(3) &&
956			  !(mvitals[PM_BLACK_PUDDING].mvflags & G_GONE)) {
957			if (Blind)
958			    You_hear("a gushing sound.");
959			else
960			    pline("A %s ooze gushes up from the drain!",
961					 hcolor(NH_BLACK));
962			(void) makemon(&mons[PM_BLACK_PUDDING],
963					 x, y, NO_MM_FLAGS);
964			exercise(A_DEX, TRUE);
965			newsym(x,y);
966			maploc->looted |= S_LPUDDING;
967			return(1);
968		    } else if(!(maploc->looted & S_LDWASHER) && !rn2(3) &&
969			      !(mvitals[washerndx].mvflags & G_GONE)) {
970			/* can't resist... */
971			pline("%s returns!", (Blind ? Something :
972							"The dish washer"));
973			if (makemon(&mons[washerndx], x, y, NO_MM_FLAGS))
974			    newsym(x,y);
975			maploc->looted |= S_LDWASHER;
976			exercise(A_DEX, TRUE);
977			return(1);
978		    } else if(!rn2(3)) {
979			pline("Flupp!  %s.", (Blind ?
980				      "You hear a sloshing sound" :
981				      "Muddy waste pops up from the drain"));
982			if(!(maploc->looted & S_LRING)) { /* once per sink */
983			    if (!Blind)
984				You("see a ring shining in its midst.");
985			    (void) mkobj_at(RING_CLASS, x, y, TRUE);
986			    newsym(x, y);
987			    exercise(A_DEX, TRUE);
988			    exercise(A_WIS, TRUE);	/* a discovery! */
989			    maploc->looted |= S_LRING;
990			}
991			return(1);
992		    }
993		    goto ouch;
994		}
995#endif
996		if (maploc->typ == STAIRS || maploc->typ == LADDER ||
997						    IS_STWALL(maploc->typ)) {
998		    if(!IS_STWALL(maploc->typ) && maploc->ladder == LA_DOWN)
999			goto dumb;
1000ouch:
1001		    pline("Ouch!  That hurts!");
1002		    exercise(A_DEX, FALSE);
1003		    exercise(A_STR, FALSE);
1004		    if (Blind) feel_location(x,y); /* we know we hit it */
1005		    if (is_drawbridge_wall(x,y) >= 0) {
1006			pline_The("drawbridge is unaffected.");
1007			/* update maploc to refer to the drawbridge */
1008			(void) find_drawbridge(&x,&y);
1009			maploc = &levl[x][y];
1010		    }
1011		    if(!rn2(3)) set_wounded_legs(RIGHT_SIDE, 5 + rnd(5));
1012		    losehp(rnd(ACURR(A_CON) > 15 ? 3 : 5), kickstr(buf),
1013			KILLED_BY);
1014		    if(Is_airlevel(&u.uz) || Levitation)
1015			hurtle(-u.dx, -u.dy, rn1(2,4), TRUE); /* assume it's heavy */
1016		    return(1);
1017		}
1018		goto dumb;
1019	}
1020
1021	if(maploc->doormask == D_ISOPEN ||
1022	   maploc->doormask == D_BROKEN ||
1023	   maploc->doormask == D_NODOOR) {
1024dumb:
1025		exercise(A_DEX, FALSE);
1026		if (martial() || ACURR(A_DEX) >= 16 || rn2(3)) {
1027			You("kick at empty space.");
1028			if (Blind) feel_location(x,y);
1029		} else {
1030			pline("Dumb move!  You strain a muscle.");
1031			exercise(A_STR, FALSE);
1032			set_wounded_legs(RIGHT_SIDE, 5 + rnd(5));
1033		}
1034		if ((Is_airlevel(&u.uz) || Levitation) && rn2(2)) {
1035		    hurtle(-u.dx, -u.dy, 1, TRUE);
1036		    return 1;		/* you moved, so use up a turn */
1037		}
1038		return(0);
1039	}
1040
1041	/* not enough leverage to kick open doors while levitating */
1042	if(Levitation) goto ouch;
1043
1044	exercise(A_DEX, TRUE);
1045	/* door is known to be CLOSED or LOCKED */
1046	if(rnl(35) < avrg_attrib + (!martial() ? 0 : ACURR(A_DEX))) {
1047		boolean shopdoor = *in_rooms(x, y, SHOPBASE) ? TRUE : FALSE;
1048		/* break the door */
1049		if(maploc->doormask & D_TRAPPED) {
1050		    if (flags.verbose) You("kick the door.");
1051		    exercise(A_STR, FALSE);
1052		    maploc->doormask = D_NODOOR;
1053		    b_trapped("door", FOOT);
1054		} else if(ACURR(A_STR) > 18 && !rn2(5) && !shopdoor) {
1055		    pline("As you kick the door, it shatters to pieces!");
1056		    exercise(A_STR, TRUE);
1057		    maploc->doormask = D_NODOOR;
1058		} else {
1059		    pline("As you kick the door, it crashes open!");
1060		    exercise(A_STR, TRUE);
1061		    maploc->doormask = D_BROKEN;
1062		}
1063		if (Blind)
1064		    feel_location(x,y);		/* we know we broke it */
1065		else
1066		    newsym(x,y);
1067		unblock_point(x,y);		/* vision */
1068		if (shopdoor) {
1069		    add_damage(x, y, 400L);
1070		    pay_for_damage("break", FALSE);
1071		}
1072		if (in_town(x, y))
1073		  for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
1074		    if (DEADMONSTER(mtmp)) continue;
1075		    if((mtmp->data == &mons[PM_WATCHMAN] ||
1076			mtmp->data == &mons[PM_WATCH_CAPTAIN]) &&
1077			couldsee(mtmp->mx, mtmp->my) &&
1078			mtmp->mpeaceful) {
1079			if (canspotmon(mtmp))
1080			    pline("%s yells:", Amonnam(mtmp));
1081			else
1082			    You_hear("someone yell:");
1083			verbalize("Halt, thief!  You're under arrest!");
1084			(void) angry_guards(FALSE);
1085			break;
1086		    }
1087		  }
1088	} else {
1089	    if (Blind) feel_location(x,y);	/* we know we hit it */
1090	    exercise(A_STR, TRUE);
1091	    pline("WHAMMM!!!");
1092	    if (in_town(x, y))
1093		for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
1094		    if (DEADMONSTER(mtmp)) continue;
1095		    if ((mtmp->data == &mons[PM_WATCHMAN] ||
1096				mtmp->data == &mons[PM_WATCH_CAPTAIN]) &&
1097			    mtmp->mpeaceful && couldsee(mtmp->mx, mtmp->my)) {
1098			if (canspotmon(mtmp))
1099			    pline("%s yells:", Amonnam(mtmp));
1100			else
1101			    You_hear("someone yell:");
1102			if(levl[x][y].looted & D_WARNED) {
1103			    verbalize("Halt, vandal!  You're under arrest!");
1104			    (void) angry_guards(FALSE);
1105			} else {
1106			    verbalize("Hey, stop damaging that door!");
1107			    levl[x][y].looted |= D_WARNED;
1108			}
1109			break;
1110		    }
1111		}
1112	}
1113	return(1);
1114}
1115
1116STATIC_OVL void
1117drop_to(cc, loc)
1118coord *cc;
1119schar loc;
1120{
1121	/* cover all the MIGR_xxx choices generated by down_gate() */
1122	switch (loc) {
1123	 case MIGR_RANDOM:	/* trap door or hole */
1124		    if (Is_stronghold(&u.uz)) {
1125			cc->x = valley_level.dnum;
1126			cc->y = valley_level.dlevel;
1127			break;
1128		    } else if (In_endgame(&u.uz) || Is_botlevel(&u.uz)) {
1129			cc->y = cc->x = 0;
1130			break;
1131		    } /* else fall to the next cases */
1132	 case MIGR_STAIRS_UP:
1133	 case MIGR_LADDER_UP:
1134		    cc->x = u.uz.dnum;
1135		    cc->y = u.uz.dlevel + 1;
1136		    break;
1137	 case MIGR_SSTAIRS:
1138		    cc->x = sstairs.tolev.dnum;
1139		    cc->y = sstairs.tolev.dlevel;
1140		    break;
1141	 default:
1142	 case MIGR_NOWHERE:
1143		    /* y==0 means "nowhere", in which case x doesn't matter */
1144		    cc->y = cc->x = 0;
1145		    break;
1146	}
1147}
1148
1149void
1150impact_drop(missile, x, y, dlev)
1151struct obj *missile;
1152xchar x, y, dlev;
1153{
1154	schar toloc;
1155	register struct obj *obj, *obj2;
1156	register struct monst *shkp;
1157	long oct, dct, price, debit, robbed;
1158	boolean angry, costly, isrock;
1159	coord cc;
1160
1161	if(!OBJ_AT(x, y)) return;
1162
1163	toloc = down_gate(x, y);
1164	drop_to(&cc, toloc);
1165	if (!cc.y) return;
1166
1167	if (dlev) {
1168		/* send objects next to player falling through trap door.
1169		 * checked in obj_delivery().
1170		 */
1171		toloc = MIGR_NEAR_PLAYER;
1172		cc.y = dlev;
1173	}
1174
1175	costly = costly_spot(x, y);
1176	price = debit = robbed = 0L;
1177	angry = FALSE;
1178	shkp = (struct monst *) 0;
1179	/* if 'costly', we must keep a record of ESHK(shkp) before
1180	 * it undergoes changes through the calls to stolen_value.
1181	 * the angry bit must be reset, if needed, in this fn, since
1182	 * stolen_value is called under the 'silent' flag to avoid
1183	 * unsavory pline repetitions.
1184	 */
1185	if(costly) {
1186	    if ((shkp = shop_keeper(*in_rooms(x, y, SHOPBASE))) != 0) {
1187		debit	= ESHK(shkp)->debit;
1188		robbed	= ESHK(shkp)->robbed;
1189		angry	= !shkp->mpeaceful;
1190	    }
1191	}
1192
1193	isrock = (missile && missile->otyp == ROCK);
1194	oct = dct = 0L;
1195	for(obj = level.objects[x][y]; obj; obj = obj2) {
1196		obj2 = obj->nexthere;
1197		if(obj == missile) continue;
1198		/* number of objects in the pile */
1199		oct += obj->quan;
1200		if(obj == uball || obj == uchain) continue;
1201		/* boulders can fall too, but rarely & never due to rocks */
1202		if((isrock && obj->otyp == BOULDER) ||
1203		   rn2(obj->otyp == BOULDER ? 30 : 3)) continue;
1204		obj_extract_self(obj);
1205
1206		if(costly) {
1207		    price += stolen_value(obj, x, y,
1208				(costly_spot(u.ux, u.uy) &&
1209				 index(u.urooms, *in_rooms(x, y, SHOPBASE))),
1210				TRUE);
1211		    /* set obj->no_charge to 0 */
1212		    if (Has_contents(obj))
1213			picked_container(obj);	/* does the right thing */
1214		    if (obj->oclass != COIN_CLASS)
1215			obj->no_charge = 0;
1216		}
1217
1218		add_to_migration(obj);
1219		obj->ox = cc.x;
1220		obj->oy = cc.y;
1221		obj->owornmask = (long)toloc;
1222
1223		/* number of fallen objects */
1224		dct += obj->quan;
1225	}
1226
1227	if (dct && cansee(x,y)) {	/* at least one object fell */
1228	    const char *what = (dct == 1L ? "object falls" : "objects fall");
1229
1230	    if (missile)
1231		pline("From the impact, %sother %s.",
1232		      dct == oct ? "the " : dct == 1L ? "an" : "", what);
1233	    else if (oct == dct)
1234		pline("%s adjacent %s %s.",
1235		      dct == 1L ? "The" : "All the", what, gate_str);
1236	    else
1237		pline("%s adjacent %s %s.",
1238		      dct == 1L ? "One of the" : "Some of the",
1239		      dct == 1L ? "objects falls" : what, gate_str);
1240	}
1241
1242	if(costly && shkp && price) {
1243		if(ESHK(shkp)->robbed > robbed) {
1244		    You("removed %ld %s worth of goods!", price, currency(price));
1245		    if(cansee(shkp->mx, shkp->my)) {
1246			if(ESHK(shkp)->customer[0] == 0)
1247			    (void) strncpy(ESHK(shkp)->customer,
1248					   plname, PL_NSIZ);
1249			if(angry)
1250			    pline("%s is infuriated!", Monnam(shkp));
1251			else pline("\"%s, you are a thief!\"", plname);
1252		    } else  You_hear("a scream, \"Thief!\"");
1253		    hot_pursuit(shkp);
1254		    (void) angry_guards(FALSE);
1255		    return;
1256		}
1257		if(ESHK(shkp)->debit > debit) {
1258		    long amt = (ESHK(shkp)->debit - debit);
1259		    You("owe %s %ld %s for goods lost.",
1260			Monnam(shkp),
1261			amt, currency(amt));
1262		}
1263	}
1264
1265}
1266
1267/* NOTE: ship_object assumes otmp was FREED from fobj or invent.
1268 * <x,y> is the point of drop.  otmp is _not_ an <x,y> resident:
1269 * otmp is either a kicked, dropped, or thrown object.
1270 */
1271boolean
1272ship_object(otmp, x, y, shop_floor_obj)
1273xchar  x, y;
1274struct obj *otmp;
1275boolean shop_floor_obj;
1276{
1277	schar toloc;
1278	xchar ox, oy;
1279	coord cc;
1280	struct obj *obj;
1281	struct trap *t;
1282	boolean nodrop, unpaid, container, impact = FALSE;
1283	long n = 0L;
1284
1285	if (!otmp) return(FALSE);
1286	if ((toloc = down_gate(x, y)) == MIGR_NOWHERE) return(FALSE);
1287	drop_to(&cc, toloc);
1288	if (!cc.y) return(FALSE);
1289
1290	/* objects other than attached iron ball always fall down ladder,
1291	   but have a chance of staying otherwise */
1292	nodrop = (otmp == uball) || (otmp == uchain) ||
1293		(toloc != MIGR_LADDER_UP && rn2(3));
1294
1295	container = Has_contents(otmp);
1296	unpaid = (otmp->unpaid || (container && count_unpaid(otmp->cobj)));
1297
1298	if(OBJ_AT(x, y)) {
1299	    for(obj = level.objects[x][y]; obj; obj = obj->nexthere)
1300		if(obj != otmp) n += obj->quan;
1301	    if(n) impact = TRUE;
1302	}
1303	/* boulders never fall through trap doors, but they might knock
1304	   other things down before plugging the hole */
1305	if (otmp->otyp == BOULDER &&
1306		((t = t_at(x, y)) != 0) &&
1307		(t->ttyp == TRAPDOOR || t->ttyp == HOLE)) {
1308	    if (impact) impact_drop(otmp, x, y, 0);
1309	    return FALSE;		/* let caller finish the drop */
1310	}
1311
1312	if (cansee(x, y))
1313	    otransit_msg(otmp, nodrop, n);
1314
1315	if (nodrop) {
1316	    if (impact) impact_drop(otmp, x, y, 0);
1317	    return(FALSE);
1318	}
1319
1320	if(unpaid || shop_floor_obj) {
1321	    if(unpaid) {
1322		subfrombill(otmp, shop_keeper(*u.ushops));
1323		(void)stolen_value(otmp, u.ux, u.uy, TRUE, FALSE);
1324	    } else {
1325		ox = otmp->ox;
1326		oy = otmp->oy;
1327		(void)stolen_value(otmp, ox, oy,
1328			  (costly_spot(u.ux, u.uy) &&
1329			      index(u.urooms, *in_rooms(ox, oy, SHOPBASE))),
1330			  FALSE);
1331	    }
1332	    /* set otmp->no_charge to 0 */
1333	    if(container)
1334		picked_container(otmp); /* happens to do the right thing */
1335	    if(otmp->oclass != COIN_CLASS)
1336		otmp->no_charge = 0;
1337	}
1338
1339	if (otmp == uwep) setuwep((struct obj *)0);
1340	if (otmp == uquiver) setuqwep((struct obj *)0);
1341	if (otmp == uswapwep) setuswapwep((struct obj *)0);
1342
1343	/* some things break rather than ship */
1344	if (breaktest(otmp)) {
1345	    const char *result;
1346
1347	    if (objects[otmp->otyp].oc_material == GLASS
1348#ifdef TOURIST
1349		|| otmp->otyp == EXPENSIVE_CAMERA
1350#endif
1351		) {
1352		if (otmp->otyp == MIRROR)
1353		    change_luck(-2);
1354		result = "crash";
1355	    } else {
1356		/* penalty for breaking eggs laid by you */
1357		if (otmp->otyp == EGG && otmp->spe && otmp->corpsenm >= LOW_PM)
1358		    change_luck((schar) -min(otmp->quan, 5L));
1359		result = "splat";
1360	    }
1361	    You_hear("a muffled %s.",result);
1362	    obj_extract_self(otmp);
1363	    obfree(otmp, (struct obj *) 0);
1364	    return TRUE;
1365	}
1366
1367	add_to_migration(otmp);
1368	otmp->ox = cc.x;
1369	otmp->oy = cc.y;
1370	otmp->owornmask = (long)toloc;
1371	/* boulder from rolling boulder trap, no longer part of the trap */
1372	if (otmp->otyp == BOULDER) otmp->otrapped = 0;
1373
1374	if(impact) {
1375	    /* the objs impacted may be in a shop other than
1376	     * the one in which the hero is located.  another
1377	     * check for a shk is made in impact_drop.  it is, e.g.,
1378	     * possible to kick/throw an object belonging to one
1379	     * shop into another shop through a gap in the wall,
1380	     * and cause objects belonging to the other shop to
1381	     * fall down a trap door--thereby getting two shopkeepers
1382	     * angry at the hero in one shot.
1383	     */
1384	    impact_drop(otmp, x, y, 0);
1385	    newsym(x,y);
1386	}
1387	return(TRUE);
1388}
1389
1390void
1391obj_delivery()
1392{
1393	register struct obj *otmp, *otmp2;
1394	register int nx, ny;
1395	long where;
1396
1397	for (otmp = migrating_objs; otmp; otmp = otmp2) {
1398	    otmp2 = otmp->nobj;
1399	    if (otmp->ox != u.uz.dnum || otmp->oy != u.uz.dlevel) continue;
1400
1401	    obj_extract_self(otmp);
1402	    where = otmp->owornmask;		/* destination code */
1403	    otmp->owornmask = 0L;
1404
1405	    switch ((int)where) {
1406	     case MIGR_STAIRS_UP:   nx = xupstair,  ny = yupstair;
1407				break;
1408	     case MIGR_LADDER_UP:   nx = xupladder,  ny = yupladder;
1409				break;
1410	     case MIGR_SSTAIRS:	    nx = sstairs.sx,  ny = sstairs.sy;
1411				break;
1412	     case MIGR_NEAR_PLAYER: nx = u.ux,  ny = u.uy;
1413				break;
1414	     default:
1415	     case MIGR_RANDOM:	    nx = ny = 0;
1416				break;
1417	    }
1418	    if (nx > 0) {
1419		place_object(otmp, nx, ny);
1420		stackobj(otmp);
1421		(void)scatter(nx, ny, rnd(2), 0, otmp);
1422	    } else {		/* random location */
1423		/* set dummy coordinates because there's no
1424		   current position for rloco() to update */
1425		otmp->ox = otmp->oy = 0;
1426		rloco(otmp);
1427	    }
1428	}
1429}
1430
1431STATIC_OVL void
1432otransit_msg(otmp, nodrop, num)
1433register struct obj *otmp;
1434register boolean nodrop;
1435long num;
1436{
1437	char obuf[BUFSZ];
1438
1439	Sprintf(obuf, "%s%s",
1440		 (otmp->otyp == CORPSE &&
1441			type_is_pname(&mons[otmp->corpsenm])) ? "" : "The ",
1442		 xname(otmp));
1443
1444	if(num) { /* means: other objects are impacted */
1445	    Sprintf(eos(obuf), " %s %s object%s",
1446		    otense(otmp, "hit"),
1447		    num == 1L ? "another" : "other",
1448		    num > 1L ? "s" : "");
1449	    if(nodrop)
1450		Sprintf(eos(obuf), ".");
1451	    else
1452		Sprintf(eos(obuf), " and %s %s.",
1453			otense(otmp, "fall"), gate_str);
1454	    pline("%s", obuf);
1455	} else if(!nodrop)
1456	    pline("%s %s %s.", obuf, otense(otmp, "fall"), gate_str);
1457}
1458
1459/* migration destination for objects which fall down to next level */
1460schar
1461down_gate(x, y)
1462xchar x, y;
1463{
1464	struct trap *ttmp;
1465
1466	gate_str = 0;
1467	/* this matches the player restriction in goto_level() */
1468	if (on_level(&u.uz, &qstart_level) && !ok_to_quest())
1469	    return MIGR_NOWHERE;
1470
1471	if ((xdnstair == x && ydnstair == y) ||
1472		(sstairs.sx == x && sstairs.sy == y && !sstairs.up)) {
1473	    gate_str = "down the stairs";
1474	    return (xdnstair == x && ydnstair == y) ?
1475		    MIGR_STAIRS_UP : MIGR_SSTAIRS;
1476	}
1477	if (xdnladder == x && ydnladder == y) {
1478	    gate_str = "down the ladder";
1479	    return MIGR_LADDER_UP;
1480	}
1481
1482	if (((ttmp = t_at(x, y)) != 0 && ttmp->tseen) &&
1483		(ttmp->ttyp == TRAPDOOR || ttmp->ttyp == HOLE)) {
1484	    gate_str = (ttmp->ttyp == TRAPDOOR) ?
1485		    "through the trap door" : "through the hole";
1486	    return MIGR_RANDOM;
1487	}
1488	return MIGR_NOWHERE;
1489}
1490
1491/*dokick.c*/
1492