Wikia

Wikihack

Source:SLASH'EM 0.0.7E7F2/dokick.c

2,032pages on
this wiki
Talk0

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.
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*/

Around Wikia's network

Random Wiki