Source:NetHack 3.2.0/mthrowu.c

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

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

1.   /*	SCCS Id: @(#)mthrowu.c	3.2	96/03/15	*/ 2.   /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 3.    /* NetHack may be freely redistributed. See license for details. */ 4.     5.    #include "hack.h"  6. 7.   STATIC_DCL int FDECL(drop_throw,(struct obj *,BOOLEAN_P,int,int)); 8.    9.    #define URETREATING(x,y) (distmin(u.ux,u.uy,x,y) > distmin(u.ux0,u.uy0,x,y)) 10.   11.   #ifndef OVLB 12.   13.   STATIC_DCL const char *breathwep[]; 14.   15.   #else /* OVLB */ 16.   17.   /*  18.    * Keep consistent with breath weapons in zap.c, and AD_* in monattk.h.  19. */ 20.   STATIC_OVL NEARDATA const char *breathwep[] = { 21.  				"fragments", 22.  				"fire", 23.  				"frost", 24.  				"sleep gas", 25.  				"a disintegration blast", 26.  				"lightning", 27.  				"poison gas", 28.  				"acid", 29.  				"strange breath #8", 30.  				"strange breath #9" 31.  };  32.    33.   int 34.  thitu(tlev, dam, obj, name)	/* u is hit by sth, but not a monster */ 35.  	register int tlev, dam; 36.  	struct obj *obj; 37.  	register const char *name; 38.  {  39.   	const char *onm = (obj && obj_is_pname(obj)) ? the(name) : an(name); 40.  	boolean is_acid = (obj && obj->otyp == ACID_VENOM); 41.   42.   	if(u.uac + tlev <= rnd(20)) { 43.  		if(Blind || !flags.verbose) pline("It misses."); 44.  		else You("are almost hit by %s!", onm); 45.  		return(0); 46.  	} else { 47.  		if(Blind || !flags.verbose) You("are hit!"); 48.  		else You("are hit by %s!", onm); 49.   50.   		if (obj && objects[obj->otyp].oc_material == SILVER  51.   				&& hates_silver(uasmon)) { 52.  			dam += rnd(20); 53.  			pline_The("silver sears your flesh!"); 54.  			exercise(A_CON, FALSE); 55.  		}  56.   		if (is_acid && resists_acid(&youmonst)) 57.  			pline("It doesn't seem to hurt you."); 58.  		else { 59.  			if (is_acid) pline("It burns!"); 60.  			if (Half_physical_damage) dam = (dam+1) / 2; 61.  			losehp(dam, name, (obj && obj_is_pname(obj)) ?  62.   			       KILLED_BY : KILLED_BY_AN); 63.  			exercise(A_STR, FALSE); 64.  		}  65.   		return(1); 66.  	}  67.   }  68.    69.   /* Be sure this corresponds with what happens to player-thrown objects in  70. * dothrow.c (for consistency). --KAA 71.   * Returns 0 if object still exists (not destroyed). 72.   */  73.    74.   STATIC_OVL int 75.  drop_throw(obj, ohit, x, y)  76. register struct obj *obj; 77.  boolean ohit; 78.  int x,y; 79.  {  80.   	int retvalu = 1; 81.  	int create; 82.  	struct monst *mtmp; 83.  	struct trap *t; 84.   85.   	if (obj->otyp == CREAM_PIE || obj->oclass == VENOM_CLASS ||  86.   		    (ohit && obj->otyp == EGG)) 87.  		create = 0; 88.  	else if (ohit &&  89.   		 ((obj->otyp >= ARROW && obj->otyp <= SHURIKEN) || 90.  		  obj->otyp == ROCK)) 91.  		create = !rn2(3); 92.  	else create = 1; 93.   94.   	if (create && !((mtmp = m_at(x, y)) && (mtmp->mtrapped) && 95.  			(t = t_at(x, y)) && ((t->ttyp == PIT) ||  96.   			(t->ttyp == SPIKED_PIT)))) { 97.  		int objgone = 0; 98.   99.   		if (down_gate(x, y) != -1) 100. 			objgone = ship_object(obj, x, y, FALSE); 101. 		if (!objgone) { 102. 			if (!flooreffects(obj,x,y,"fall")) { /* don't double-dip on damage */ 103. 			    place_object(obj, x, y); 104. 			    stackobj(obj); 105. 			    retvalu = 0; 106. 			}  107.  		}  108.  	} else obfree(obj, (struct obj*) 0); 109. 	return retvalu; 110. }  111.   112.  #endif /* OVLB */ 113. #ifdef OVL1 114.  115.  /* an object launched by someone/thing other than player attacks a monster; 116.    return 1 if the object has stopped moving (hit or its range used up) */ 117. int 118. ohitmon(mtmp, otmp, range, verbose) 119. struct monst *mtmp;	/* accidental target */ 120. struct obj *otmp;	/* missile; might be destroyed by drop_throw */ 121. int range;		/* how much farther will object travel if it misses */ 122. 			/* Use -1 to signify to keep going even after hit, */ 123. 			/* unless its gone (used for rolling_boulder_traps) */ 124. boolean verbose;  /* give message(s) even when you can't see what happened */ 125. {  126.  	int damage, tmp; 127. 	boolean vis, ismimic; 128. 	int objgone = 1; 129.  130.  	ismimic = mtmp->m_ap_type && mtmp->m_ap_type != M_AP_MONSTER; 131. 	vis = cansee(bhitpos.x, bhitpos.y); 132.  133.  	tmp = 5 + find_mac(mtmp) + omon_adj(mtmp, otmp, FALSE); 134. 	if (tmp < rnd(20)) { 135. 	    if (!ismimic) { 136. 		if (vis) miss(distant_name(otmp, xname), mtmp); 137. 		else if (verbose) pline("It is missed."); 138. 	    }  139.  	    if (!range) { /* Last position; object drops */ 140. 		(void) drop_throw(otmp, 0, mtmp->mx, mtmp->my); 141. 		return 1; 142. 	    }  143.  	} else if (otmp->oclass == POTION_CLASS) { 144. 	    if (ismimic) seemimic(mtmp); 145. 	    mtmp->msleep = 0; 146. 	    if (vis) otmp->dknown = 1; 147. 	    potionhit(mtmp, otmp); 148. 	    return 1; 149. 	} else { 150. 	    damage = dmgval(otmp, mtmp); 151. 	    if (damage < 1) damage = 1; 152. 	    if (otmp->otyp == ACID_VENOM && resists_acid(mtmp)) 153. 		damage = 0; 154. 	    if (ismimic) seemimic(mtmp); 155. 	    mtmp->msleep = 0; 156. 	    if (vis) hit(distant_name(otmp,xname), mtmp, exclam(damage)); 157. 	    else if (verbose) pline("It is hit%s", exclam(damage)); 158.  159.  	    if (otmp->opoisoned) { 160. 		if (resists_poison(mtmp)) { 161. 		    if (vis) pline_The("poison doesn't seem to affect %s.",  162.  				   mon_nam(mtmp)); 163. 		} else { 164. 		    if (rn2(30)) { 165. 			damage += rnd(6); 166. 		    } else { 167. 			if (vis) pline_The("poison was deadly..."); 168. 			damage = mtmp->mhp; 169. 		    }  170.  		}  171.  	    }  172.  	    if (objects[otmp->otyp].oc_material == SILVER &&  173.  		    hates_silver(mtmp->data)) { 174. 		if (vis) pline_The("silver sears %s flesh!",  175.  				s_suffix(mon_nam(mtmp))); 176. 		else if (verbose) pline("Its flesh is seared!"); 177. 	    }  178.  	    if (otmp->otyp == ACID_VENOM && cansee(mtmp->mx,mtmp->my)) { 179. 		if (resists_acid(mtmp)) { 180. 		    if (vis || verbose) 181. 			pline("%s is unaffected.", Monnam(mtmp)); 182. 		    damage = 0; 183. 		} else { 184. 		    if (vis) pline_The("acid burns %s!", mon_nam(mtmp)); 185. 		    else if (verbose) pline("It is burned!"); 186. 		}  187.  	    }  188.  	    mtmp->mhp -= damage; 189. 	    if (mtmp->mhp < 1) { 190. 		if (vis || verbose) 191. 		    pline("%s is %s!", Monnam(mtmp),  192.  			(nonliving(mtmp->data) || !vis)  193.  			? "destroyed" : "killed"); 194. 		mondied(mtmp); 195. 	    }  196.   197.  	    if ((otmp->otyp == CREAM_PIE || otmp->otyp == BLINDING_VENOM) &&  198.  		   haseyes(mtmp->data)) { 199. 		if (vis) pline("%s is blinded by %s.",  200.  				Monnam(mtmp), the(xname(otmp))); 201. 		mtmp->mcansee = 0; 202. 		tmp = (int)mtmp->mblinded + rnd(25) + 20; 203. 		if (tmp > 127) tmp = 127; 204. 		mtmp->mblinded = tmp; 205. 	    }  206.   207.  	    objgone = drop_throw(otmp, 1, bhitpos.x, bhitpos.y); 208. 	    if (!objgone && range == -1) {  /* special case */ 209. 		    obj_extract_self(otmp); /* free it for motion again */ 210. 		    return 0; 211. 	    }  212.  	    return 1; 213. 	}  214.  	return 0; 215. }  216.   217.  void 218. m_throw(mon, x, y, dx, dy, range, obj) 219. 	register struct monst *mon; 220. 	register int x,y,dx,dy,range;		/* direction and range */ 221. 	register struct obj *obj; 222. {  223.  	register struct monst *mtmp; 224. 	struct obj *singleobj; 225. 	char sym = obj->oclass; 226. 	int hitu, blindinc = 0; 227.  228.  	bhitpos.x = x;  229. bhitpos.y = y; 230. 231. 	if (obj->quan == 1L) { 232. 	    /*  233.  	     * Remove object from minvent. This cannot be done later on; 234. 	     * what if the player dies before then, leaving the monster 235. 	     * with 0 daggers? (This caused the infamous 2^32-1 orcish 236.  	     * dagger bug). 237. 	     *  238.  	     * VENOM is not in minvent - it should already be OBJ_FREE. 239. 	     * The extract below does nothing. 240. 	     */  241.   242.  	    /* not possibly_unwield, which checks the object's */ 243. 	    /* location, not its existence */ 244. 	    if (MON_WEP(mon) == obj) { 245. 		    obj->owornmask &= ~W_WEP; 246. 		    MON_NOWEP(mon); 247. 	    }  248.  	    obj_extract_self(obj); 249. 	    singleobj = obj; 250. 	    obj = (struct obj *) 0; 251. 	} else { 252. 	    singleobj = splitobj(obj, obj->quan - 1L); 253. 	    obj_extract_self(singleobj); 254. 	}  255.   256.  	singleobj->owornmask = 0; /* threw one of multiple weapons in hand? */ 257.   258.  	if (singleobj->cursed && (dx || dy) && !rn2(7)) { 259. 	    if(canseemon(mon) && flags.verbose) { 260. 		if((singleobj->oclass == WEAPON_CLASS || 261. 						singleobj->oclass == GEM_CLASS)  262.  		   && objects[singleobj->otyp].w_propellor) 263. 		    pline("%s misfires!", Monnam(mon)); 264. 		else 265. 		    pline("%s slips as %s throws it!",  266.  			  The(xname(singleobj)), mon_nam(mon)); 267. 	    }  268.  	    dx = rn2(3)-1; 269. 	    dy = rn2(3)-1; 270. 	    /* pre-check validity of new direction */ 271. 	    if((!dx && !dy)  272.  	       || !isok(bhitpos.x+dx,bhitpos.y+dy)  273.  	       /* missile hits the wall */  274.  	       || IS_ROCK(levl[bhitpos.x+dx][bhitpos.y+dy].typ)) { 275. 		(void) drop_throw(singleobj, 0, bhitpos.x, bhitpos.y); 276. 		return; 277. 	    }  278.  	}  279.   280.  	/* Note: drop_throw may destroy singleobj. Since obj must be destroyed 281. 	 * early to avoid the dagger bug, anyone who modifies this code should 282. 	 * be careful not to use either one after it's been freed. 283. 	 */  284.  	if (sym) tmp_at(DISP_FLASH, obj_to_glyph(singleobj)); 285. 	while(range-- > 0) { /* Actually the loop is always exited by break */ 286. 		bhitpos.x += dx; 287. 		bhitpos.y += dy; 288. 		if ((mtmp = m_at(bhitpos.x, bhitpos.y)) != 0) { 289. 		    if (ohitmon(mtmp, singleobj, range, TRUE)) 290. 			break; 291. 		} else if (bhitpos.x == u.ux && bhitpos.y == u.uy) { 292. 			if (multi) nomul(0); 293.  294.  			if (singleobj->oclass == POTION_CLASS) { 295. 			    if (!Blind) singleobj->dknown = 1; 296. 			    potionhit(&youmonst, singleobj); 297. 			    break; 298. 			}  299.  			switch(singleobj->otyp) { 300. 			    int dam, hitv; 301. 			    case CREAM_PIE: 302. 			    case BLINDING_VENOM: 303. 				hitu = thitu(8, 0, singleobj, xname(singleobj)); 304. 				break; 305. 			    default: 306. 				dam = dmgval(singleobj, &youmonst); 307. 				hitv = 3 - distmin(u.ux,u.uy, mon->mx,mon->my); 308. 				if (hitv < -4) hitv = -4; 309. 				if (is_elf(mon->data) &&  310.  				    objects[singleobj->otyp].w_propellor  311.  								== WP_BOW) { 312. 				    hitv++; 313. 				    if (MON_WEP(mon) &&  314.  					MON_WEP(mon)->otyp == ELVEN_BOW) 315. 					hitv++; 316. 				    if(singleobj->otyp == ELVEN_ARROW) dam++; 317. 				}  318.  				if (bigmonst(uasmon)) hitv++; 319. 				hitv += 8+singleobj->spe; 320.  321.  				if (dam < 1) dam = 1; 322. 				hitu = thitu(hitv, dam,  323.  					singleobj, xname(singleobj)); 324. 			}  325.  			if (hitu && singleobj->opoisoned) { 326. 			    char *singlename = xname(singleobj); 327. 			    poisoned(singlename, A_STR, singlename, 10); 328. 			}  329.  			if(hitu && (singleobj->otyp == CREAM_PIE || 330. 				     singleobj->otyp == BLINDING_VENOM)) { 331. 			    blindinc = rnd(25); 332. 			    if(singleobj->otyp == CREAM_PIE) { 333. 				if(!Blind) pline("Yecch!  You've been creamed."); 334. 				else	pline("There's %s sticky all over your %s.",  335.  						something,  336.  						body_part(FACE)); 337. 			    } else {	/* venom in the eyes */ 338. 				if(Blindfolded) /* nothing */ ; 339. 				else if(!Blind) pline_The("venom blinds you."); 340. 				else	Your("%s sting.",  341.  					makeplural(body_part(EYE))); 342. 			    }  343.  			}  344.  			stop_occupation; 345. 			if (hitu || !range) { 346. 			    (void) drop_throw(singleobj, hitu, u.ux, u.uy); 347. 			    break; 348. 			}  349.  		} else if (!range	/* reached end of path */  350.  			/* missile hits edge of screen */  351.  			|| !isok(bhitpos.x+dx,bhitpos.y+dy)  352.  			/* missile hits the wall */  353.  			|| IS_ROCK(levl[bhitpos.x+dx][bhitpos.y+dy].typ)  354.  #ifdef SINKS  355.  			/* Thrown objects "sink" */  356.  			|| IS_SINK(levl[bhitpos.x][bhitpos.y].typ)  357.  #endif  358.  								) { 359. 		    (void) drop_throw(singleobj, 0, bhitpos.x, bhitpos.y); 360. 		    break; 361. 		}  362.  		tmp_at(bhitpos.x, bhitpos.y); 363. 		delay_output; 364. 	}  365.  	tmp_at(bhitpos.x, bhitpos.y); 366. 	delay_output; 367. 	tmp_at(DISP_END, 0); 368. 	/* blindfold keeps substances out of your eyes */ 369. 	if (blindinc && !Blindfolded) { 370. 		u.ucreamed += blindinc; 371. 		make_blinded(Blinded + blindinc,FALSE); 372. 	}  373.  }  374.   375.  #endif /* OVL1 */ 376. #ifdef OVLB 377.  378.  /* Remove an item from the monster's inventory and destroy it. */ 379.  void 380. m_useup(mon, obj) 381. struct monst *mon; 382. struct obj *obj; 383. {  384.  	if (obj->quan > 1L) { 385. 		obj->quan--; 386. 	} else { 387. 		obj_extract_self(obj); 388. 		possibly_unwield(mon); 389. 		if (obj->owornmask) { 390. 		    mon->misc_worn_check &= ~obj->owornmask; 391. 		    update_mon_intrinsics(mon, obj, FALSE); 392. 		}  393.  		dealloc_obj(obj); 394. 	}  395.  }  396.   397.  #endif /* OVLB */ 398. #ifdef OVL1 399.  400.  void 401. thrwmu(mtmp)	/* monster throws item at you */ 402. register struct monst *mtmp; 403. {  404.  	struct obj *otmp; 405. 	register xchar x, y;  406. 407. 	if(lined_up(mtmp)) { 408. 	    if (mtmp->weapon_check == NEED_WEAPON || !MON_WEP(mtmp)) { 409. 		mtmp->weapon_check = NEED_RANGED_WEAPON; 410. 		/* mon_wield_item resets weapon_check as appropriate */ 411. 		if(mon_wield_item(mtmp) != 0) return; 412. 	    }  413.  	    otmp = select_rwep(mtmp); 414. 	    if (otmp) { 415. 		/* If you are coming toward the monster, the monster 416. 		 * should try to soften you up with missiles. If you are 417. 		 * going away, you are probably hurt or running. Give 418. 		 * chase, but if you are getting too far away, throw. 419. 		 */  420.  		x = mtmp->mx; 421. 		y = mtmp->my; 422. 		if(!URETREATING(x,y) ||  423.  		   !rn2(BOLT_LIM-distmin(x,y,mtmp->mux,mtmp->muy))) 424. 		{  425.  		    const char *verb = "throws"; 426.  427.  		    if (otmp->otyp == ARROW  428.  			|| otmp->otyp == ELVEN_ARROW  429.  			|| otmp->otyp == ORCISH_ARROW  430.  			|| otmp->otyp == CROSSBOW_BOLT) verb = "shoots"; 431. 		    if (canseemon(mtmp)) { 432. 			pline("%s %s %s!", Monnam(mtmp), verb,  433.  			      obj_is_pname(otmp) ?  434.  			      the(singular(otmp, xname)) :  435.  			      an(singular(otmp, xname))); 436. 		    }  437.  		    m_throw(mtmp, mtmp->mx, mtmp->my, sgn(tbx), sgn(tby),  438.  			distmin(mtmp->mx,mtmp->my,mtmp->mux,mtmp->muy), otmp); 439. 		    nomul(0); 440. 		    return; 441. 		}  442.  	    }  443.  	}  444.  }  445.   446.  #endif /* OVL1 */ 447. #ifdef OVLB 448.  449.  int 450. spitmu(mtmp, mattk)		/* monster spits substance at you */ 451. register struct monst *mtmp; 452. register struct attack *mattk; 453. {  454.  	register struct obj *otmp; 455.  456.  	if(mtmp->mcan) { 457.  458.  	    if(flags.soundok) 459. 		pline("A dry rattle comes from %s throat",  460.  		                      s_suffix(mon_nam(mtmp))); 461. 	    return 0; 462. 	}  463.  	if(lined_up(mtmp)) { 464. 		switch (mattk->adtyp) { 465. 		    case AD_BLND: 466. 		    case AD_DRST: 467. 			otmp = mksobj(BLINDING_VENOM, TRUE, FALSE); 468. 			break; 469. 		    default: 470. 			impossible("bad attack type in spitmu"); 471. 				/* fall through */ 472. 		    case AD_ACID: 473. 			otmp = mksobj(ACID_VENOM, TRUE, FALSE); 474. 			break; 475. 		}  476.  		if(!rn2(BOLT_LIM-distmin(mtmp->mx,mtmp->my,mtmp->mux,mtmp->muy))) { 477. 		    if (canseemon(mtmp)) 478. 			pline("%s spits venom!", Monnam(mtmp)); 479. 		    m_throw(mtmp, mtmp->mx, mtmp->my, sgn(tbx), sgn(tby),  480.  			distmin(mtmp->mx,mtmp->my,mtmp->mux,mtmp->muy), otmp); 481. 		    nomul(0); 482. 		    return 0; 483. 		}  484.  	}  485.  	return 0; 486. }  487.   488.  #endif /* OVLB */ 489. #ifdef OVL1 490.  491.  int 492. breamu(mtmp, mattk)			/* monster breathes at you (ranged) */ 493. 	register struct monst *mtmp; 494. 	register struct attack  *mattk; 495. {  496.  	/* if new breath types are added, change AD_ACID to max type */ 497. 	int typ = (mattk->adtyp == AD_RBRE) ? rnd(AD_ACID) : mattk->adtyp ; 498.  499.  	if(lined_up(mtmp)) { 500.  501.  	    if(mtmp->mcan) { 502. 		if(flags.soundok) { 503. 		    if(canseemon(mtmp)) 504. 			pline("%s coughs.", Monnam(mtmp)); 505. 		    else 506. 			You_hear("a cough."); 507. 		}  508.  		return(0); 509. 	    }  510.  	    if(!mtmp->mspec_used && rn2(3)) { 511.  512.  		if((typ >= AD_MAGM) && (typ <= AD_ACID)) { 513.  514.  		    if(canseemon(mtmp)) 515. 			pline("%s breathes %s!", Monnam(mtmp),  516.  			      breathwep[typ-1]); 517. 		    buzz((int) (-20 - (typ-1)), (int)mattk->damn,  518.  			 mtmp->mx, mtmp->my, sgn(tbx), sgn(tby)); 519. 		    nomul(0); 520. 		    /* breath runs out sometimes. Also, give monster some 521. 		     * cunning; don't breath if the player fell asleep. 522. 		     */  523.  		    if(!rn2(3)) 524. 			mtmp->mspec_used = 10+rn2(20); 525. 		    if(typ == AD_SLEE && !Sleep_resistance) 526. 			mtmp->mspec_used += rnd(20); 527. 		} else impossible("Breath weapon %d used", typ-1); 528. 	    }  529.  	}  530.  	return(1); 531. }  532.   533.  boolean 534. linedup(ax, ay, bx, by) 535. register xchar ax, ay, bx, by; 536. {  537.  	tbx = ax - bx;	/* These two values are set for use */ 538. 	tby = ay - by;	/* after successful return. */ 539.   540.  	/* sometimes displacement makes a monster think that you're at its 541. 	   own location; prevent it from throwing and zapping in that case */ 542. 	if (!tbx && !tby) return FALSE; 543.  544.  	if((!tbx || !tby || abs(tbx) == abs(tby)) /* straight line or diagonal */  545.  	   && distmin(tbx, tby, 0, 0) < BOLT_LIM) { 546. 	    if(ax == u.ux && ay == u.uy) return((boolean)(couldsee(bx,by))); 547. 	    else if(clear_path(ax,ay,bx,by)) return TRUE; 548. 	}  549.  	return FALSE; 550. }  551.   552.  boolean 553. lined_up(mtmp)		/* is mtmp in position to use ranged attack? */ 554.  	register struct monst *mtmp; 555. {  556.  	return(linedup(mtmp->mux,mtmp->muy,mtmp->mx,mtmp->my)); 557. }  558.   559.  #endif /* OVL1 */ 560. #ifdef OVL0 561.  562.  /* Check if a monster is carrying a particular item. 563.  */  564.  struct obj * 565. m_carrying(mtmp, type) 566. struct monst *mtmp; 567. int type; 568. {  569.  	register struct obj *otmp; 570.  571.  	for(otmp = mtmp->minvent; otmp; otmp = otmp->nobj) 572. 		if(otmp->otyp == type) 573. 			return(otmp); 574. 	return((struct obj *) 0); 575. }  576.   577.  #endif /* OVL0 */ 578.  579.  /*mthrowu.c*/