Wikia

Wikihack

Source:NetHack 3.1.0/mthrowu.c

2,032pages on
this wiki
Talk0

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

Around Wikia's network

Random Wiki