Source:NetHack 3.0.0/mthrowu.c

From NetHackWiki
Revision as of 05:05, 4 March 2008 by Kernigh bot (talk | contribs) (NetHack 3.0.0/mthrowu.c moved to Source:NetHack 3.0.0/mthrowu.c: Robot: moved page)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

Below is the full text to mthrowu.c from the source code of NetHack 3.0.0. To link to a particular line, write [[NetHack 3.0.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.

This content was modified from the original NetHack source code distribution (by splitting up NetHack content between wiki pages, and possibly further editing). See the page history for a list of who changed it, and on what dates.

1.    /*	SCCS Id: @(#)mthrowu.c	3.0	88/04/13
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 int movedist();
8.    
9.    #define URETREATING(x,y) (movedist(u.ux,u.uy,x,y) > movedist(u.ux0,u.uy0,x,y))
10.   
11.   boolean lined_up();
12.   
13.   schar	tbx = 0, tby = 0;	/* used for direction of throw, buzz, etc. */
14.   
15.   const char *breathwep[] = {	"fragments",
16.   				"fire",
17.   				"sleep gas",
18.   				"frost",
19.   				"death",
20.   				"lightning",
21.   				"poison gas",
22.   				"acid"
23.   };
24.   
25.   int
26.   thitu(tlev, dam, name)	/* u is hit by sth, but not a monster */
27.   	register int tlev, dam;
28.   	register char *name;
29.   {
30.   	char buf[BUFSZ];
31.   	boolean acidic = (!strcmp(name, "splash of venom") && dam);
32.   	/* A horrible kludge... the problem is that we want to do something
33.   	 * special--and we can't do it after returning since we might die and
34.   	 * not return, but the special stuff should be done anyway...
35.   	 */
36.   
37.   	setan(name, buf);
38.   	if(u.uac + tlev <= rnd(20)) {
39.   		if(Blind || !flags.verbose) pline("It misses.");
40.   		else You("are almost hit by %s!", buf);
41.   		return(0);
42.   	} else {
43.   		if(Blind || !flags.verbose) You("are hit!");
44.   		else You("are hit by %s!", buf);
45.   		Strcpy(buf,name);
46.   		/* If name came from xname() we must copy it, otherwise if
47.   		 * you die, the possession identify will call xname(),
48.   		 * overwriting xname's buffer, and your tombstone will say
49.   		 * you were killed by a green gem or some such.
50.   		 */
51.   #ifdef POLYSELF
52.   		if (acidic && resists_acid(uasmon))
53.   			pline("It doesn't seem to hurt you.");
54.   		else {
55.   #endif
56.   			if (acidic) pline("It burns!");
57.   			losehp(dam, buf);
58.   #ifdef POLYSELF
59.   		}
60.   #endif
61.   		return(1);
62.   	}
63.   }
64.   
65.   /* Be sure this corresponds with what happens to player-thrown objects in
66.    * dothrow.c (for consistency). --KAA
67.    */
68.   static void
69.   drop_throw(obj, ohit, x, y)
70.   register struct obj *obj;
71.   boolean ohit;
72.   int x,y;
73.   {
74.   	int create;
75.   
76.   	if (obj->otyp == CREAM_PIE || obj->olet == VENOM_SYM)
77.   		create = 0;
78.   	else if (ohit &&
79.   		 ((obj->otyp >= ARROW && obj->otyp <= SHURIKEN) ||
80.   		  obj->otyp == ROCK))
81.   		create = !rn2(3);
82.   	else create = 1;
83.   	if (create && !flooreffects(obj,x,y)) {
84.   		obj->ox = x;
85.   		obj->oy = y;
86.   		obj->nobj = fobj;
87.   		fobj = obj;
88.   		stackobj(fobj);
89.   		levl[x][y].omask = 1;
90.   	} else free((genericptr_t)obj);
91.   }
92.   
93.   static void
94.   m_throw(x, y, dx, dy, range, obj)
95.   	register int x,y,dx,dy,range;		/* direction and range */
96.   	register struct obj *obj;
97.   {
98.   	register struct monst *mtmp;
99.   	struct obj *singleobj;
100.  	char sym = obj->olet;
101.  	int damage;
102.  	int hitu, blindinc=0;
103.  
104.  	bhitpos.x = x;
105.  	bhitpos.y = y;
106.  
107.  	singleobj = splitobj(obj, (int)obj->quan-1);
108.  	/* splitobj leaves the new object in the chain (i.e. the monster's
109.  	 * inventory).  Remove it.  We can do this in 1 line, but it's highly
110.  	 * dependent on the fact that we know splitobj() places it immediately
111.  	 * after obj.
112.  	 */
113.  	obj->nobj = singleobj->nobj;
114.  
115.  	if(sym) {
116.  		tmp_at(-1, sym);	/* open call */
117.  		tmp_at(-3, (int)AT_OBJ);
118.  	}
119.  	while(range-- > 0) { /* Actually the loop is always exited by break */
120.  		bhitpos.x += dx;
121.  		bhitpos.y += dy;
122.  		if(levl[bhitpos.x][bhitpos.y].mmask) {
123.  		    mtmp = m_at(bhitpos.x,bhitpos.y);
124.  
125.  		    if(mtmp->data->ac + 8 + obj->spe <= rnd(20)) {
126.  			miss(distant_name(singleobj,xname), mtmp);
127.  			if (!range) { /* Last position; object drops */
128.  			    drop_throw(singleobj, 0, mtmp->mx, mtmp->my);
129.  			    break;
130.  			}
131.  		    } else {
132.  			damage = dmgval(obj, mtmp->data);
133.  			if (damage < 1) damage = 1;
134.  			if (obj->otyp==ACID_VENOM && resists_acid(mtmp->data))
135.  			    damage = 0;
136.  			hit(distant_name(singleobj,xname), mtmp,exclam(damage));
137.  			if (obj->opoisoned) {
138.  			    if (resists_poison(mtmp->data))
139.  				kludge("The poison doesn't seem to affect %s.",
140.  								mon_nam(mtmp));
141.  			    else {
142.  				if (rn2(10)) damage += rnd(6);
143.  				else {
144.  				    pline("The poison was deadly...");
145.  				    damage = mtmp->mhp;
146.  				}
147.  			    }
148.  			}
149.  			if (obj->otyp==ACID_VENOM && cansee(mtmp->mx,mtmp->my)){
150.  			    if (resists_acid(mtmp->data)) {
151.  				pline("%s is unaffected.", Monnam(mtmp));
152.  				damage = 0;
153.  			    } else pline("The acid burns %s!", mon_nam(mtmp));
154.  			}
155.  			mtmp->mhp -= damage;
156.  			if(mtmp->mhp < 1) {
157.  			    if (cansee(mtmp->mx, mtmp->my))
158.  				pline("%s is killed!", Monnam(mtmp));
159.  			    mondied(mtmp);
160.  			}
161.  
162.  			if((obj->otyp == CREAM_PIE) ||
163.  			   (obj->otyp == BLINDING_VENOM)) {
164.  			    if (cansee(mtmp->mx, mtmp->my))
165.  				pline("%s is blinded by the %s.",
166.  				      Monnam(mtmp), xname(singleobj));
167.  			    if(mtmp->msleep) mtmp->msleep = 0;
168.  			    mtmp->mcansee = 0;
169.  			    {
170.  				register unsigned rnd_tmp = rnd(25) + 20;
171.  				if((mtmp->mblinded + rnd_tmp) > 127)
172.  					mtmp->mblinded = 127;
173.  				else mtmp->mblinded += rnd_tmp;
174.  			    }
175.  			}
176.  			drop_throw(singleobj, 1, bhitpos.x, bhitpos.y);
177.  			break;
178.  		    }
179.  		}
180.  		if (bhitpos.x == u.ux && bhitpos.y == u.uy) {
181.  			if (multi) nomul(0);
182.  
183.  			switch(obj->otyp) {
184.  			    int dam;
185.  			    case CREAM_PIE:
186.  			    case BLINDING_VENOM:
187.  				hitu = thitu(8, 0, xname(singleobj));
188.  				break;
189.  			    default:
190.  				dam = dmgval(obj, uasmon);
191.  				if (dam < 1) dam = 1;
192.  				hitu = thitu(8+obj->spe, dam, xname(singleobj));
193.  			}
194.  			if (obj->opoisoned)
195.  			    /* it's safe to call xname twice because it's the
196.  			       same object both times... */
197.  			    poisoned(xname(singleobj), A_STR, xname(singleobj));
198.  			if(hitu && (obj->otyp == CREAM_PIE ||
199.  				     obj->otyp == BLINDING_VENOM)) {
200.  			    blindinc = rnd(25);
201.  			    if(obj->otyp == CREAM_PIE) {
202.  				if(!Blind) pline("Yecch!  You've been creamed.");
203.  				else	pline("There's something sticky all over your %s.", body_part(FACE));
204.  			    } else {	/* venom in the eyes */
205.  				if(Blindfolded) /* nothing */ ;
206.  				else if(!Blind) pline("The venom blinds you.");
207.  				else	Your("%s sting.",
208.  					makeplural(body_part(EYE)));
209.  			    }
210.  			}
211.  			if (hitu || !range) {
212.  			    drop_throw(singleobj, hitu, u.ux, u.uy);
213.  			    break;
214.  			}
215.  		} else if (!range	/* reached end of path */
216.  			/* missile hits edge of screen */
217.  			|| !isok(bhitpos.x+dx,bhitpos.y+dy)
218.  			/* missile hits the wall */
219.  			|| IS_WALL(levl[bhitpos.x+dx][bhitpos.y+dy].typ)
220.  			|| levl[bhitpos.x+dx][bhitpos.y+dy].typ == SDOOR
221.  			|| levl[bhitpos.x+dx][bhitpos.y+dy].typ == SCORR
222.  #ifdef SINKS
223.  			/* Thrown objects "sink" */
224.  			|| IS_SINK(levl[bhitpos.x][bhitpos.y].typ)
225.  #endif
226.  								) {
227.  		    drop_throw(singleobj, 0, bhitpos.x, bhitpos.y);
228.  		    break;
229.  		}
230.  		tmp_at(bhitpos.x, bhitpos.y);
231.  	}
232.  	tmp_at(bhitpos.x, bhitpos.y);
233.  	tmp_at(-1, -1);
234.  	/* blindfold keeps substances out of your eyes */
235.  	if (blindinc && !Blindfolded) {
236.  		u.ucreamed += blindinc;
237.  		make_blinded(Blinded + blindinc,FALSE);
238.  	}
239.  }
240.  
241.  /* Remove an item from the monster's inventory.
242.   */
243.  void
244.  m_useup(mon, obj)
245.  struct monst *mon;
246.  struct obj *obj;
247.  {
248.  	struct obj *otmp, *prev;
249.  
250.  	prev = ((struct obj *) 0);
251.  	for (otmp = mon->minvent; otmp; otmp = otmp->nobj) {
252.  		if (otmp == obj) {
253.  			if (prev)
254.  				prev->nobj = obj->nobj;
255.  			else
256.  				mon->minvent = obj->nobj;
257.  			free((genericptr_t) obj);
258.  			break;
259.  		}
260.  		prev = otmp;
261.  	}
262.  }
263.  
264.  /* Always returns 0??? -SAC */
265.  int
266.  thrwmu(mtmp)	/* monster throws item at you */
267.  register struct monst *mtmp;
268.  {
269.  	struct obj *otmp, *select_rwep();
270.  	register xchar x, y;
271.  
272.  	if(lined_up(mtmp)) {
273.  
274.  	    if((otmp = select_rwep(mtmp))) {
275.  
276.  		/* If you are coming toward the monster, the monster
277.  		 * should try to soften you up with missiles.  If you are
278.  		 * going away, you are probably hurt or running.  Give
279.  		 * chase, but if you are getting too far away, throw.
280.  		 */
281.  		x = mtmp->mx;
282.  		y = mtmp->my;
283.  		if(!URETREATING(x,y) ||
284.  		   !rn2(BOLT_LIM-movedist(x,mtmp->mux,y,mtmp->muy)))
285.  		{
286.  		    m_throw(mtmp->mx, mtmp->my, sgn(tbx), sgn(tby), 
287.  			movedist(mtmp->mx,mtmp->mux,mtmp->my,mtmp->muy), otmp);
288.  		    if (!otmp->quan) m_useup(mtmp, otmp);
289.  		    nomul(0);
290.  		    return 0;
291.  		}
292.  	    }
293.  	}
294.  	return 0;
295.  }
296.  
297.  int
298.  spitmu(mtmp)			/* monster spits substance at you */
299.  register struct monst *mtmp;
300.  {
301.  	register struct obj *otmp;
302.  
303.  	if(mtmp->mcan) {
304.  
305.  	    if(flags.soundok)
306.  		pline("A dry rattle comes from %s's throat", mon_nam(mtmp));
307.  	    return 0;
308.  	}
309.  	if(lined_up(mtmp)) {
310.  		otmp = mksobj(mtmp->data==&mons[PM_COBRA] ?
311.  			BLINDING_VENOM : ACID_VENOM, FALSE);
312.  		/* really incorrect; should check the attack type; this might
313.  		 * fail if someone introduces another monster with a venom
314.  		 * attack...
315.  		 */
316.  		if(!rn2(BOLT_LIM-movedist(mtmp->mx,mtmp->mux,mtmp->my,mtmp->muy))) {
317.  
318.  		    m_throw(mtmp->mx, mtmp->my, sgn(tbx), sgn(tby), 
319.  			movedist(mtmp->mx,mtmp->mux,mtmp->my,mtmp->muy), otmp);
320.  		    nomul(0);
321.  		    return 0;
322.  		}
323.  	}
324.  	return 0;
325.  }
326.  
327.  int
328.  breamu(mtmp, mattk)			/* monster breathes at you (ranged) */
329.  	register struct monst *mtmp;
330.  	register struct attack  *mattk;
331.  {
332.  	if(lined_up(mtmp)) {
333.  
334.  	    if(mtmp->mcan) {
335.  		if(flags.soundok) {
336.  		    if(canseemon(mtmp))
337.  			pline("%s coughs.", Monnam(mtmp));
338.  		    else
339.  			You("hear a cough.");
340.  		}
341.  		return(0);
342.  	    }
343.  	    if(rn2(3)) {
344.  
345.  		if((mattk->adtyp >= 1) && (mattk->adtyp < 11)) {
346.  
347.  		    if(canseemon(mtmp))
348.  			pline("%s breathes %s!", Monnam(mtmp),
349.  			      breathwep[mattk->adtyp-1]);
350.  		    buzz((int) (-20 - (mattk->adtyp-1)), (int)mattk->damn,
351.  			 mtmp->mx, mtmp->my, sgn(tbx), sgn(tby));
352.  		    nomul(0);
353.  		} else impossible("Breath weapon %d used", mattk->adtyp-1);
354.  	    }
355.  	}
356.  	return(1);
357.  }
358.  
359.  boolean
360.  linedup(ax, ay, bx, by)
361.  register xchar ax, ay, bx, by;
362.  {
363.  	register xchar x, y;
364.  
365.  	tbx = ax - bx;	/* These two values are set for use */
366.  	tby = ay - by;	/* after successful return.	    */
367.  
368.  	if((!tbx || !tby || abs(tbx) == abs(tby)) /* straight line or diagonal */
369.  	   && movedist(tbx, 0,  tby, 0) < BOLT_LIM) {
370.  
371.  		/* Check if there are any dead squares between.  If so,
372.  		 * it will not be possible to shoot.
373.  		 */
374.  		x = bx; y = by;
375.  		while(x != ax || y != ay) {
376.  
377.  		    if (!ACCESSIBLE(levl[x][y].typ) ||
378.  			  (IS_DOOR(levl[x][y].typ) && 
379.  				(levl[x][y].doormask & (D_LOCKED | D_CLOSED)))) 
380.  			return FALSE;
381.  		    x += sgn(tbx), y += sgn(tby);
382.  		}
383.  		return TRUE;
384.  	}
385.  	return FALSE;
386.  }
387.  
388.  boolean
389.  lined_up(mtmp)		/* is mtmp in position to use ranged attack? */
390.  	register struct monst *mtmp;
391.  {
392.  	return(linedup(mtmp->mux,mtmp->muy,mtmp->mx,mtmp->my));
393.  }
394.  
395.  /* Check if a monster is carrying a particular item.
396.   */
397.  struct obj *
398.  m_carrying(mtmp, type)
399.  struct monst *mtmp;
400.  int type;
401.  {
402.  	register struct obj *otmp;
403.  
404.  	for(otmp = mtmp->minvent; otmp; otmp = otmp->nobj)
405.  		if(otmp->otyp == type)
406.  			return(otmp);
407.  	return((struct obj *) 0);
408.  }
409.  
410.  static int
411.  movedist(x0, x1, y0, y1)
412.  {
413.  	register int absdx, absdy;
414.  
415.  	absdx = abs(x1 - x0);
416.  	absdy = abs(y1 - y0);
417.  
418.  	return (max(absdx,absdy));
419.  }