Source:NetHack 3.2.0/dokick.c

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

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; imattk[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. *  is the point of drop. otmp is _not_ an  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*/