Source:SLASH'EM 0.0.7E7F2/dokick.c

From NetHackWiki
Revision as of 18:58, 7 March 2008 by Kernigh bot (talk | contribs) (SLASH'EM 0.0.7E7F2/dokick.c moved to Source:SLASH'EM 0.0.7E7F2/dokick.c: Robot: moved page)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

Below is the full text to dokick.c from the source code of SLASH'EM 0.0.7E7F2. To link to a particular line, write [[SLASH'EM 0.0.7E7F2/dokick.c#line123]], for example.

The latest source code for vanilla NetHack is at Source code.


The NetHack General Public License applies to screenshots, source code and other content from NetHack.

This content was modified from the original NetHack source code distribution (by splitting up NetHack content between wiki pages, and possibly further editing). See the page history for a list of who changed it, and on what dates.

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