Fandom

Wikihack

Source:NetHack 3.2.0/dokick.c

2,034pages on
this wiki
Add New Page
Talk0

Ad blocker interference detected!


Wikia is a free-to-use site that makes money from advertising. We have a modified experience for viewers using ad blockers

Wikia is not accessible if you’ve made further modifications. Remove the custom ad blocker rule(s) and the page will load as expected.

Below is the full text to dokick.c from the source code of NetHack 3.2.0. To link to a particular line, write [[NetHack 3.2.0/dokick.c#line123]], for example.

Warning! This is the source code from an old release. For the latest release, see Source code

The NetHack General Public License applies to screenshots, source code and other content from NetHack.
1.    /*	SCCS Id: @(#)dokick.c	3.2	96/03/23	*/
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()	(Role_is('S') || Role_is('P') || is_bigfoot(uasmon))
10.   
11.   static NEARDATA struct rm *maploc;
12.   static NEARDATA const char *gate_str;
13.   
14.   extern boolean notonhead;	/* for long worms */
15.   
16.   static void FDECL(kickdmg, (struct monst *, BOOLEAN_P));
17.   static void FDECL(kick_monster, (XCHAR_P, XCHAR_P));
18.   static int FDECL(kick_object, (XCHAR_P, XCHAR_P));
19.   static char *FDECL(kickstr, (char *));
20.   static void FDECL(otransit_msg, (struct obj *, BOOLEAN_P, int));
21.   static void FDECL(drop_to, (coord *,SCHAR_P));
22.   
23.   static NEARDATA struct obj *kickobj;
24.   
25.   #define IS_SHOP(x)	(rooms[x].rtype >= SHOPBASE)
26.   
27.   static void
28.   kickdmg(mon, clumsy)
29.   register struct monst *mon;
30.   register boolean clumsy;
31.   {
32.   	register int mdx, mdy;
33.   	register int dmg = ( ACURRSTR + ACURR(A_DEX) + ACURR(A_CON) )/ 15;
34.   
35.   	/* excessive wt affects dex, so it affects dmg */
36.   	if(clumsy) dmg = dmg/2;
37.   
38.   	/* kicking a dragon or an elephant will not harm it */
39.   	if(thick_skinned(mon->data)) dmg = 0;
40.   
41.   	/* a good kick exercises your dex */
42.   	exercise(A_DEX, TRUE);
43.   
44.   /*	it is unchivalrous to attack the defenseless or from behind */
45.   	if (Role_is('K') &&
46.   		u.ualign.type == A_LAWFUL && u.ualign.record > -10 &&
47.   		(!mon->mcanmove || mon->msleep || mon->mflee))
48.   		adjalign(-1);
49.   
50.   	/* squeeze some guilt feelings... */
51.   	if(mon->mtame) {
52.   	    abuse_dog(mon);
53.   	    mon->mflee = mon->mtame ? 1 : 0;
54.   #ifdef HISX
55.   	    mon->mfleetim = mon->mfleetim + (dmg ? rnd(dmg) : 1);
56.   #else
57.   	    mon->mfleetim += (dmg ? rnd(dmg) : 1);
58.   #endif
59.   	}
60.   
61.   	if (dmg > 0) {
62.   		/* convert potential damage to actual damage */
63.   		dmg = rnd(dmg);
64.   		if (martial()) dmg += rn2(ACURR(A_DEX)/2 + 1);
65.   	}
66.   	dmg += u.udaminc;	/* add ring(s) of increase damage */
67.   	if (dmg > 0) {
68.   		mon->mhp -= dmg;
69.   		if (mon->mhp < 1) {
70.   			(void) passive(mon, TRUE, 0, TRUE);
71.   			killed(mon);
72.   			return;
73.   		}
74.   	}
75.   	if(martial() && !bigmonst(mon->data) && !rn2(3) && mon->mcanmove
76.   	   && mon != u.ustuck) {
77.   		/* see if the monster has a place to move into */
78.   		mdx = mon->mx + u.dx;
79.   		mdy = mon->my + u.dy;
80.   		if(goodpos(mdx, mdy, mon, mon->data)) {
81.   			pline("%s reels from the blow.", Monnam(mon));
82.   			remove_monster(mon->mx, mon->my);
83.   			newsym(mon->mx, mon->my);
84.   			place_monster(mon, mdx, mdy);
85.   			newsym(mon->mx, mon->my);
86.   			set_apparxy(mon);
87.   		}
88.   	}
89.   	(void) passive(mon, FALSE, 1, TRUE);
90.   
91.   }
92.   
93.   static void
94.   kick_monster(x, y)
95.   register xchar x, y;
96.   {
97.   	register boolean clumsy = FALSE;
98.   	register struct monst *mon = m_at(x, y);
99.   	register int i, j;
100.  
101.  	bhitpos.x = x;
102.  	bhitpos.y = y;
103.  	if (attack_checks(mon, (struct obj *)0)) return;
104.  	setmangry(mon);
105.  
106.  	/* Kick attacks by kicking monsters are normal attacks, not special.
107.  	 * If you have >1 kick attack, you get all of them.
108.  	 */
109.  	if (attacktype(uasmon, AT_KICK)) {
110.  	    schar tmp = find_roll_to_hit(mon);
111.  	    for(i=0; i<NATTK; i++) {
112.  		if (uasmon->mattk[i].aatyp == AT_KICK && multi >= 0) {
113.  		    /* check multi; maybe they had 2 kicks and the first */
114.  		    /* was a kick against a floating eye */
115.  		    if (tmp > rnd(20)) {
116.  			int sum;
117.  
118.  			You("kick %s.", mon_nam(mon));
119.  			sum = damageum(mon, &(uasmon->mattk[i]));
120.  			if (sum == 2)
121.  				(void)passive(mon, 1, 0, TRUE);
122.  			else (void)passive(mon, sum, 1, TRUE);
123.  		    } else {
124.  			missum(mon, &(uasmon->mattk[i]));
125.  			(void)passive(mon, 0, 1, TRUE);
126.  		    }
127.  		}
128.  	    }
129.  	    return;
130.  	}
131.  
132.  	if(noncorporeal(mon->data)) {
133.  		Your("kick passes through!");
134.  		return;
135.  	}
136.  
137.  	if(Levitation && !rn2(3) && verysmall(mon->data) &&
138.  	   !is_flyer(mon->data)) {
139.  		pline("Floating in the air, you miss wildly!");
140.  		exercise(A_DEX, FALSE);
141.  		(void) passive(mon, FALSE, 1, TRUE);
142.  		return;
143.  	}
144.  
145.  	i = -inv_weight();
146.  	j = weight_cap();
147.  
148.  	if(i < (j*3)/10) {
149.  		if(!rn2((i < j/10) ? 2 : (i < j/5) ? 3 : 4)) {
150.  			if(martial() && !rn2(2)) goto doit;
151.  			Your("clumsy kick does no damage.");
152.  			(void) passive(mon, FALSE, 1, TRUE);
153.  			return;
154.  		}
155.  		if(i < j/10) clumsy = TRUE;
156.  		else if(!rn2((i < j/5) ? 2 : 3)) clumsy = TRUE;
157.  	}
158.  
159.  	if(Fumbling) clumsy = TRUE;
160.  
161.  	else if(uarm && objects[uarm->otyp].oc_bulky && ACURR(A_DEX) < rnd(25))
162.  		clumsy = TRUE;
163.  doit:
164.  	You("kick %s.", mon_nam(mon));
165.  	if(!rn2(clumsy ? 3 : 4) && (clumsy || !bigmonst(mon->data)) &&
166.  	   mon->mcansee && !mon->mtrapped && !thick_skinned(mon->data) &&
167.  	   mon->data->mlet != S_EEL && haseyes(mon->data) && mon->mcanmove &&
168.  	   !mon->mstun && !mon->mconf && !mon->msleep &&
169.  	   mon->data->mmove >= 12) {
170.  		if(!nohands(mon->data) && !rn2(martial() ? 5 : 3)) {
171.  		    pline("%s blocks your %skick.", Monnam(mon),
172.  				clumsy ? "clumsy " : "");
173.  		    (void) passive(mon, FALSE, 1, TRUE);
174.  		    return;
175.  		} else {
176.  		    mnexto(mon);
177.  		    if(mon->mx != x || mon->my != y) {
178.  			pline("%s %s, %s evading your %skick.", Monnam(mon),
179.  				(can_teleport(mon->data) ? "teleports" :
180.  				 is_floater(mon->data) ? "floats" :
181.  				 is_flyer(mon->data) ? "flutters" :
182.  				 nolimbs(mon->data) ? "slides" :
183.  				 "jumps"),
184.  				clumsy ? "easily" : "nimbly",
185.  				clumsy ? "clumsy " : "");
186.  			(void) passive(mon, FALSE, 1, TRUE);
187.  			return;
188.  		    }
189.  		}
190.  	}
191.  	kickdmg(mon, clumsy);
192.  }
193.  
194.  /*
195.   *  Return TRUE if caught (the gold taken care of), FALSE otherwise.
196.   *  The gold object is *not* attached to the fobj chain!
197.   */
198.  boolean
199.  ghitm(mtmp, gold)
200.  register struct monst *mtmp;
201.  register struct obj *gold;
202.  {
203.  	if(!likes_gold(mtmp->data) && !mtmp->isshk && !mtmp->ispriest
204.  			&& !is_mercenary(mtmp->data)) {
205.  		wakeup(mtmp);
206.  	} else if (!mtmp->mcanmove) {
207.  		/* too light to do real damage */
208.  		if (canseemon(mtmp))
209.  		    pline_The("gold hits %s.", mon_nam(mtmp));
210.  	} else {
211.  		mtmp->msleep = 0;
212.  		mtmp->meating = 0;
213.  		if(!rn2(4)) setmangry(mtmp); /* not always pleasing */
214.  
215.  		/* greedy monsters catch gold */
216.  		if (cansee(mtmp->mx, mtmp->my))
217.  		    pline("%s catches the gold.", Monnam(mtmp));
218.  		mtmp->mgold += gold->quan;
219.  		if (mtmp->isshk) {
220.  			long robbed = ESHK(mtmp)->robbed;
221.  
222.  			if (robbed) {
223.  				robbed -= gold->quan;
224.  				if (robbed < 0) robbed = 0;
225.  				pline_The("amount %scovers %s recent losses.",
226.  				      !robbed ? "" : "partially ",
227.  				      his[mtmp->female]);
228.  				ESHK(mtmp)->robbed = robbed;
229.  				if(!robbed)
230.  					make_happy_shk(mtmp, FALSE);
231.  			} else {
232.  				if(mtmp->mpeaceful) {
233.  				    ESHK(mtmp)->credit += gold->quan;
234.  				    You("have %ld zorkmid%s in credit.",
235.  					ESHK(mtmp)->credit,
236.  					plur(ESHK(mtmp)->credit));
237.  				} else verbalize("Thanks, scum!");
238.  			}
239.  		} else if (mtmp->ispriest) {
240.  			if (mtmp->mpeaceful)
241.  			    verbalize("Thank you for your contribution.");
242.  			else verbalize("Thanks, scum!");
243.  		} else if (is_mercenary(mtmp->data)) {
244.  		    long goldreqd = 0L;
245.  
246.  		    if (rn2(3)) {
247.  			if (mtmp->data == &mons[PM_SOLDIER])
248.  			   goldreqd = 100L;
249.  			else if (mtmp->data == &mons[PM_SERGEANT])
250.  			   goldreqd = 250L;
251.  			else if (mtmp->data == &mons[PM_LIEUTENANT])
252.  			   goldreqd = 500L;
253.  			else if (mtmp->data == &mons[PM_CAPTAIN])
254.  			   goldreqd = 750L;
255.  
256.  			if (goldreqd) {
257.  			   if (gold->quan > goldreqd +
258.  				(u.ugold + u.ulevel*rn2(5))/ACURR(A_CHA))
259.  			    mtmp->mpeaceful = TRUE;
260.  			}
261.  		     }
262.  		     if (mtmp->mpeaceful)
263.  			    verbalize("That should do.  Now beat it!");
264.  		     else verbalize("That's not enough, coward!");
265.  		 }
266.  
267.  		dealloc_obj(gold);
268.  		return(1);
269.  	}
270.  	return(0);
271.  }
272.  
273.  static int
274.  kick_object(x, y)
275.  xchar x, y;
276.  {
277.  	int range;
278.  	register struct monst *mon, *shkp;
279.  	register struct obj *otmp;
280.  	struct trap *trap;
281.  	char bhitroom;
282.  	boolean costly, insider, isgold, slide = FALSE;
283.  
284.  	/* if a pile, the "top" object gets kicked */
285.  	kickobj = level.objects[x][y];
286.  
287.  	/* kickobj should always be set due to conditions of call */
288.  	if(!kickobj || kickobj->otyp == BOULDER
289.  			|| kickobj == uball || kickobj == uchain)
290.  		return(0);
291.  
292.  	if((trap = t_at(x,y)) && trap->tseen) {
293.  		if (((trap->ttyp == PIT || trap->ttyp == SPIKED_PIT)
294.  					&& !passes_walls(uasmon))
295.  				|| trap->ttyp == WEB) {
296.  			You_cant("kick %s that's in a %s!", something,
297.  				trap->ttyp == WEB ? "web" : "pit");
298.  			return(1);
299.  		}
300.  	}
301.  
302.  	if(Fumbling && !rn2(3)) {
303.  		Your("clumsy kick missed.");
304.  		return(1);
305.  	}
306.  
307.  	/* range < 2 means the object will not move.	*/
308.  	/* maybe dexterity should also figure here.     */
309.  	range = (int)((ACURRSTR)/2 - kickobj->owt/40);
310.  
311.  	if(martial()) range += rnd(3);
312.  
313.  	if(is_ice(x,y)) { range += rnd(3); slide = TRUE; }
314.  	if(kickobj->greased) { range += rnd(3); slide = TRUE; }
315.  
316.  	/* Mjollnir is magically too heavy to kick */
317.  	if(kickobj->oartifact == ART_MJOLLNIR) range = 1;
318.  
319.  	/* see if the object has a place to move into */
320.  	if(!ZAP_POS(levl[x+u.dx][y+u.dy].typ) || closed_door(x+u.dx, y+u.dy))
321.  		range = 1;
322.  
323.  	costly = ((shkp = shop_keeper(*in_rooms(x, y, SHOPBASE))) &&
324.  				    costly_spot(x, y));
325.  	insider = (*u.ushops && inside_shop(u.ux, u.uy) &&
326.  				    *in_rooms(x, y, SHOPBASE) == *u.ushops);
327.  
328.  	/* a box gets a chance of breaking open here */
329.  	if(Is_box(kickobj)) {
330.  		boolean otrp = kickobj->otrapped;
331.  		struct obj *otmp2;
332.  		long loss = 0L;
333.  
334.  		if(range < 2) pline("THUD!");
335.  
336.  		for(otmp = kickobj->cobj; otmp; otmp = otmp2) {
337.  			const char *result = (char *)0;
338.  
339.  			otmp2 = otmp->nobj;
340.  			if (objects[otmp->otyp].oc_material == GLASS
341.  			    && otmp->oclass != GEM_CLASS
342.  			    && !obj_resists(otmp, 33, 100)) {
343.  				result = "shatter";
344.  			} else if (otmp->otyp == EGG && !rn2(3)) {
345.  				result = "cracking";
346.  			}
347.  			if (result) {
348.  				You_hear("a muffled %s.",result);
349.  				if(costly) loss += stolen_value(otmp, x, y,
350.  					    (boolean)shkp->mpeaceful, TRUE);
351.  				if (otmp->quan > 1L)
352.  					useup(otmp);
353.  				else {
354.  					obj_extract_self(otmp);
355.  					obfree(otmp, (struct obj *) 0);
356.  				}
357.  			}
358.  		}
359.  		if(costly && loss) {
360.  		    if(!insider) {
361.  			You("caused %ld zorkmids worth of damage!", loss);
362.  			make_angry_shk(shkp, x, y);
363.  		    } else {
364.  			You("owe %s %ld zorkmids for objects destroyed.",
365.  			    mon_nam(shkp), loss);
366.  		    }
367.  		}
368.  
369.  		if (kickobj->olocked) {
370.  		    if (!rn2(5) || (martial() && !rn2(2))) {
371.  			You("break open the lock!");
372.  			kickobj->olocked = 0;
373.  			kickobj->obroken = 1;
374.  			if (otrp) (void) chest_trap(kickobj, LEG, FALSE);
375.  			return(1);
376.  		    }
377.  		} else {
378.  		    if (!rn2(3) || (martial() && !rn2(2))) {
379.  			pline_The("lid slams open, then falls shut.");
380.  			if (otrp) (void) chest_trap(kickobj, LEG, FALSE);
381.  			return(1);
382.  		    }
383.  		}
384.  		if(range < 2) return(1);
385.  		/* else let it fall through to the next cases... */
386.  	}
387.  
388.  	/* fragile objects should not be kicked */
389.  	if (breaks(kickobj, kickobj->ox, kickobj->oy, FALSE)) return 1;
390.  
391.  	if(IS_ROCK(levl[x][y].typ)) {
392.  		if ((!martial() && rn2(20) > ACURR(A_DEX))
393.  				|| IS_ROCK(levl[u.ux][u.uy].typ)) {
394.  			if (Blind) pline("It doesn't come loose.");
395.  			else pline("%s do%sn't come loose.",
396.  				The(distant_name(kickobj, xname)),
397.  				(kickobj->quan == 1L) ? "es" : "");
398.  			return(!rn2(3) || martial());
399.  		}
400.  		if (Blind) pline("It comes loose.");
401.  		else pline("%s come%s loose.",
402.  			   The(distant_name(kickobj, xname)),
403.  			   (kickobj->quan == 1L) ? "s" : "");
404.  		obj_extract_self(kickobj);
405.  		newsym(x, y);
406.  		if (costly && (!costly_spot(u.ux, u.uy)
407.  			       || !index(u.urooms, *in_rooms(x, y, SHOPBASE))))
408.  			addtobill(kickobj, FALSE, FALSE, FALSE);
409.  		if(!flooreffects(kickobj,u.ux,u.uy,"fall")) {
410.  		    place_object(kickobj, u.ux, u.uy);
411.  		    stackobj(kickobj);
412.  		    newsym(u.ux, u.uy);
413.  		}
414.  		return(1);
415.  	}
416.  
417.  	isgold = (kickobj->oclass == GOLD_CLASS);
418.  
419.  	/* too heavy to move.  range is calculated as potential distance from
420.  	 * player, so range == 2 means the object may move up to one square
421.  	 * from its current position
422.  	 */
423.  	if(range < 2 || (isgold && kickobj->quan > 300L)) {
424.  	    if(!Is_box(kickobj)) pline("Thump!");
425.  	    return(!rn2(3) || martial());
426.  	}
427.  
428.  	if (kickobj->quan > 1L && !isgold) (void) splitobj(kickobj, 1L);
429.  
430.  	if (slide && !Blind)
431.  	    pline("Whee!  %s slide%s across the %s.", Doname2(kickobj),
432.  		kickobj->quan > 1L ? "" : "s",
433.  		surface(x,y));
434.  
435.  	obj_extract_self(kickobj);
436.  	newsym(x, y);
437.  	mon = bhit(u.dx, u.dy, range, KICKED_WEAPON,
438.  		   (int (*)()) 0, (int (*)()) 0, kickobj);
439.  
440.  	/* We check for whether the object falls down the stairs by
441.  	 * calling ship_object() from bhit().  This is necessary so that if
442.  	 * the object doesn't fall, we can continue bhit() by moving the
443.  	 * object the rest of the way.  If it does fall, bhit() returns at
444.  	 * the fall position (which must have stairs at it).  This is somewhat
445.  	 * ugly (for instance, we need to duplicate the shop check within
446.  	 * bhit()), and we really should be checking _whether_ it falls in there
447.  	 * and only doing the actual fall here, but this would take a lot of
448.  	 * rewriting.
449.  	 */
450.  	if (!mon && down_gate(bhitpos.x, bhitpos.y) != MIGR_NOWHERE)
451.  		return 1;
452.  
453.  	if(mon) {
454.  	    if (mon->isshk &&
455.  		    kickobj->where == OBJ_MINVENT && kickobj->ocarry == mon)
456.  		return 1;	/* alert shk caught it */
457.  	    notonhead = (mon->mx != bhitpos.x || mon->my != bhitpos.y);
458.  	    /* awake monster if sleeping */
459.  	    wakeup(mon);
460.  	    if(isgold ? ghitm(mon, kickobj) :	/* caught? */
461.  		thitmonst(mon, kickobj))	/* hit && used up? */
462.  		return(1);
463.  	}
464.  	bhitroom = *in_rooms(bhitpos.x, bhitpos.y, SHOPBASE);
465.  	if (costly && (!costly_spot(bhitpos.x, bhitpos.y) ||
466.  			*in_rooms(x, y, SHOPBASE) != bhitroom)) {
467.  	    if(isgold)
468.  		costly_gold(x, y, kickobj->quan);
469.  	    else (void)stolen_value(kickobj, x, y,
470.  				    (boolean)shkp->mpeaceful, FALSE);
471.  	}
472.  
473.  	if(flooreffects(kickobj,bhitpos.x,bhitpos.y,"fall")) return(1);
474.  	place_object(kickobj, bhitpos.x, bhitpos.y);
475.  	stackobj(kickobj);
476.  	newsym(kickobj->ox, kickobj->oy);
477.  	return(1);
478.  }
479.  
480.  static char *
481.  kickstr(buf)
482.  char *buf;
483.  {
484.  	const char *what;
485.  
486.  	if (kickobj) what = distant_name(kickobj,doname);
487.  	else if (IS_DOOR(maploc->typ)) what = "a door";
488.  	else if (IS_STWALL(maploc->typ)) what = "a wall";
489.  	else if (IS_ROCK(maploc->typ)) what = "a rock";
490.  	else if (IS_THRONE(maploc->typ)) what = "a throne";
491.  #ifdef SINKS
492.  	else if (IS_SINK(maploc->typ)) what = "a sink";
493.  #endif
494.  	else if (IS_ALTAR(maploc->typ)) what = "an altar";
495.  	else if (IS_DRAWBRIDGE(maploc->typ)) what = "the drawbridge";
496.  	else if (maploc->typ == STAIRS) what = "the stairs";
497.  	else if (maploc->typ == LADDER) what = "a ladder";
498.  	else what = "something weird";
499.  	return strcat(strcpy(buf, "kicking "), what);
500.  }
501.  
502.  int
503.  dokick()
504.  {
505.  	register int x, y;
506.  	int avrg_attrib;
507.  	register struct monst *mtmp;
508.  	s_level *slev;
509.  	boolean no_kick = FALSE;
510.  	char buf[BUFSZ];
511.  
512.  	if (nolimbs(uasmon)) {
513.  		You("have no legs to kick with.");
514.  		no_kick = TRUE;
515.  	} else if (verysmall(uasmon)) {
516.  		You("are too small to do any kicking.");
517.  		no_kick = TRUE;
518.  	} else if (Wounded_legs) {
519.  		Your("%s %s in no shape for kicking.",
520.  		  ((Wounded_legs & BOTH_SIDES)==BOTH_SIDES)
521.  		    ? (const char *)makeplural(body_part(LEG)) : body_part(LEG),
522.  		  ((Wounded_legs & BOTH_SIDES)==BOTH_SIDES) ? "are" : "is");
523.  		no_kick = TRUE;
524.  	} else if (near_capacity() > SLT_ENCUMBER) {
525.  		Your("load is too heavy to balance yourself for a kick.");
526.  		no_kick = TRUE;
527.  	} else if (u.uinwater && !rn2(2)) {
528.  		Your("slow motion kick doesn't hit anything.");
529.  		no_kick = TRUE;
530.  	} else if (u.utrap) {
531.  		switch (u.utraptype) {
532.  		    case TT_PIT:
533.  			pline("There's not enough room to kick down here.");
534.  			break;
535.  		    case TT_WEB:
536.  		    case TT_BEARTRAP:
537.  			You_cant("move your %s!", body_part(LEG));
538.  			break;
539.  		    default:
540.  			break;
541.  		}
542.  		no_kick = TRUE;
543.  	}
544.  
545.  	if (no_kick) {
546.  		/* discard direction typeahead, if any */
547.  		display_nhwindow(WIN_MESSAGE, TRUE);	/* --More-- */
548.  		return 0;
549.  	}
550.  
551.  	if(!getdir((char *)0)) return(0);
552.  	if(!u.dx && !u.dy) return(0);
553.  
554.  	x = u.ux + u.dx;
555.  	y = u.uy + u.dy;
556.  	avrg_attrib = (ACURRSTR+ACURR(A_DEX)+ACURR(A_CON))/3;
557.  
558.  	if(u.uswallow) {
559.  		switch(rn2(3)) {
560.  		case 0:  You_cant("move your %s!", body_part(LEG));
561.  			 break;
562.  		case 1:  if (is_animal(u.ustuck->data)) {
563.  				pline("%s burps loudly.", Monnam(u.ustuck));
564.  				break;
565.  			 }
566.  		default: Your("feeble kick has no effect."); break;
567.  		}
568.  		return(1);
569.  	}
570.  
571.  	wake_nearby();
572.  	u_wipe_engr(2);
573.  
574.  	maploc = &levl[x][y];
575.  
576.  	/* The next four tests should stay in      */
577.  	/* their present order: monsters, objects, */
578.  	/* non-doors, doors.			   */
579.  
580.  	if(MON_AT(x, y)) {
581.  		struct permonst *mdat = m_at(x,y)->data;
582.  		kick_monster(x, y);
583.  		if((Is_airlevel(&u.uz) || Levitation) && flags.move) {
584.  		    int range;
585.  
586.  		    range = ((int)uasmon->cwt + (weight_cap() + inv_weight()));
587.  		    if (range < 1) range = 1; /* divide by zero avoidance */
588.  		    range = (3*(int)mdat->cwt) / range;
589.  
590.  		    if(range < 1) range = 1;
591.  		    hurtle(-u.dx, -u.dy, range);
592.  		}
593.  		return(1);
594.  	}
595.  
596.  	kickobj = (struct obj *)0;
597.  	if (OBJ_AT(x, y) &&
598.  	    (!Levitation || Is_airlevel(&u.uz) || Is_waterlevel(&u.uz)
599.  	     || sobj_at(BOULDER,x,y))) {
600.  		if(kick_object(x, y)) {
601.  		    if(Is_airlevel(&u.uz))
602.  			hurtle(-u.dx, -u.dy, 1); /* assume it's light */
603.  		    return(1);
604.  		}
605.  		goto ouch;
606.  	}
607.  
608.  	if(!IS_DOOR(maploc->typ)) {
609.  		if(maploc->typ == SDOOR) {
610.  		    if(!Levitation && rn2(30) < avrg_attrib) {
611.  			pline("Crash!  You kick open a secret door!");
612.  			exercise(A_DEX, TRUE);
613.  			maploc->typ = DOOR;
614.  			maploc->doormask = exposed_sdoor_mask(maploc);
615.  			if(maploc->doormask & D_TRAPPED) {
616.  			    maploc->doormask = D_NODOOR;
617.  			    b_trapped("door", FOOT);
618.  			} else if (maploc->doormask != D_NODOOR)
619.  			    maploc->doormask = D_ISOPEN;
620.  			if (Blind)
621.  			    feel_location(x,y);	/* we know its gone */
622.  			else
623.  			    newsym(x,y);
624.  			unblock_point(x,y);	/* vision */
625.  			return(1);
626.  		    } else goto ouch;
627.  		}
628.  		if(maploc->typ == SCORR) {
629.  		    if(!Levitation && rn2(30) < avrg_attrib) {
630.  			pline("Crash!  You kick open a secret passage!");
631.  			exercise(A_DEX, TRUE);
632.  			maploc->typ = CORR;
633.  			if (Blind)
634.  			    feel_location(x,y);	/* we known its gone */
635.  			else
636.  			    newsym(x,y);
637.  			unblock_point(x,y);	/* vision */
638.  			return(1);
639.  		    } else goto ouch;
640.  		}
641.  		if(IS_THRONE(maploc->typ)) {
642.  		    register int i;
643.  		    if(Levitation) goto dumb;
644.  		    if((Luck < 0 || maploc->doormask) && !rn2(3)) {
645.  			maploc->typ = ROOM;
646.  			maploc->doormask = 0; /* don't leave loose ends.. */
647.  			mkgold((long)rnd(200), x, y);
648.  			if (Blind)
649.  			    pline("CRASH!  You destroy it.");
650.  			else {
651.  			    pline("CRASH!  You destroy the throne.");
652.  			    newsym(x, y);
653.  			}
654.  			exercise(A_DEX, TRUE);
655.  			return(1);
656.  		    } else if(Luck > 0 && !rn2(3) && !maploc->looted) {
657.  			mkgold((long) rn1(201, 300), x, y);
658.  			i = Luck + 1;
659.  			if(i > 6) i = 6;
660.  			while(i--) (void) mkobj_at(GEM_CLASS, x, y, TRUE);
661.  			if (Blind)
662.  			    You("kick %s loose!", something);
663.  			else {
664.  			    You("kick loose some ornamental coins and gems!");
665.  			    newsym(x, y);
666.  			}
667.  			/* prevent endless milking */
668.  			maploc->looted = T_LOOTED;
669.  			return(1);
670.  		    } else if (!rn2(4)) {
671.  			if(dunlev(&u.uz) < dunlevs_in_dungeon(&u.uz)) {
672.  			    fall_through(FALSE);
673.  			    return(1);
674.  			} else goto ouch;
675.  		    }
676.  		    goto ouch;
677.  		}
678.  		if(IS_ALTAR(maploc->typ)) {
679.  		    if(Levitation) goto dumb;
680.  		    You("kick %s.",(Blind ? something : "the altar"));
681.  		    if(!rn2(3)) goto ouch;
682.  		    altar_wrath(x, y);
683.  		    exercise(A_DEX, TRUE);
684.  		    return(1);
685.  		}
686.  		if(IS_FOUNTAIN(maploc->typ)) {
687.  		    if(Levitation) goto dumb;
688.  		    You("kick %s.",(Blind ? something : "the fountain"));
689.  		    if(!rn2(3)) goto ouch;
690.  		    /* make metal boots rust */
691.  		    if(uarmf && rn2(3))
692.  			if (!rust_dmg(uarmf, "metal boots", 1, FALSE)) {
693.  				Your("boots get wet.");
694.  				/* could cause short-lived fumbling here */
695.  			}
696.  		    exercise(A_DEX, TRUE);
697.  		    return(1);
698.  		}
699.  #ifdef SINKS
700.  		if(IS_SINK(maploc->typ)) {
701.  		    if(Levitation) goto dumb;
702.  		    if(rn2(5)) {
703.  			if(flags.soundok)
704.  			    pline("Klunk!  The pipes vibrate noisily.");
705.  			else pline("Klunk!");
706.  			exercise(A_DEX, TRUE);
707.  			return(1);
708.  		    } else if(!(maploc->looted & S_LPUDDING) && !rn2(3) &&
709.  			  !(mvitals[PM_BLACK_PUDDING].mvflags & G_GONE)) {
710.  			if (Blind)
711.  			    You_hear("a gushing sound.");
712.  			else
713.  			    pline("A %s ooze gushes up from the drain!",
714.  					 hcolor(Black));
715.  			(void) makemon(&mons[PM_BLACK_PUDDING], x, y);
716.  			exercise(A_DEX, TRUE);
717.  			newsym(x,y);
718.  			maploc->looted |= S_LPUDDING;
719.  			return(1);
720.  		    } else if(!(maploc->looted & S_LDWASHER) && !rn2(3) &&
721.  			      !(mvitals[poly_gender() == 1 ? PM_INCUBUS
722.  					: PM_SUCCUBUS].mvflags & G_GONE)) {
723.  			/* can't resist... */
724.  			pline("%s returns!", (Blind ? Something :
725.  							"The dish washer"));
726.  			if (makemon(&mons[poly_gender() == 1 ?
727.  				PM_INCUBUS : PM_SUCCUBUS], x, y)) newsym(x,y);
728.  			maploc->looted |= S_LDWASHER;
729.  			exercise(A_DEX, TRUE);
730.  			return(1);
731.  		    } else if(!rn2(3)) {
732.  			pline("Flupp!  %s.", (Blind ?
733.  				      "You hear a sloshing sound" :
734.  				      "Muddy waste pops up from the drain"));
735.  			if(!(maploc->looted & S_LRING)) { /* once per sink */
736.  			    if (!Blind)
737.  				You("see a ring shining in its midst.");
738.  			    (void) mkobj_at(RING_CLASS, x, y, TRUE);
739.  			    newsym(x, y);
740.  			    exercise(A_DEX, TRUE);
741.  			    exercise(A_WIS, TRUE);	/* a discovery! */
742.  			    maploc->looted |= S_LRING;
743.  			}
744.  			return(1);
745.  		    }
746.  		    goto ouch;
747.  		}
748.  #endif
749.  		if (maploc->typ == STAIRS || maploc->typ == LADDER ||
750.  						    IS_STWALL(maploc->typ)) {
751.  		    if(!IS_STWALL(maploc->typ) && maploc->ladder == LA_DOWN)
752.  			goto dumb;
753.  ouch:
754.  		    pline("Ouch!  That hurts!");
755.  		    exercise(A_DEX, FALSE);
756.  		    exercise(A_STR, FALSE);
757.  		    if (Blind) feel_location(x,y); /* we know we hit it */
758.  		    if(!rn2(3)) set_wounded_legs(RIGHT_SIDE, 5 + rnd(5));
759.  		    losehp(rnd(ACURR(A_CON) > 15 ? 3 : 5), kickstr(buf),
760.  			KILLED_BY);
761.  		    if(Is_airlevel(&u.uz) || Levitation)
762.  			hurtle(-u.dx, -u.dy, rn1(2,4)); /* assume it's heavy */
763.  		    return(1);
764.  		}
765.  		if (is_drawbridge_wall(x,y) >= 0) {
766.  		    pline_The("drawbridge is unaffected.");
767.  		    if(Levitation)
768.  			hurtle(-u.dx, -u.dy, rn1(2,4)); /* it's heavy */
769.  		    return(1);
770.  		}
771.  		goto dumb;
772.  	}
773.  
774.  	if(maploc->doormask == D_ISOPEN ||
775.  	   maploc->doormask == D_BROKEN ||
776.  	   maploc->doormask == D_NODOOR) {
777.  dumb:
778.  		exercise(A_DEX, FALSE);
779.  		if (martial() || ACURR(A_DEX) >= 16 || rn2(3)) {
780.  			You("kick at empty space.");
781.  			feel_location(x,y);
782.  		} else {
783.  			pline("Dumb move!  You strain a muscle.");
784.  			exercise(A_STR, FALSE);
785.  			set_wounded_legs(RIGHT_SIDE, 5 + rnd(5));
786.  		}
787.  		if ((Is_airlevel(&u.uz) || Levitation) && rn2(2)) {
788.  		    hurtle(-u.dx, -u.dy, 1);
789.  		    return 1;		/* you moved, so use up a turn */
790.  		}
791.  		return(0);
792.  	}
793.  
794.  	/* not enough leverage to kick open doors while levitating */
795.  	if(Levitation) goto ouch;
796.  
797.  	exercise(A_DEX, TRUE);
798.  	/* door is known to be CLOSED or LOCKED */
799.  	if(rnl(35) < avrg_attrib + (!martial() ? 0 : ACURR(A_DEX))) {
800.  		boolean shopdoor = *in_rooms(x, y, SHOPBASE) ? TRUE : FALSE;
801.  		/* break the door */
802.  		if(maploc->doormask & D_TRAPPED) {
803.  		    if (flags.verbose) You("kick the door.");
804.  		    exercise(A_STR, FALSE);
805.  		    maploc->doormask = D_NODOOR;
806.  		    b_trapped("door", FOOT);
807.  		} else if(ACURR(A_STR) > 18 && !rn2(5) && !shopdoor) {
808.  		    pline("As you kick the door, it shatters to pieces!");
809.  		    exercise(A_STR, TRUE);
810.  		    maploc->doormask = D_NODOOR;
811.  		} else {
812.  		    pline("As you kick the door, it crashes open!");
813.  		    exercise(A_STR, TRUE);
814.  		    maploc->doormask = D_BROKEN;
815.  		}
816.  		if (Blind)
817.  		    feel_location(x,y);		/* we know we broke it */
818.  		else
819.  		    newsym(x,y);
820.  		unblock_point(x,y);		/* vision */
821.  		if (shopdoor) {
822.  		    add_damage(x, y, 400L);
823.  		    pay_for_damage("break");
824.  		}
825.  		if ((slev = Is_special(&u.uz)) && slev->flags.town)
826.  		  for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
827.  		    if((mtmp->data == &mons[PM_WATCHMAN] ||
828.  			mtmp->data == &mons[PM_WATCH_CAPTAIN]) &&
829.  			couldsee(mtmp->mx, mtmp->my) &&
830.  			mtmp->mpeaceful) {
831.  			pline("%s yells:", Amonnam(mtmp));
832.  			verbalize("Halt, thief!  You're under arrest!");
833.  			(void) angry_guards(FALSE);
834.  			break;
835.  		    }
836.  		  }
837.  	} else {
838.  	    if (Blind) feel_location(x,y);	/* we know we hit it */
839.  	    exercise(A_STR, TRUE);
840.  	    pline("WHAMMM!!!");
841.  	    if ((slev = Is_special(&u.uz)) && slev->flags.town)
842.  		for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
843.  		    if ((mtmp->data == &mons[PM_WATCHMAN] ||
844.  				mtmp->data == &mons[PM_WATCH_CAPTAIN]) &&
845.  			    mtmp->mpeaceful && couldsee(mtmp->mx, mtmp->my)) {
846.  			pline("%s yells:", Amonnam(mtmp));
847.  			if(levl[x][y].looted & D_WARNED) {
848.  			    verbalize("Halt, vandal!  You're under arrest!");
849.  			    (void) angry_guards(FALSE);
850.  			} else {
851.  			    verbalize("Hey, stop damaging that door!");
852.  			    levl[x][y].looted |= D_WARNED;
853.  			}
854.  			break;
855.  		    }
856.  		}
857.  	}
858.  	return(1);
859.  }
860.  
861.  static void
862.  drop_to(cc, loc)
863.  coord *cc;
864.  schar loc;
865.  {
866.  	/* cover all the MIGR_xxx choices generated by down_gate() */
867.  	switch (loc) {
868.  	 case MIGR_RANDOM:	/* trap door or hole */
869.  		    if (Is_stronghold(&u.uz)) {
870.  			cc->x = valley_level.dnum;
871.  			cc->y = valley_level.dlevel;
872.  			break;
873.  		    } else if (In_endgame(&u.uz) || Is_botlevel(&u.uz)) {
874.  			cc->y = cc->x = 0;
875.  			break;
876.  		    } /* else fall to the next cases */
877.  	 case MIGR_STAIRS_UP:
878.  	 case MIGR_LADDER_UP:
879.  		    cc->x = u.uz.dnum;
880.  		    cc->y = u.uz.dlevel + 1;
881.  		    break;
882.  	 case MIGR_SSTAIRS:
883.  		    cc->x = sstairs.tolev.dnum;
884.  		    cc->y = sstairs.tolev.dlevel;
885.  		    break;
886.  	 default:
887.  	 case MIGR_NOWHERE:
888.  		    /* y==0 means "nowhere", in which case x doesn't matter */
889.  		    cc->y = cc->x = 0;
890.  		    break;
891.  	}
892.  }
893.  
894.  void
895.  impact_drop(missile, x, y, dlev)
896.  struct obj *missile;
897.  xchar x, y, dlev;
898.  {
899.  	schar toloc;
900.  	register struct obj *obj, *obj2;
901.  	register struct monst *shkp;
902.  	long oct, dct, price, debit, robbed;
903.  	boolean angry, costly, isrock;
904.  	coord cc;
905.  
906.  	if(!OBJ_AT(x, y)) return;
907.  
908.  	toloc = down_gate(x, y);
909.  	drop_to(&cc, toloc);
910.  	if (!cc.y) return;
911.  
912.  	if (dlev) {
913.  		/* send objects next to player falling through trap door.
914.  		 * checked in obj_delivery().
915.  		 */
916.  		toloc = MIGR_NEAR_PLAYER;
917.  		cc.y = dlev;
918.  	}
919.  
920.  	costly = costly_spot(x, y);
921.  	price = debit = robbed = 0L;
922.  	angry = FALSE;
923.  	shkp = (struct monst *) 0;
924.  	/* if 'costly', we must keep a record of ESHK(shkp) before
925.  	 * it undergoes changes through the calls to stolen_value.
926.  	 * the angry bit must be reset, if needed, in this fn, since
927.  	 * stolen_value is called under the 'silent' flag to avoid
928.  	 * unsavory pline repetitions.
929.  	 */
930.  	if(costly) {
931.  	    if ((shkp = shop_keeper(*in_rooms(x, y, SHOPBASE))) != 0) {
932.  		debit	= ESHK(shkp)->debit;
933.  		robbed	= ESHK(shkp)->robbed;
934.  		angry	= !shkp->mpeaceful;
935.  	    }
936.  	}
937.  
938.  	isrock = (missile && missile->otyp == ROCK);
939.  	oct = dct = 0L;
940.  	for(obj = level.objects[x][y]; obj; obj = obj2) {
941.  		obj2 = obj->nexthere;
942.  		if(obj == missile) continue;
943.  		/* number of objects in the pile */
944.  		oct += obj->quan;
945.  		if(obj == uball || obj == uchain) continue;
946.  		/* boulders can fall too, but rarely & never due to rocks */
947.  		if((isrock && obj->otyp == BOULDER) ||
948.  		   rn2(obj->otyp == BOULDER ? 30 : 3)) continue;
949.  		obj_extract_self(obj);
950.  
951.  		if(costly) {
952.  		    price += stolen_value(obj, x, y,
953.  				(costly_spot(u.ux, u.uy) &&
954.  				 index(u.urooms, *in_rooms(x, y, SHOPBASE))),
955.  				TRUE);
956.  		    /* set obj->no_charge to 0 */
957.  		    if (Has_contents(obj))
958.  			picked_container(obj);	/* does the right thing */
959.  		    if (obj->oclass != GOLD_CLASS)
960.  			obj->no_charge = 0;
961.  		}
962.  
963.  		add_to_migration(obj);
964.  		obj->ox = cc.x;
965.  		obj->oy = cc.y;
966.  		obj->owornmask = (long)toloc;
967.  
968.  		/* number of fallen objects */
969.  		dct += obj->quan;
970.  	}
971.  
972.  	if (dct) {	/* at least one object fell */
973.  	    const char *what = (dct == 1L ? "object falls" : "objects fall");
974.  	    if (missile)
975.  		pline("From the impact, %sother %s.",
976.  			dct == oct ? "the " : dct == 1L ? "an" : "", what);
977.  	    else
978.  		if (oct == dct) {
979.  		    pline("%s adjacent %s %s.",
980.  			    dct == 1L ? "The" : "All the",
981.  			    what, gate_str);
982.  		} else {
983.  		    pline("%s adjacent %s %s.",
984.  			    dct == 1L ? "One of the" : "Some of the",
985.  			    dct == 1L ? "objects falls" : what,
986.  			    gate_str);
987.  		}
988.  	}
989.  
990.  	if(costly && shkp && price) {
991.  		if(ESHK(shkp)->robbed > robbed) {
992.  		    You("removed %ld zorkmids worth of goods!", price);
993.  		    if(cansee(shkp->mx, shkp->my)) {
994.  			if(ESHK(shkp)->customer[0] == 0)
995.  			    (void) strncpy(ESHK(shkp)->customer,
996.  					   plname, PL_NSIZ);
997.  			if(angry)
998.  			    pline("%s is infuriated!", Monnam(shkp));
999.  			else pline("\"%s, you are a thief!\"", plname);
1000. 		    } else  You_hear("a scream, \"Thief!\"");
1001. 		    hot_pursuit(shkp);
1002. 		    (void) angry_guards(FALSE);
1003. 		    return;
1004. 		}
1005. 		if(ESHK(shkp)->debit > debit)
1006. 		    You("owe %s %ld zorkmids for goods lost.",
1007. 			Monnam(shkp),
1008. 			(ESHK(shkp)->debit - debit));
1009. 	}
1010. 
1011. }
1012. 
1013. /* NOTE: ship_object assumes otmp was FREED from fobj or invent.
1014.  * <x,y> is the point of drop.  otmp is _not_ an <x,y> resident:
1015.  * otmp is either a kicked, dropped, or thrown object.
1016.  */
1017. boolean
1018. ship_object(otmp, x, y, shop_floor_obj)
1019. xchar  x, y;
1020. struct obj *otmp;
1021. boolean shop_floor_obj;
1022. {
1023. 	schar toloc;
1024. 	xchar ox, oy;
1025. 	coord cc;
1026. 	struct obj *obj;
1027. 	struct trap *t;
1028. 	boolean nodrop, unpaid, container, impact = FALSE;
1029. 	int n = 0;
1030. 
1031. 	if (!otmp) return(FALSE);
1032. 	if ((toloc = down_gate(x, y)) == MIGR_NOWHERE) return(FALSE);
1033. 	drop_to(&cc, toloc);
1034. 	if (!cc.y) return(FALSE);
1035. 
1036. 	/* objects other than attached iron ball always fall down ladder,
1037. 	   but have a chance of staying otherwise */
1038. 	nodrop = (otmp == uball) || (otmp == uchain) ||
1039. 			(toloc != MIGR_LADDER_UP && rn2(3));
1040. 
1041. 	container = Has_contents(otmp);
1042. 	unpaid = (otmp->unpaid || (container && count_unpaid(otmp->cobj)));
1043. 
1044. 	if(OBJ_AT(x, y)) {
1045. 	    for(obj = level.objects[x][y]; obj; obj = obj->nexthere)
1046. 		if(obj != otmp) n++;
1047. 	    if(n) impact = TRUE;
1048. 	}
1049. 	/* boulders never fall through trap doors, but they might knock
1050. 	   other things down before plugging the hole */
1051. 	if (otmp->otyp == BOULDER &&
1052. 		((t = t_at(x, y)) != 0) &&
1053. 		(t->ttyp == TRAPDOOR || t->ttyp == HOLE)) {
1054. 	    if (impact) impact_drop(otmp, x, y, 0);
1055. 	    return FALSE;		/* let caller finish the drop */
1056. 	}
1057. 
1058. 	otransit_msg(otmp, nodrop, n);
1059. 
1060. 	if (nodrop) {
1061. 	    if (impact) impact_drop(otmp, x, y, 0);
1062. 	    return(FALSE);
1063. 	}
1064. 
1065. 	if(unpaid || shop_floor_obj) {
1066. 	    if(unpaid) {
1067. 		subfrombill(otmp, shop_keeper(*u.ushops));
1068. 		(void)stolen_value(otmp, u.ux, u.uy, TRUE, FALSE);
1069. 	    } else {
1070. 		ox = otmp->ox;
1071. 		oy = otmp->oy;
1072. 		(void)stolen_value(otmp, ox, oy,
1073. 			  (costly_spot(u.ux, u.uy) &&
1074. 			      index(u.urooms, *in_rooms(ox, oy, SHOPBASE))),
1075. 			  FALSE);
1076. 	    }
1077. 	    /* set otmp->no_charge to 0 */
1078. 	    if(container)
1079. 		picked_container(otmp); /* happens to do the right thing */
1080. 	    if(otmp->oclass != GOLD_CLASS)
1081. 		otmp->no_charge = 0;
1082. 	}
1083. 
1084. 	add_to_migration(otmp);
1085. 	otmp->ox = cc.x;
1086. 	otmp->oy = cc.y;
1087. 	otmp->owornmask = (long)toloc;
1088. 
1089. 	if(impact) {
1090. 	    /* the objs impacted may be in a shop other than
1091. 	     * the one in which the hero is located.  another
1092. 	     * check for a shk is made in impact_drop.  it is, e.g.,
1093. 	     * possible to kick/throw an object belonging to one
1094. 	     * shop into another shop through a gap in the wall,
1095. 	     * and cause objects belonging to the other shop to
1096. 	     * fall down a trapdoor--thereby getting two shopkeepers
1097. 	     * angry at the hero in one shot.
1098. 	     */
1099. 	    impact_drop(otmp, x, y, 0);
1100. 	    newsym(x,y);
1101. 	}
1102. 	return(TRUE);
1103. }
1104. 
1105. void
1106. obj_delivery()
1107. {
1108. 	register struct obj *otmp, *otmp2;
1109. 	register int nx, ny;
1110. 	long where;
1111. 
1112. 	for (otmp = migrating_objs; otmp; otmp = otmp2) {
1113. 	    otmp2 = otmp->nobj;
1114. 	    if (otmp->ox != u.uz.dnum || otmp->oy != u.uz.dlevel) continue;
1115. 
1116. 	    obj_extract_self(otmp);
1117. 	    where = otmp->owornmask;		/* destination code */
1118. 	    otmp->owornmask = 0L;
1119. 
1120. 	    switch ((int)where) {
1121. 	     case MIGR_STAIRS_UP:   nx = xupstair,  ny = yupstair;
1122. 				break;
1123. 	     case MIGR_LADDER_UP:   nx = xupladder,  ny = yupladder;
1124. 				break;
1125. 	     case MIGR_SSTAIRS:	    nx = sstairs.sx,  ny = sstairs.sy;
1126. 				break;
1127. 	     case MIGR_NEAR_PLAYER: nx = u.ux,  ny = u.uy;
1128. 				break;
1129. 	     default:
1130. 	     case MIGR_RANDOM:	    nx = ny = 0;
1131. 				break;
1132. 	    }
1133. 	    if (nx > 0) {
1134. 		place_object(otmp, nx, ny);
1135. 		stackobj(otmp);
1136. 		scatter(nx, ny, rnd(2), 0);
1137. 	    } else {		/* random location */
1138. 		/* set dummy coordinates because there's no
1139. 		   current position for rloco() to update */
1140. 		otmp->ox = otmp->oy = 0;
1141. 		rloco(otmp);
1142. 	    }
1143. 	}
1144. }
1145. 
1146. static void
1147. otransit_msg(otmp, nodrop, num)
1148. register struct obj *otmp;
1149. register boolean nodrop;
1150. int num;
1151. {
1152. 	char obuf[BUFSZ];
1153. 
1154. 	Sprintf(obuf, "%s%s",
1155. 		 (otmp->otyp == CORPSE &&
1156. 			type_is_pname(&mons[otmp->corpsenm])) ? "" : "The ",
1157. 		 xname(otmp));
1158. 
1159. 	if(num) { /* means: other objects are impacted */
1160. 	    Sprintf(eos(obuf), " hit%s %s object%s",
1161. 		      otmp->quan == 1L ? "s" : "",
1162. 		      num == 1 ? "another" : "other",
1163. 		      num > 1 ? "s" : "");
1164. 	    if(nodrop)
1165. 		Sprintf(eos(obuf), " and stop%s.",
1166. 			otmp->quan == 1L ? "s" : "");
1167. 	    else
1168. 		Sprintf(eos(obuf), " and fall%s %s.",
1169. 			otmp->quan == 1L ? "s" : "", gate_str);
1170. 	    pline(obuf);
1171. 	} else if(!nodrop)
1172. 	    pline("%s fall%s %s.", obuf,
1173. 		  otmp->quan == 1L ? "s" : "", gate_str);
1174. }
1175. 
1176. /* migration destination for objects which fall down to next level */
1177. schar
1178. down_gate(x, y)
1179. xchar x, y;
1180. {
1181. 	struct trap *ttmp;
1182. 
1183. 	gate_str = 0;
1184. 	/* this matches the player restriction in goto_level() */
1185. 	if (on_level(&u.uz, &qstart_level) && !ok_to_quest())
1186. 	    return MIGR_NOWHERE;
1187. 
1188. 	if ((xdnstair == x && ydnstair == y) ||
1189. 		(sstairs.sx == x && sstairs.sy == y && !sstairs.up)) {
1190. 	    gate_str = "down the stairs";
1191. 	    return (xdnstair == x && ydnstair == y) ?
1192. 		    MIGR_STAIRS_UP : MIGR_SSTAIRS;
1193. 	}
1194. 	if (xdnladder == x && ydnladder == y) {
1195. 	    gate_str = "down the ladder";
1196. 	    return MIGR_LADDER_UP;
1197. 	}
1198. 
1199. 	if (((ttmp = t_at(x, y)) != 0 && ttmp->tseen) &&
1200. 		(ttmp->ttyp == TRAPDOOR || ttmp->ttyp == HOLE)) {
1201. 	    gate_str = (ttmp->ttyp == TRAPDOOR) ?
1202. 		    "through the trap door" : "through the hole";
1203. 	    return MIGR_RANDOM;
1204. 	}
1205. 	return MIGR_NOWHERE;
1206. }
1207. 
1208. /*dokick.c*/

Also on Fandom

Random Wiki