Fandom

Wikihack

Source:SLASH'EM 0.0.7E7F2/mthrowu.c

2,034pages on
this wiki
Add New Page
Talk0

Ad blocker interference detected!


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

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

Below is the full text to mthrowu.c from the source code of SLASH'EM 0.0.7E7F2. To link to a particular line, write [[SLASH'EM 0.0.7E7F2/mthrowu.c#line123]], for example.

The latest source code for vanilla NetHack is at Source code.


The NetHack General Public License applies to screenshots, source code and other content from NetHack.
1.    /*	SCCS Id: @(#)mthrowu.c	3.4	2003/05/09	*/
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 monst *, 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.   #define POLE_LIM 5	/* How far monsters can use pole-weapons */
12.   
13.   #ifndef OVLB
14.   
15.   const char *breathwep[];
16.   
17.   #else /* OVLB */
18.   
19.   /*
20.    * Keep consistent with breath weapons in zap.c, and AD_* in monattk.h.
21.    */
22.   NEARDATA const char *breathwep[] = {
23.   				"fragments",
24.   				"fire",
25.   				"frost",
26.   				"sleep gas",
27.   				"a disintegration blast",
28.   				"lightning",
29.   				"poison gas",
30.   				"acid",
31.   				"strange breath #8",
32.   				"strange breath #9"
33.   };
34.   
35.   /* hero is hit by something other than a monster */
36.   int
37.   thitu(tlev, dam, obj, name)
38.   int tlev, dam;
39.   struct obj *obj;
40.   const char *name;	/* if null, then format `obj' */
41.   {
42.   	const char *onm, *knm;
43.   	boolean is_acid;
44.   	int kprefix = KILLED_BY_AN;
45.   	char onmbuf[BUFSZ], knmbuf[BUFSZ];
46.   
47.   	if (!name) {
48.   	    if (!obj) panic("thitu: name & obj both null?");
49.   	    name = strcpy(onmbuf,
50.   			 (obj->quan > 1L) ? doname(obj) : mshot_xname(obj));
51.   	    knm = strcpy(knmbuf, killer_xname(obj));
52.   	    kprefix = KILLED_BY;  /* killer_name supplies "an" if warranted */
53.   	} else {
54.   	    knm = name;
55.   	    /* [perhaps ought to check for plural here to] */
56.   	    if (!strncmpi(name, "the ", 4) ||
57.   		    !strncmpi(name, "an ", 3) ||
58.   		    !strncmpi(name, "a ", 2)) kprefix = KILLED_BY;
59.   	}
60.   	onm = (obj && obj_is_pname(obj)) ? the(name) :
61.   			    (obj && obj->quan > 1L) ? name : an(name);
62.   	is_acid = (obj && obj->otyp == ACID_VENOM);
63.   
64.   	if(u.uac + tlev <= rnd(20)) {
65.   		if(Blind || !flags.verbose) pline("It misses.");
66.   		else You("are almost hit by %s.", onm);
67.   		return(0);
68.   	} else {
69.   		if(Blind || !flags.verbose) You("are hit!");
70.   		else You("are hit by %s%s", onm, exclam(dam));
71.   
72.   		if (obj && objects[obj->otyp].oc_material == SILVER
73.   				&& hates_silver(youmonst.data)) {
74.   			dam += rnd(20);
75.   			pline_The("silver sears your flesh!");
76.   			exercise(A_CON, FALSE);
77.   		}
78.   		if (is_acid && Acid_resistance)
79.   			pline("It doesn't seem to hurt you.");
80.   		else {
81.   			if (is_acid) pline("It burns!");
82.   			if (Half_physical_damage) dam = (dam+1) / 2;
83.   			losehp(dam, knm, kprefix);
84.   			exercise(A_STR, FALSE);
85.   		}
86.   		return(1);
87.   	}
88.   }
89.   
90.   /* Be sure this corresponds with what happens to player-thrown objects in
91.    * dothrow.c (for consistency). --KAA
92.    * Returns 0 if object still exists (not destroyed).
93.    */
94.   
95.   STATIC_OVL int
96.   drop_throw(mon, obj, ohit, x, y)
97.   register struct monst *mon;
98.   register struct obj *obj;
99.   boolean ohit;
100.  int x,y;
101.  {
102.  	struct obj *mwep = (struct obj *) 0;
103.  	
104.  	int retvalu = 1;
105.  	int create;
106.  	struct monst *mtmp;
107.  	struct trap *t;
108.  
109.  	if (mon) mwep = MON_WEP(mon);
110.  
111.  	if (obj->otyp == CREAM_PIE || obj->oclass == VENOM_CLASS ||
112.  /* WAC added Spoon throw code */
113.  # ifdef P_SPOON
114.                      (obj->oartifact == ART_HOUCHOU) ||
115.  # endif
116.  #ifdef FIREARMS
117.  		    /* WAC -- assume monsters don't throw without 
118.  		    	using the right propellor */
119.                      (is_bullet(obj)) ||
120.  #endif
121.  		    (ohit && obj->otyp == EGG))
122.  		create = 0;
123.  	else if (ohit && (is_multigen(obj) || obj->otyp == ROCK))
124.  		create = !rn2(3);
125.  	else create = 1;
126.  
127.  #ifdef FIREARMS
128.  	/* Detonate rockets */
129.  	if (is_grenade(obj)) {
130.  		if (!ohit) {
131.  			create = 1; /* Don't destroy */
132.  			arm_bomb(obj, FALSE);
133.  		} else {
134.  			grenade_explode(obj, bhitpos.x, bhitpos.y, FALSE, 0);
135.  			obj = (struct obj *)0;
136.  		}
137.  	} else if (objects[obj->otyp].oc_dir & EXPLOSION) {
138.  	    	if (cansee(bhitpos.x,bhitpos.y)) 
139.  	    		pline("%s explodes in a ball of fire!", Doname2(obj));
140.  	    	else You_hear("an explosion");
141.  		explode(bhitpos.x, bhitpos.y, -ZT_SPELL(ZT_FIRE), d(3,8),
142.  		    WEAPON_CLASS, EXPL_FIERY);
143.  	}
144.  #endif
145.  
146.  	/* D: Detonate crossbow bolts from Hellfire if they hit */
147.  	if (ohit && mwep && mwep->oartifact == ART_HELLFIRE
148.  		  && is_ammo(obj) && ammo_and_launcher(obj, mwep)) {
149.  	  
150.  		if (cansee(bhitpos.x,bhitpos.y)) 
151.  			pline("%s explodes in a ball of fire!", Doname2(obj));
152.  		else 
153.  			You_hear("an explosion");
154.  
155.  		explode(bhitpos.x, bhitpos.y, -ZT_SPELL(ZT_FIRE),
156.  		    d(2,6), WEAPON_CLASS, EXPL_FIERY);
157.  
158.  		/* D: Exploding bolts will be destroyed */
159.  		create = 0;
160.  	}
161.  
162.  	if (create && !((mtmp = m_at(x, y)) && (mtmp->mtrapped) &&
163.  			(t = t_at(x, y)) && ((t->ttyp == PIT) ||
164.  			(t->ttyp == SPIKED_PIT)))) {
165.  		int objgone = 0;
166.  
167.  		if (down_gate(x, y) != -1)
168.  			objgone = ship_object(obj, x, y, FALSE);
169.  		if (!objgone) {
170.  			if (!flooreffects(obj,x,y,"fall")) { /* don't double-dip on damage */
171.  			    place_object(obj, x, y);
172.  			    if (!mtmp && x == u.ux && y == u.uy)
173.  				mtmp = &youmonst;
174.  			    if (mtmp && ohit)
175.  				passive_obj(mtmp, obj, (struct attack *)0);
176.  			    stackobj(obj);
177.  			    retvalu = 0;
178.  			}
179.  		}
180.  	} else if (obj) obfree(obj, (struct obj*) 0);
181.  
182.  	return retvalu;
183.  }
184.  
185.  #endif /* OVLB */
186.  #ifdef OVL1
187.  
188.  /* an object launched by someone/thing other than player attacks a monster;
189.     return 1 if the object has stopped moving (hit or its range used up) */
190.  int
191.  ohitmon(mon, mtmp, otmp, range, verbose)
192.  struct monst *mon;  /* monster thrower (if applicable) */
193.  struct monst *mtmp;	/* accidental target */
194.  struct obj *otmp;	/* missile; might be destroyed by drop_throw */
195.  int range;		/* how much farther will object travel if it misses */
196.  			/* Use -1 to signify to keep going even after hit, */
197.  			/* unless its gone (used for rolling_boulder_traps) */
198.  boolean verbose;  /* give message(s) even when you can't see what happened */
199.  {
200.  	int damage, tmp;
201.  	boolean vis, ismimic;
202.  	int objgone = 1;
203.  
204.  	ismimic = mtmp->m_ap_type && mtmp->m_ap_type != M_AP_MONSTER;
205.  	vis = cansee(bhitpos.x, bhitpos.y);
206.  
207.  	tmp = 5 + find_mac(mtmp) + omon_adj(mtmp, otmp, FALSE);
208.  	if (tmp < rnd(20)) {
209.  	    if (!ismimic) {
210.  		if (vis) miss(distant_name(otmp, mshot_xname), mtmp);
211.  		else if (verbose) pline("It is missed.");
212.  	    }
213.  	    if (!range) { /* Last position; object drops */
214.  		(void) drop_throw(mon, otmp, 0, mtmp->mx, mtmp->my);
215.  		return 1;
216.  	    }
217.  	} else if (otmp->oclass == POTION_CLASS) {
218.  	    if (ismimic) seemimic(mtmp);
219.  	    mtmp->msleeping = 0;
220.  	    if (vis) otmp->dknown = 1;
221.  	    potionhit(mtmp, otmp, FALSE);
222.  	    if (mon && !DEADMONSTER(mon) && !DEADMONSTER(mtmp) &&
223.  		    mtmp->movement >= NORMAL_SPEED && rn2(4)) {
224.  		/* retaliate */
225.  		mtmp->movement -= NORMAL_SPEED;
226.  		mattackm(mtmp, mon);
227.  	    }
228.  	    return 1;
229.  	} else {
230.  	    damage = dmgval(otmp, mtmp);
231.  # ifdef P_SPOON
232.              if (otmp->otyp == SPOON) {
233.              pline("The spoon flashes brightly as it hits %s.",
234.                     the(mon_nam(mtmp)));
235.              }
236.  # endif /* P_SPOON */
237.  
238.  	    if (otmp->otyp == ACID_VENOM && resists_acid(mtmp))
239.  		damage = 0;
240.  	    if (ismimic) seemimic(mtmp);
241.  	    mtmp->msleeping = 0;
242.  	    if (vis) hit(distant_name(otmp,mshot_xname), mtmp, exclam(damage));
243.  	    else if (verbose) pline("%s is hit%s", Monnam(mtmp), exclam(damage));
244.  
245.  	    if (otmp->opoisoned && is_poisonable(otmp)) {
246.  		if (resists_poison(mtmp)) {
247.  		    if (vis) pline_The("poison doesn't seem to affect %s.",
248.  				   mon_nam(mtmp));
249.  		} else {
250.  		    if (rn2(30)) {
251.  			damage += rnd(6);
252.  		    } else {
253.  			if (vis) pline_The("poison was deadly...");
254.  			damage = mtmp->mhp;
255.  		    }
256.  		}
257.  	    }
258.  	    if (objects[otmp->otyp].oc_material == SILVER &&
259.  		    hates_silver(mtmp->data)) {
260.  		if (vis) pline_The("silver sears %s flesh!",
261.  				s_suffix(mon_nam(mtmp)));
262.  		else if (verbose) pline("Its flesh is seared!");
263.  	    }
264.  	    if (otmp->otyp == ACID_VENOM && cansee(mtmp->mx,mtmp->my)) {
265.  		if (resists_acid(mtmp)) {
266.  		    if (vis || verbose)
267.  			pline("%s is unaffected.", Monnam(mtmp));
268.  		    damage = 0;
269.  		} else {
270.  		    if (vis) pline_The("acid burns %s!", mon_nam(mtmp));
271.  		    else if (verbose) pline("It is burned!");
272.  		}
273.  	    }
274.  	    mtmp->mhp -= damage;
275.  	    if (mtmp->mhp < 1) {
276.  		if (vis || verbose)
277.  		    pline("%s is %s!", Monnam(mtmp),
278.  			(nonliving(mtmp->data) || !canspotmon(mtmp))
279.  			? "destroyed" : "killed");
280.  		/* don't blame hero for unknown rolling boulder trap */
281.  		if (!flags.mon_moving &&
282.  		    (otmp->otyp != BOULDER || range >= 0 || !otmp->otrapped))
283.  		    xkilled(mtmp,0);
284.  		else mondied(mtmp);
285.  	    }
286.  
287.  	    if (can_blnd((struct monst*)0, mtmp,
288.  		    (uchar)(otmp->otyp == BLINDING_VENOM ? AT_SPIT : AT_WEAP),
289.  		    otmp)) {
290.  		if (vis && mtmp->mcansee)
291.  		    pline("%s is blinded by %s.", Monnam(mtmp), the(xname(otmp)));
292.  		mtmp->mcansee = 0;
293.  		tmp = (int)mtmp->mblinded + rnd(25) + 20;
294.  		if (tmp > 127) tmp = 127;
295.  		mtmp->mblinded = tmp;
296.  	    }
297.  
298.  	    if (mon && !DEADMONSTER(mon) && !DEADMONSTER(mtmp) &&
299.  		    mtmp->movement >= NORMAL_SPEED && rn2(4)) {
300.  		/* retaliate */
301.  		mtmp->movement -= NORMAL_SPEED;
302.  		mattackm(mtmp, mon);
303.  	    }
304.  
305.  	    objgone = drop_throw(mon, otmp, 1, bhitpos.x, bhitpos.y);
306.  	    if (!objgone && range == -1) {  /* special case */
307.  		    obj_extract_self(otmp); /* free it for motion again */
308.  		    return 0;
309.  	    }
310.  	    return 1;
311.  	}
312.  	return 0;
313.  }
314.  
315.  void
316.  m_throw(mon, x, y, dx, dy, range, obj)
317.  	register struct monst *mon;
318.  	register int x,y,dx,dy,range;		/* direction and range */
319.  	register struct obj *obj;
320.  {
321.  	register struct monst *mtmp;
322.  	struct obj *singleobj, *mwep;
323.  	char sym = obj->oclass;
324.  	int hitu, blindinc = 0;
325.  
326.  	bhitpos.x = x;
327.  	bhitpos.y = y;
328.  
329.  	if (obj->quan == 1L) {
330.  	    /*
331.  	     * Remove object from minvent.  This cannot be done later on;
332.  	     * what if the player dies before then, leaving the monster
333.  	     * with 0 daggers?  (This caused the infamous 2^32-1 orcish
334.  	     * dagger bug).
335.  	     *
336.  	     * VENOM is not in minvent - it should already be OBJ_FREE.
337.  	     * The extract below does nothing.
338.  	     */
339.  
340.  	    /* not possibly_unwield, which checks the object's */
341.  	    /* location, not its existence */
342.  	    if (MON_WEP(mon) == obj) {
343.  		    setmnotwielded(mon,obj);
344.  		    MON_NOWEP(mon);
345.  	    }
346.  	    obj_extract_self(obj);
347.  	    singleobj = obj;
348.  	    obj = (struct obj *) 0;
349.  	} else {
350.  	    singleobj = splitobj(obj, 1L);
351.  	    obj_extract_self(singleobj);
352.  	}
353.  
354.  	singleobj->owornmask = 0; /* threw one of multiple weapons in hand? */
355.  
356.  	if (mon) mwep = MON_WEP(mon);
357.  	else mwep = (struct obj *) 0;
358.  	
359.  	/* D: Special launcher effects */
360.  	if (mwep && is_ammo(singleobj) && ammo_and_launcher(singleobj, mwep)) {
361.  	    if (mwep->oartifact == ART_PLAGUE && is_poisonable(singleobj))
362.  			singleobj->opoisoned = 1;
363.  
364.  	    /* D: Hellfire is handled in drop_throw */
365.  	}
366.  
367.  	if (singleobj->cursed && (dx || dy) && !rn2(7)) {
368.  	    if(canseemon(mon) && flags.verbose) {
369.  		if(is_ammo(singleobj))
370.  		    pline("%s misfires!", Monnam(mon));
371.  		else
372.  		    pline("%s as %s throws it!",
373.  			  Tobjnam(singleobj, "slip"), mon_nam(mon));
374.  	    }
375.  	    dx = rn2(3)-1;
376.  	    dy = rn2(3)-1;
377.  	    /* check validity of new direction */
378.  	    if (!dx && !dy) {
379.  		(void) drop_throw(mon, singleobj, 0, bhitpos.x, bhitpos.y);
380.  		return;
381.  	    }
382.  	}
383.  
384.  	/* pre-check for doors, walls and boundaries.
385.  	  Also need to pre-check for bars regardless of direction;
386.  	  the random chance for small objects hitting bars is
387.  	  skipped when reaching them at point blank range */
388.  	if (!isok(bhitpos.x+dx,bhitpos.y+dy)
389.  	    || IS_ROCK(levl[bhitpos.x+dx][bhitpos.y+dy].typ)
390.  	    || closed_door(bhitpos.x+dx, bhitpos.y+dy)
391.  	    || (levl[bhitpos.x + dx][bhitpos.y + dy].typ == IRONBARS &&
392.  	        hits_bars(&singleobj, bhitpos.x, bhitpos.y, 0, 0))) {
393.  	    (void) drop_throw(mon, singleobj, 0, bhitpos.x, bhitpos.y);
394.  	    return;
395.  	}
396.  
397.  	/* Note: drop_throw may destroy singleobj.  Since obj must be destroyed
398.  	 * early to avoid the dagger bug, anyone who modifies this code should
399.  	 * be careful not to use either one after it's been freed.
400.  	 */
401.  	if (sym) tmp_at(DISP_FLASH, obj_to_glyph(singleobj));
402.  	while(range-- > 0) { /* Actually the loop is always exited by break */
403.  		bhitpos.x += dx;
404.  		bhitpos.y += dy;
405.  		if ((mtmp = m_at(bhitpos.x, bhitpos.y)) != 0) {
406.  		    if (ohitmon(mon, mtmp, singleobj, range, TRUE))
407.  			break;
408.  		} else if (bhitpos.x == u.ux && bhitpos.y == u.uy) {
409.  		    if (multi) nomul(0);
410.  
411.  		    if (singleobj->oclass == GEM_CLASS &&
412.  			    singleobj->otyp <= LAST_GEM+9 /* 9 glass colors */
413.  			    && is_unicorn(youmonst.data)) {
414.  			if (singleobj->otyp > LAST_GEM) {
415.  			    You("catch the %s.", xname(singleobj));
416.  			    You("are not interested in %s junk.",
417.  				s_suffix(mon_nam(mon)));
418.  			    makeknown(singleobj->otyp);
419.  			    dropy(singleobj);
420.  			} else {
421.  			    You("accept %s gift in the spirit in which it was intended.",
422.  				s_suffix(mon_nam(mon)));
423.  			    (void)hold_another_object(singleobj,
424.  				"You catch, but drop, %s.", xname(singleobj),
425.  				"You catch:");
426.  			}
427.  			break;
428.  		    }
429.  		    if (singleobj->oclass == POTION_CLASS) {
430.  			if (!Blind) singleobj->dknown = 1;
431.  			potionhit(&youmonst, singleobj, FALSE);
432.  			break;
433.  		    }
434.  		    switch(singleobj->otyp) {
435.  			int dam, hitv;
436.  			case EGG:
437.  			    if (!touch_petrifies(&mons[singleobj->corpsenm])) {
438.  				impossible("monster throwing egg type %d",
439.  					singleobj->corpsenm);
440.  				hitu = 0;
441.  				break;
442.  			    }
443.  			    /* fall through */
444.  			case CREAM_PIE:
445.  			case BLINDING_VENOM:
446.  			    hitu = thitu(8, 0, singleobj, (char *)0);
447.  			    break;
448.  			default:
449.  			    dam = dmgval(singleobj, &youmonst);
450.  			    hitv = 3 - distmin(u.ux,u.uy, mon->mx,mon->my);
451.  			    if (hitv < -4) hitv = -4;
452.  			    if (is_elf(mon->data) &&
453.  				objects[singleobj->otyp].oc_skill == P_BOW) {
454.  				hitv++;
455.  				if (MON_WEP(mon) &&
456.  				    MON_WEP(mon)->otyp == ELVEN_BOW)
457.  				    hitv++;
458.  				if(singleobj->otyp == ELVEN_ARROW) dam++;
459.  			    }
460.  			    if (bigmonst(youmonst.data)) hitv++;
461.  			    hitv += 8 + singleobj->spe;
462.  			    if (dam < 1) dam = 1;
463.  			    hitu = thitu(hitv, dam, singleobj, (char *)0);
464.  		    }
465.  		    if (hitu && singleobj->opoisoned &&
466.  			is_poisonable(singleobj)) {
467.  			char onmbuf[BUFSZ], knmbuf[BUFSZ];
468.  
469.  			Strcpy(onmbuf, xname(singleobj));
470.  			Strcpy(knmbuf, killer_xname(singleobj));
471.  			poisoned(onmbuf, A_STR, knmbuf, -10);
472.  		    }
473.  		    if(hitu &&
474.  		       can_blnd((struct monst*)0, &youmonst,
475.  				(uchar)(singleobj->otyp == BLINDING_VENOM ?
476.  					AT_SPIT : AT_WEAP), singleobj)) {
477.  			blindinc = rnd(25);
478.  			if(singleobj->otyp == CREAM_PIE) {
479.  			    if(!Blind) pline("Yecch!  You've been creamed.");
480.  			    else pline("There's %s sticky all over your %s.",
481.  				       something,
482.  				       body_part(FACE));
483.  			} else if(singleobj->otyp == BLINDING_VENOM) {
484.  			    int num_eyes = eyecount(youmonst.data);
485.  			    /* venom in the eyes */
486.  			    if(!Blind) pline_The("venom blinds you.");
487.  			    else Your("%s sting%s.",
488.  				      (num_eyes == 1) ? body_part(EYE) :
489.  						makeplural(body_part(EYE)),
490.  				      (num_eyes == 1) ? "s" : "");
491.  			}
492.  		    }
493.  		    if (hitu && singleobj->otyp == EGG) {
494.  			if (!Stone_resistance
495.  			    && !(poly_when_stoned(youmonst.data) &&
496.  				 polymon(PM_STONE_GOLEM))) {
497.  			    Stoned = 5;
498.  			    killer = (char *) 0;
499.  			}
500.  		    }
501.  		    stop_occupation();
502.  		    if (hitu || !range) {
503.                          (void) drop_throw(mon, singleobj, hitu, u.ux, u.uy);
504.  			break;
505.  		    }
506.  		}
507.  		if (!range	/* reached end of path */
508.  			/* missile hits edge of screen */
509.  			|| !isok(bhitpos.x+dx,bhitpos.y+dy)
510.  			/* missile hits the wall */
511.  			|| IS_ROCK(levl[bhitpos.x+dx][bhitpos.y+dy].typ)
512.  			/* missile hit closed door */
513.  			|| closed_door(bhitpos.x+dx, bhitpos.y+dy)
514.  			/* missile might hit bars */
515.  			|| (levl[bhitpos.x+dx][bhitpos.y+dy].typ == IRONBARS &&
516.  		        hits_bars(&singleobj, bhitpos.x, bhitpos.y, !rn2(5), 0))
517.  #ifdef SINKS
518.  			/* Thrown objects "sink" */
519.  			|| IS_SINK(levl[bhitpos.x][bhitpos.y].typ)
520.  #endif
521.  								) {
522.  		    if (singleobj) /* hits_bars might have destroyed it */
523.  			(void) drop_throw(mon, singleobj, 0, bhitpos.x, bhitpos.y);
524.  		    break;
525.  		}
526.  		tmp_at(bhitpos.x, bhitpos.y);
527.  		delay_output();
528.  	}
529.  	tmp_at(bhitpos.x, bhitpos.y);
530.  	delay_output();
531.  	tmp_at(DISP_END, 0);
532.  
533.  	if (blindinc) {
534.  		u.ucreamed += blindinc;
535.  		make_blinded(Blinded + (long)blindinc, FALSE);
536.  		if (!Blind) Your(vision_clears);
537.  	}
538.  }
539.  
540.  #endif /* OVL1 */
541.  #ifdef OVLB
542.  
543.  /* Remove an item from the monster's inventory and destroy it. */
544.  void
545.  m_useup(mon, obj)
546.  struct monst *mon;
547.  struct obj *obj;
548.  {
549.  	if (obj->quan > 1L) {
550.  		obj->quan--;
551.  		obj->owt = weight(obj);
552.  	} else {
553.  		obj_extract_self(obj);
554.  		possibly_unwield(mon, FALSE);
555.  		if (obj->owornmask) {
556.  		    mon->misc_worn_check &= ~(obj->owornmask);
557.  		    update_mon_intrinsics(mon, obj, FALSE, FALSE);
558.  		}
559.  		obfree(obj, (struct obj*) 0);
560.  	}
561.  }
562.  
563.  #endif /* OVLB */
564.  #ifdef OVL1
565.  
566.  /* monster attempts ranged weapon attack against player */
567.  void
568.  thrwmu(mtmp)
569.  struct monst *mtmp;
570.  {
571.  	struct obj *otmp, *mwep;
572.  	xchar x, y;
573.  	schar skill;
574.  	int multishot;
575.  	const char *onm;
576.  	int chance;
577.  
578.  	/* Rearranged beginning so monsters can use polearms not in a line */
579.  	if (mtmp->weapon_check == NEED_WEAPON || !MON_WEP(mtmp)) {
580.  	    mtmp->weapon_check = NEED_RANGED_WEAPON;
581.  	    /* mon_wield_item resets weapon_check as appropriate */
582.  	    if(mon_wield_item(mtmp) != 0) return;
583.  	}
584.  
585.  	/* Pick a weapon */
586.  	otmp = select_rwep(mtmp);
587.  	if (!otmp) return;
588.  
589.  	if ((MON_WEP(mtmp) == otmp) && is_pole(otmp)) {
590.  	    int dam, hitv;
591.  
592.  	    if (dist2(mtmp->mx, mtmp->my, mtmp->mux, mtmp->muy) > POLE_LIM ||
593.  		    !couldsee(mtmp->mx, mtmp->my))
594.  		return;	/* Out of range, or intervening wall */
595.  
596.  	    if (canseemon(mtmp)) {
597.  		onm = xname(otmp);
598.  		pline("%s thrusts %s.", Monnam(mtmp),
599.  		      obj_is_pname(otmp) ? the(onm) : an(onm));
600.  	    }
601.  
602.  	    dam = dmgval(otmp, &youmonst);
603.  	    hitv = 3 - distmin(u.ux,u.uy, mtmp->mx,mtmp->my);
604.  	    if (hitv < -4) hitv = -4;
605.  	    if (bigmonst(youmonst.data)) hitv++;
606.  	    hitv += 8 + otmp->spe;
607.  	    if (dam < 1) dam = 1;
608.  
609.  	    (void) thitu(hitv, dam, otmp, (char *)0);
610.  	    stop_occupation();
611.  	    return;
612.  	}
613.  
614.  	x = mtmp->mx;
615.  	y = mtmp->my;
616.  	/* If you are coming toward the monster, the monster
617.  	 * should try to soften you up with missiles.  If you are
618.  	 * going away, you are probably hurt or running.  Give
619.  	 * chase, but if you are getting too far away, throw.
620.  	 */
621.  	/* WAC Catch this since rn2(0) is illegal */
622.  	chance = (BOLT_LIM - distmin(x,y,mtmp->mux,mtmp->muy) > 0) ?
623.  		BOLT_LIM - distmin(x,y,mtmp->mux,mtmp->muy) : 1;
624.  	if (!lined_up(mtmp) || (URETREATING(x,y) && rn2(chance)))
625.  	    return;
626.  
627.  	skill = objects[otmp->otyp].oc_skill;
628.  	mwep = MON_WEP(mtmp);		/* wielded weapon */
629.  
630.  	if (ammo_and_launcher(otmp, mwep) && objects[mwep->otyp].oc_range &&
631.  		dist2(mtmp->mx, mtmp->my, mtmp->mux, mtmp->muy) >
632.  		objects[mwep->otyp].oc_range * objects[mwep->otyp].oc_range)
633.  	    return; /* Out of range */
634.  
635.  	/* Multishot calculations */
636.  	multishot = 1;
637.  	if ((ammo_and_launcher(otmp, mwep) || skill == P_DAGGER ||
638.  		skill == -P_DART || skill == -P_SHURIKEN) && !mtmp->mconf) {
639.  	    /* Assumes lords are skilled, princes are expert */
640.  	    if (is_prince(mtmp->data)) multishot += 2;
641.  	    else if (is_lord(mtmp->data)) multishot++;
642.  
643.  	    /*  Elven Craftsmanship makes for light,  quick bows */
644.  	    if (otmp->otyp == ELVEN_ARROW && !otmp->cursed)
645.  		multishot++;
646.  	    if (mwep && mwep->otyp == ELVEN_BOW && !mwep->cursed) multishot++;
647.  	    /* 1/3 of object enchantment */
648.  	    if (mwep && mwep->spe > 1)
649.  		multishot += rounddiv(mwep->spe, 3);
650.  	    /* Some randomness */
651.  	    if (multishot > 1)
652.  		multishot = rnd(multishot);
653.  #ifdef FIREARMS
654.  	    if (mwep && objects[mwep->otyp].oc_rof && is_launcher(mwep))
655.  		multishot += objects[mwep->otyp].oc_rof;
656.  #endif
657.  
658.  	    switch (monsndx(mtmp->data)) {
659.  	    case PM_RANGER:
660.  		    multishot++;
661.  		    break;
662.  	    case PM_ROGUE:
663.  		    if (skill == P_DAGGER) multishot++;
664.  		    break;
665.  	    case PM_NINJA:
666.  	    case PM_SAMURAI:
667.  		    if (otmp->otyp == YA && mwep &&
668.  			mwep->otyp == YUMI) multishot++;
669.  		    break;
670.  	    default:
671.  		break;
672.  	    }
673.  	    /* racial bonus */
674.  	    if ((is_elf(mtmp->data) &&
675.  		    otmp->otyp == ELVEN_ARROW &&
676.  		    mwep && mwep->otyp == ELVEN_BOW) ||
677.  		(is_orc(mtmp->data) &&
678.  		    otmp->otyp == ORCISH_ARROW &&
679.  		    mwep && mwep->otyp == ORCISH_BOW))
680.  		multishot++;
681.  
682.  	    if ((long)multishot > otmp->quan) multishot = (int)otmp->quan;
683.  	    if (multishot < 1) multishot = 1;
684.  	    /* else multishot = rnd(multishot); */
685.  	}
686.  
687.  	if (canseemon(mtmp)) {
688.  	    char onmbuf[BUFSZ];
689.  
690.  	    if (multishot > 1) {
691.  		/* "N arrows"; multishot > 1 implies otmp->quan > 1, so
692.  		   xname()'s result will already be pluralized */
693.  		Sprintf(onmbuf, "%d %s", multishot, xname(otmp));
694.  		onm = onmbuf;
695.  	    } else {
696.  		/* "an arrow" */
697.  		onm = singular(otmp, xname);
698.  		onm = obj_is_pname(otmp) ? the(onm) : an(onm);
699.  	    }
700.  	    m_shot.s = ammo_and_launcher(otmp,mwep) ? TRUE : FALSE;
701.  	    pline("%s %s %s!", Monnam(mtmp),
702.  #ifdef FIREARMS
703.  		  m_shot.s ? is_bullet(otmp) ? "fires" : "shoots" : "throws",
704.  		  onm);
705.  #else
706.  		  m_shot.s ? "shoots" : "throws", onm);
707.  #endif
708.  	    m_shot.o = otmp->otyp;
709.  	} else {
710.  	    m_shot.o = STRANGE_OBJECT;	/* don't give multishot feedback */
711.  	}
712.  
713.  	m_shot.n = multishot;
714.  	for (m_shot.i = 1; m_shot.i <= m_shot.n; m_shot.i++)
715.  	    m_throw(mtmp, mtmp->mx, mtmp->my, sgn(tbx), sgn(tby),
716.  		    distmin(mtmp->mx, mtmp->my, mtmp->mux, mtmp->muy), otmp);
717.  	m_shot.n = m_shot.i = 0;
718.  	m_shot.o = STRANGE_OBJECT;
719.  	m_shot.s = FALSE;
720.  
721.  	nomul(0);
722.  }
723.  
724.  #endif /* OVL1 */
725.  #ifdef OVLB
726.  
727.  int
728.  spitmu(mtmp, mattk)		/* monster spits substance at you */
729.  register struct monst *mtmp;
730.  register struct attack *mattk;
731.  {
732.  	register struct obj *otmp;
733.  
734.  	if(mtmp->mcan) {
735.  
736.  	    if(flags.soundok)
737.  		pline("A dry rattle comes from %s throat.",
738.  		                      s_suffix(mon_nam(mtmp)));
739.  	    return 0;
740.  	}
741.  	if(lined_up(mtmp)) {
742.  		switch (mattk->adtyp) {
743.  		    case AD_BLND:
744.  		    case AD_DRST:
745.  			otmp = mksobj(BLINDING_VENOM, TRUE, FALSE);
746.  			break;
747.  		    default:
748.  			impossible("bad attack type in spitmu");
749.  				/* fall through */
750.  		    case AD_ACID:
751.  			otmp = mksobj(ACID_VENOM, TRUE, FALSE);
752.  			break;
753.  		}
754.  		if(!rn2(BOLT_LIM-distmin(mtmp->mx,mtmp->my,mtmp->mux,mtmp->muy))) {
755.  		    if (canseemon(mtmp))
756.  			pline("%s spits venom!", Monnam(mtmp));
757.  		    m_throw(mtmp, mtmp->mx, mtmp->my, sgn(tbx), sgn(tby),
758.  			distmin(mtmp->mx,mtmp->my,mtmp->mux,mtmp->muy), otmp);
759.  		    nomul(0);
760.  		    return 0;
761.  		}
762.  	}
763.  	return 0;
764.  }
765.  
766.  #endif /* OVLB */
767.  #ifdef OVL1
768.  
769.  int
770.  breamu(mtmp, mattk)			/* monster breathes at you (ranged) */
771.  	register struct monst *mtmp;
772.  	register struct attack  *mattk;
773.  {
774.  	/* if new breath types are added, change AD_ACID to max type */
775.  	int typ = (mattk->adtyp == AD_RBRE) ? rnd(AD_ACID) : mattk->adtyp ;
776.  
777.  	if(lined_up(mtmp)) {
778.  
779.  	    if(mtmp->mcan) {
780.  		if(flags.soundok) {
781.  		    if(canseemon(mtmp))
782.  			pline("%s coughs.", Monnam(mtmp));
783.  		    else
784.  			You_hear("a cough.");
785.  		}
786.  		return(0);
787.  	    }
788.  	    if(!mtmp->mspec_used && rn2(3)) {
789.  
790.  		if((typ >= AD_MAGM) && (typ <= AD_ACID)) {
791.  
792.  		    if(canseemon(mtmp))
793.  			pline("%s breathes %s!", Monnam(mtmp),
794.  			      breathwep[typ-1]);
795.  		    buzz((int) (-20 - (typ-1)), (int)mattk->damn,
796.  			 mtmp->mx, mtmp->my, sgn(tbx), sgn(tby));
797.  		    nomul(0);
798.  		    /* breath runs out sometimes. Also, give monster some
799.  		     * cunning; don't breath if the player fell asleep.
800.  		     */
801.  		    if(!rn2(3))
802.  			mtmp->mspec_used = 10+rn2(20);
803.  		    if(typ == AD_SLEE && !Sleep_resistance)
804.  			mtmp->mspec_used += rnd(20);
805.  		} else impossible("Breath weapon %d used", typ-1);
806.  	    }
807.  	}
808.  	return(1);
809.  }
810.  
811.  
812.  /* WAC for doorbusting ONLY (at this point in time) No checks */
813.  boolean
814.  breamspot(mtmp, mattk, ax, ay)
815.  register struct monst *mtmp;
816.  register struct attack  *mattk;
817.  xchar ax, ay;
818.  {
819.  	/* if new breath types are added, change AD_ACID to max type */
820.  	int typ = (mattk->adtyp == AD_RBRE) ? rnd(AD_ACID) : mattk->adtyp ;
821.  
822.  
823.  	if((typ >= AD_MAGM) && (typ <= AD_ACID)) {
824.  		if(canseemon(mtmp))
825.  			pline("%s breathes %s!", Monnam(mtmp),
826.  				breathwep[typ-1]);
827.  		/* Do the door first - monster is ON TOP so call direct */
828.  		zap_over_floor(mtmp->mx, mtmp->my, (int) (-20 - (typ-1)), NULL);
829.  		buzz((int) (-20 - (typ-1)), (int)mattk->damn, 
830.  				mtmp->mx, mtmp->my, ax, ay);
831.  		nomul(0);
832.  		/* breath runs out sometimes. */
833.  		if(!rn2(3))
834.  			mtmp->mspec_used = 10+rn2(20);
835.  	} else impossible("Breath weapon %d used", typ-1);
836.  	return(TRUE);
837.  }
838.  
839.  
840.  boolean
841.  linedup(ax, ay, bx, by)
842.  register xchar ax, ay, bx, by;
843.  {
844.  	tbx = ax - bx;	/* These two values are set for use */
845.  	tby = ay - by;	/* after successful return.	    */
846.  
847.  	/* sometimes displacement makes a monster think that you're at its
848.  	   own location; prevent it from throwing and zapping in that case */
849.  	if (!tbx && !tby) return FALSE;
850.  
851.  	if((!tbx || !tby || abs(tbx) == abs(tby)) /* straight line or diagonal */
852.  	   && distmin(tbx, tby, 0, 0) < BOLT_LIM) {
853.  	    if(ax == u.ux && ay == u.uy) return((boolean)(couldsee(bx,by)));
854.  	    else if(clear_path(ax,ay,bx,by)) return TRUE;
855.  	}
856.  	return FALSE;
857.  }
858.  
859.  boolean
860.  lined_up(mtmp)		/* is mtmp in position to use ranged attack? */
861.  	register struct monst *mtmp;
862.  {
863.  	return(linedup(mtmp->mux,mtmp->muy,mtmp->mx,mtmp->my));
864.  }
865.  
866.  #endif /* OVL1 */
867.  #ifdef OVL0
868.  
869.  /* Check if a monster is carrying a particular item.
870.   */
871.  struct obj *
872.  m_carrying(mtmp, type)
873.  struct monst *mtmp;
874.  int type;
875.  {
876.  	register struct obj *otmp;
877.  
878.  	for(otmp = mtmp->minvent; otmp; otmp = otmp->nobj)
879.  		if(otmp->otyp == type)
880.  			return(otmp);
881.  	return((struct obj *) 0);
882.  }
883.  
884.  /* TRUE iff thrown/kicked/rolled object doesn't pass through iron bars */
885.  boolean
886.  hits_bars(obj_p, x, y, always_hit, whodidit)
887.  struct obj **obj_p;	/* *obj_p will be set to NULL if object breaks */
888.  int x, y;
889.  int always_hit;	/* caller can force a hit for items which would fit through */
890.  int whodidit;	/* 1==hero, 0=other, -1==just check whether it'll pass thru */
891.  {
892.      struct obj *otmp = *obj_p;
893.      int obj_type = otmp->otyp;
894.      boolean hits = always_hit;
895.  
896.      if (!hits)
897.  	switch (otmp->oclass) {
898.  	case WEAPON_CLASS:
899.  	    {
900.  		int oskill = objects[obj_type].oc_skill;
901.  
902.  		hits = (oskill != -P_BOW  && oskill != -P_CROSSBOW &&
903.  			oskill != -P_DART && oskill != -P_SHURIKEN &&
904.  #ifdef FIREARMS
905.  			(oskill != -P_FIREARM || obj_type == ROCKET) &&
906.  #endif
907.  			oskill != P_SPEAR && oskill != P_JAVELIN &&
908.  			oskill != P_KNIFE);	/* but not dagger */
909.  		break;
910.  	    }
911.  	case ARMOR_CLASS:
912.  		hits = (objects[obj_type].oc_armcat != ARM_GLOVES);
913.  		break;
914.  	case TOOL_CLASS:
915.  		hits = (obj_type != SKELETON_KEY &&
916.  			obj_type != LOCK_PICK &&
917.  #ifdef TOURIST
918.  			obj_type != CREDIT_CARD &&
919.  #endif
920.  			obj_type != TALLOW_CANDLE &&
921.  			obj_type != WAX_CANDLE &&
922.  			obj_type != LENSES &&
923.  			obj_type != TIN_WHISTLE &&
924.  			obj_type != MAGIC_WHISTLE);
925.  		break;
926.  	case ROCK_CLASS:	/* includes boulder */
927.  		if (obj_type != STATUE ||
928.  			mons[otmp->corpsenm].msize > MZ_TINY) hits = TRUE;
929.  		break;
930.  	case FOOD_CLASS:
931.  		if (obj_type == CORPSE &&
932.  			mons[otmp->corpsenm].msize > MZ_TINY) hits = TRUE;
933.  		else
934.  		    hits = (obj_type == MEAT_STICK ||
935.  			    obj_type == HUGE_CHUNK_OF_MEAT);
936.  		break;
937.  	case SPBOOK_CLASS:
938.  	case WAND_CLASS:
939.  	case BALL_CLASS:
940.  	case CHAIN_CLASS:
941.  		hits = TRUE;
942.  		break;
943.  	default:
944.  		break;
945.  	}
946.  
947.      if (hits && whodidit != -1) {
948.  	if (whodidit ? hero_breaks(otmp, x, y, FALSE) : breaks(otmp, x, y))
949.  	    *obj_p = otmp = 0;		/* object is now gone */
950.  	    /* breakage makes its own noises */
951.  	else if (obj_type == BOULDER || obj_type == HEAVY_IRON_BALL)
952.  	    pline("Whang!");
953.  	else if (otmp->oclass == COIN_CLASS ||
954.  		objects[obj_type].oc_material == GOLD ||
955.  		objects[obj_type].oc_material == SILVER)
956.  	    pline("Clink!");
957.  	else
958.  	    pline("Clonk!");
959.      }
960.  
961.      return hits;
962.  }
963.  
964.  #endif /* OVL0 */
965.  
966.  /*mthrowu.c*/

Also on Fandom

Random Wiki