Source:NetHack 3.4.0/dokick.c

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