Fandom

Wikihack

Source:NetHack 3.2.0/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 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

The NetHack General Public License applies to screenshots, source code and other content from NetHack.
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*/

Also on Fandom

Random Wiki