Fandom

Wikihack

Source:SLASH'EM 0.0.7E7F2/mthrowu.c

2,034pages on
this wiki
Add New Page
Talk0

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*/

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.