Wikia

Wikihack

Source:Uhitm.c

2,032pages on
this wiki
Talk0

Below is the full text to src/uhitm.c from NetHack 3.4.3. To link to a particular line, write [[uhitm.c#line123]], for example.

Top of file Edit

1.    /*	SCCS Id: @(#)uhitm.c	3.4	2003/02/18	*/
2.    /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3.    /* NetHack may be freely redistributed.  See license for details. */
4.    
The NetHack General Public License applies to screenshots, source code and other content from NetHack.
5.    #include "hack.h"
6.    
7.    STATIC_DCL boolean FDECL(known_hitum, (struct monst *,int *,struct attack *));
8.    STATIC_DCL void FDECL(steal_it, (struct monst *, struct attack *));
9.    STATIC_DCL boolean FDECL(hitum, (struct monst *,int,struct attack *));
10.   STATIC_DCL boolean FDECL(hmon_hitmon, (struct monst *,struct obj *,int));
11.   #ifdef STEED
12.   STATIC_DCL int FDECL(joust, (struct monst *,struct obj *));
13.   #endif
14.   STATIC_DCL void NDECL(demonpet);
15.   STATIC_DCL boolean FDECL(m_slips_free, (struct monst *mtmp,struct attack *mattk));
16.   STATIC_DCL int FDECL(explum, (struct monst *,struct attack *));
17.   STATIC_DCL void FDECL(start_engulf, (struct monst *));
18.   STATIC_DCL void NDECL(end_engulf);
19.   STATIC_DCL int FDECL(gulpum, (struct monst *,struct attack *));
20.   STATIC_DCL boolean FDECL(hmonas, (struct monst *,int));
21.   STATIC_DCL void FDECL(nohandglow, (struct monst *));
22.   STATIC_DCL boolean FDECL(shade_aware, (struct obj *));
23.   
24.   extern boolean notonhead;	/* for long worms */
25.   /* The below might become a parameter instead if we use it a lot */
26.   static int dieroll;
27.   /* Used to flag attacks caused by Stormbringer's maliciousness. */
28.   static boolean override_confirmation = FALSE;
29.   
30.   #define PROJECTILE(obj)	((obj) && is_ammo(obj))
31.   

hurtmarmor Edit

32.   /* modified from hurtarmor() in mhitu.c */
33.   /* This is not static because it is also used for monsters rusting monsters */
34.   void
35.   hurtmarmor(mdef, attk)
36.   struct monst *mdef;
37.   int attk;
38.   {
39.   	int	hurt;
40.   	struct obj *target;
41.   
42.   	switch(attk) {
43.   	    /* 0 is burning, which we should never be called with */
44.   	    case AD_RUST: hurt = 1; break;
45.   	    case AD_CORR: hurt = 3; break;
46.   	    default: hurt = 2; break;
47.   	}
48.   	/* What the following code does: it keeps looping until it
49.   	 * finds a target for the rust monster.
50.   	 * Head, feet, etc... not covered by metal, or covered by
51.   	 * rusty metal, are not targets.  However, your body always
52.   	 * is, no matter what covers it.
53.   	 */
54.   	while (1) {
55.   	    switch(rn2(5)) {
56.   	    case 0:
57.   		target = which_armor(mdef, W_ARMH);
58.   		if (!target || !rust_dmg(target, xname(target), hurt, FALSE, mdef))
59.   		    continue;
60.   		break;
61.   	    case 1:
62.   		target = which_armor(mdef, W_ARMC);
63.   		if (target) {
64.   		    (void)rust_dmg(target, xname(target), hurt, TRUE, mdef);
65.   		    break;
66.   		}
67.   		if ((target = which_armor(mdef, W_ARM)) != (struct obj *)0) {
68.   		    (void)rust_dmg(target, xname(target), hurt, TRUE, mdef);
69.   #ifdef TOURIST
70.   		} else if ((target = which_armor(mdef, W_ARMU)) != (struct obj *)0) {
71.   		    (void)rust_dmg(target, xname(target), hurt, TRUE, mdef);
72.   #endif
73.   		}
74.   		break;
75.   	    case 2:
76.   		target = which_armor(mdef, W_ARMS);
77.   		if (!target || !rust_dmg(target, xname(target), hurt, FALSE, mdef))
78.   		    continue;
79.   		break;
80.   	    case 3:
81.   		target = which_armor(mdef, W_ARMG);
82.   		if (!target || !rust_dmg(target, xname(target), hurt, FALSE, mdef))
83.   		    continue;
84.   		break;
85.   	    case 4:
86.   		target = which_armor(mdef, W_ARMF);
87.   		if (!target || !rust_dmg(target, xname(target), hurt, FALSE, mdef))
88.   		    continue;
89.   		break;
90.   	    }
91.   	    break; /* Out of while loop */
92.   	}
93.   }
94.   

attack_checks Edit

95.   /* FALSE means it's OK to attack */
96.   boolean
97.   attack_checks(mtmp, wep)
98.   register struct monst *mtmp;
99.   struct obj *wep;	/* uwep for attack(), null for kick_monster() */
100.  {
101.  	char qbuf[QBUFSZ];
102.  
103.  	/* if you're close enough to attack, alert any waiting monster */
104.  	mtmp->mstrategy &= ~STRAT_WAITMASK;
105.  
106.  	if (u.uswallow && mtmp == u.ustuck) return FALSE;
107.  
108.  	if (flags.forcefight) {
109.  		/* Do this in the caller, after we checked that the monster
110.  		 * didn't die from the blow.  Reason: putting the 'I' there
111.  		 * causes the hero to forget the square's contents since
112.  		 * both 'I' and remembered contents are stored in .glyph.
113.  		 * If the monster dies immediately from the blow, the 'I' will
114.  		 * not stay there, so the player will have suddenly forgotten
115.  		 * the square's contents for no apparent reason.
116.  		if (!canspotmon(mtmp) &&
117.  		    !glyph_is_invisible(levl[u.ux+u.dx][u.uy+u.dy].glyph))
118.  			map_invisible(u.ux+u.dx, u.uy+u.dy);
119.  		 */
120.  		return FALSE;
121.  	}
122.  
123.  	/* Put up an invisible monster marker, but with exceptions for
124.  	 * monsters that hide and monsters you've been warned about.
125.  	 * The former already prints a warning message and
126.  	 * prevents you from hitting the monster just via the hidden monster
127.  	 * code below; if we also did that here, similar behavior would be
128.  	 * happening two turns in a row.  The latter shows a glyph on
129.  	 * the screen, so you know something is there.
130.  	 */
131.  	if (!canspotmon(mtmp) &&
132.  		    !glyph_is_warning(glyph_at(u.ux+u.dx,u.uy+u.dy)) &&
133.  		    !glyph_is_invisible(levl[u.ux+u.dx][u.uy+u.dy].glyph) &&
134.  		    !(!Blind && mtmp->mundetected && hides_under(mtmp->data))) {
135.  		pline("Wait!  There's %s there you can't see!",
136.  			something);
137.  		map_invisible(u.ux+u.dx, u.uy+u.dy);
138.  		/* if it was an invisible mimic, treat it as if we stumbled
139.  		 * onto a visible mimic
140.  		 */
141.  		if(mtmp->m_ap_type && !Protection_from_shape_changers) {
142.  		    if(!u.ustuck && !mtmp->mflee && dmgtype(mtmp->data,AD_STCK))
143.  			u.ustuck = mtmp;
144.  		}
145.  		wakeup(mtmp); /* always necessary; also un-mimics mimics */
146.  		return TRUE;
147.  	}
148.  
149.  	if (mtmp->m_ap_type && !Protection_from_shape_changers &&
150.  	   !sensemon(mtmp) &&
151.  	   !glyph_is_warning(glyph_at(u.ux+u.dx,u.uy+u.dy))) {
152.  		/* If a hidden mimic was in a square where a player remembers
153.  		 * some (probably different) unseen monster, the player is in
154.  		 * luck--he attacks it even though it's hidden.
155.  		 */
156.  		if (glyph_is_invisible(levl[mtmp->mx][mtmp->my].glyph)) {
157.  		    seemimic(mtmp);
158.  		    return(FALSE);
159.  		}
160.  		stumble_onto_mimic(mtmp);
161.  		return TRUE;
162.  	}
163.  
164.  	if (mtmp->mundetected && !canseemon(mtmp) &&
165.  		!glyph_is_warning(glyph_at(u.ux+u.dx,u.uy+u.dy)) &&
166.  		(hides_under(mtmp->data) || mtmp->data->mlet == S_EEL)) {
167.  	    mtmp->mundetected = mtmp->msleeping = 0;
168.  	    newsym(mtmp->mx, mtmp->my);
169.  	    if (glyph_is_invisible(levl[mtmp->mx][mtmp->my].glyph)) {
170.  		seemimic(mtmp);
171.  		return(FALSE);
172.  	    }
173.  	    if (!(Blind ? Blind_telepat : Unblind_telepat)) {
174.  		struct obj *obj;
175.  
176.  		if (Blind || (is_pool(mtmp->mx,mtmp->my) && !Underwater))
177.  		    pline("Wait!  There's a hidden monster there!");
178.  		else if ((obj = level.objects[mtmp->mx][mtmp->my]) != 0)
179.  		    pline("Wait!  There's %s hiding under %s!",
180.  			  an(l_monnam(mtmp)), doname(obj));
181.  		return TRUE;
182.  	    }
183.  	}
184.  
185.  	/*
186.  	 * make sure to wake up a monster from the above cases if the
187.  	 * hero can sense that the monster is there.
188.  	 */
189.  	if ((mtmp->mundetected || mtmp->m_ap_type) && sensemon(mtmp)) {
190.  	    mtmp->mundetected = 0;
191.  	    wakeup(mtmp);
192.  	}
193.  
194.  	if (flags.confirm && mtmp->mpeaceful
195.  	    && !Confusion && !Hallucination && !Stunned) {
196.  		/* Intelligent chaotic weapons (Stormbringer) want blood */
197.  		if (wep && wep->oartifact == ART_STORMBRINGER) {
198.  			override_confirmation = TRUE;
199.  			return(FALSE);
200.  		}
201.  		if (canspotmon(mtmp)) {
202.  			Sprintf(qbuf, "Really attack %s?", mon_nam(mtmp));
203.  			if (yn(qbuf) != 'y') {
204.  				flags.move = 0;
205.  				return(TRUE);
206.  			}
207.  		}
208.  	}
209.  
210.  	return(FALSE);
211.  }
212.  

check_caitiff Edit

213.  /*
214.   * It is unchivalrous for a knight to attack the defenseless or from behind.
215.   */
216.  void
217.  check_caitiff(mtmp)
218.  struct monst *mtmp;
219.  {
220.  	if (Role_if(PM_KNIGHT) && u.ualign.type == A_LAWFUL &&
221.  	    (!mtmp->mcanmove || mtmp->msleeping ||
222.  	     (mtmp->mflee && !mtmp->mavenge)) &&
223.  	    u.ualign.record > -10) {
224.  	    You("caitiff!");
225.  	    adjalign(-1);
226.  	}
227.  }
228.  

find_roll_to_hit Edit

229.  schar
230.  find_roll_to_hit(mtmp)
231.  register struct monst *mtmp;
232.  {
233.  	schar tmp;
234.  	int tmp2;
235.  
236.  	tmp = 1 + Luck + abon() + find_mac(mtmp) + u.uhitinc +
237.  		maybe_polyd(youmonst.data->mlevel, u.ulevel);
238.  
239.  	check_caitiff(mtmp);
240.  
241.  /*	attacking peaceful creatures is bad for the samurai's giri */
242.  	if (Role_if(PM_SAMURAI) && mtmp->mpeaceful &&
243.  	    u.ualign.record > -10) {
244.  	    You("dishonorably attack the innocent!");
245.  	    adjalign(-1);
246.  	}
247.  
248.  /*	Adjust vs. (and possibly modify) monster state.		*/
249.  
250.  	if(mtmp->mstun) tmp += 2;
251.  	if(mtmp->mflee) tmp += 2;
252.  
253.  	if (mtmp->msleeping) {
254.  		mtmp->msleeping = 0;
255.  		tmp += 2;
256.  	}
257.  	if(!mtmp->mcanmove) {
258.  		tmp += 4;
259.  		if(!rn2(10)) {
260.  			mtmp->mcanmove = 1;
261.  			mtmp->mfrozen = 0;
262.  		}
263.  	}
264.  	if (is_orc(mtmp->data) && maybe_polyd(is_elf(youmonst.data),
265.  			Race_if(PM_ELF)))
266.  	    tmp++;
267.  	if(Role_if(PM_MONK) && !Upolyd) {
268.  	    if (uarm) {
269.  		Your("armor is rather cumbersome...");
270.  		tmp -= urole.spelarmr;
271.  	    } else if (!uwep && !uarms) {
272.  		tmp += (u.ulevel / 3) + 2;
273.  	    }
274.  	}
275.  
276.  /*	with a lot of luggage, your agility diminishes */
277.  	if ((tmp2 = near_capacity()) != 0) tmp -= (tmp2*2) - 1;
278.  	if (u.utrap) tmp -= 3;
279.  /*	Some monsters have a combination of weapon attacks and non-weapon
280.   *	attacks.  It is therefore wrong to add hitval to tmp; we must add
281.   *	it only for the specific attack (in hmonas()).
282.   */
283.  	if (uwep && !Upolyd) {
284.  		tmp += hitval(uwep, mtmp);
285.  		tmp += weapon_hit_bonus(uwep);
286.  	}
287.  	return tmp;
288.  }
289.  

attack Edit

290.  /* try to attack; return FALSE if monster evaded */
291.  /* u.dx and u.dy must be set */
292.  boolean
293.  attack(mtmp)
294.  register struct monst *mtmp;
295.  {
296.  	schar tmp;
297.  	register struct permonst *mdat = mtmp->data;
298.  
299.  	/* This section of code provides protection against accidentally
300.  	 * hitting peaceful (like '@') and tame (like 'd') monsters.
301.  	 * Protection is provided as long as player is not: blind, confused,
302.  	 * hallucinating or stunned.
303.  	 * changes by wwp 5/16/85
304.  	 * More changes 12/90, -dkh-. if its tame and safepet, (and protected
305.  	 * 07/92) then we assume that you're not trying to attack. Instead,
306.  	 * you'll usually just swap places if this is a movement command
307.  	 */
308.  	/* Intelligent chaotic weapons (Stormbringer) want blood */
309.  	if (is_safepet(mtmp) && !flags.forcefight) {
310.  	    if (!uwep || uwep->oartifact != ART_STORMBRINGER) {
311.  		/* there are some additional considerations: this won't work
312.  		 * if in a shop or Punished or you miss a random roll or
313.  		 * if you can walk thru walls and your pet cannot (KAA) or
314.  		 * if your pet is a long worm (unless someone does better).
315.  		 * there's also a chance of displacing a "frozen" monster.
316.  		 * sleeping monsters might magically walk in their sleep.
317.  		 */
318.  		boolean foo = (Punished || !rn2(7) || is_longworm(mtmp->data)),
319.  			inshop = FALSE;
320.  		char *p;
321.  
322.  		for (p = in_rooms(mtmp->mx, mtmp->my, SHOPBASE); *p; p++)
323.  		    if (tended_shop(&rooms[*p - ROOMOFFSET])) {
324.  			inshop = TRUE;
325.  			break;
326.  		    }
327.  
328.  		if (inshop || foo ||
329.  			(IS_ROCK(levl[u.ux][u.uy].typ) &&
330.  					!passes_walls(mtmp->data))) {
331.  		    char buf[BUFSZ];
332.  
333.  		    monflee(mtmp, rnd(6), FALSE, FALSE);
334.  		    Strcpy(buf, y_monnam(mtmp));
335.  		    buf[0] = highc(buf[0]);
336.  		    You("stop.  %s is in the way!", buf);
337.  		    return(TRUE);
338.  		} else if ((mtmp->mfrozen || (! mtmp->mcanmove)
339.  				|| (mtmp->data->mmove == 0)) && rn2(6)) {
340.  		    pline("%s doesn't seem to move!", Monnam(mtmp));
341.  		    return(TRUE);
342.  		} else return(FALSE);
343.  	    }
344.  	}
345.  
346.  	/* possibly set in attack_checks;
347.  	   examined in known_hitum, called via hitum or hmonas below */
348.  	override_confirmation = FALSE;
349.  	if (attack_checks(mtmp, uwep)) return(TRUE);
350.  
351.  	if (Upolyd) {
352.  		/* certain "pacifist" monsters don't attack */
353.  		if(noattacks(youmonst.data)) {
354.  			You("have no way to attack monsters physically.");
355.  			mtmp->mstrategy &= ~STRAT_WAITMASK;
356.  			goto atk_done;
357.  		}
358.  	}
359.  
360.  	if(check_capacity("You cannot fight while so heavily loaded."))
361.  	    goto atk_done;
362.  
363.  	if (u.twoweap && !can_twoweapon())
364.  		untwoweapon();
365.  
366.  	if(unweapon) {
367.  	    unweapon = FALSE;
368.  	    if(flags.verbose) {
369.  		if(uwep)
370.  		    You("begin bashing monsters with your %s.",
371.  			aobjnam(uwep, (char *)0));
372.  		else if (!cantwield(youmonst.data))
373.  		    You("begin %sing monsters with your %s %s.",
374.  			Role_if(PM_MONK) ? "strik" : "bash",
375.  			uarmg ? "gloved" : "bare",	/* Del Lamb */
376.  			makeplural(body_part(HAND)));
377.  	    }
378.  	}
379.  	exercise(A_STR, TRUE);		/* you're exercising muscles */
380.  	/* andrew@orca: prevent unlimited pick-axe attacks */
381.  	u_wipe_engr(3);
382.  
383.  	/* Is the "it died" check actually correct? */
384.  	if(mdat->mlet == S_LEPRECHAUN && !mtmp->mfrozen && !mtmp->msleeping &&
385.  	   !mtmp->mconf && mtmp->mcansee && !rn2(7) &&
386.  	   (m_move(mtmp, 0) == 2 ||			    /* it died */
387.  	   mtmp->mx != u.ux+u.dx || mtmp->my != u.uy+u.dy)) /* it moved */
388.  		return(FALSE);
389.  
390.  	tmp = find_roll_to_hit(mtmp);
391.  	if (Upolyd)
392.  		(void) hmonas(mtmp, tmp);
393.  	else
394.  		(void) hitum(mtmp, tmp, youmonst.data->mattk);
395.  	mtmp->mstrategy &= ~STRAT_WAITMASK;
396.  
397.  atk_done:
398.  	/* see comment in attack_checks() */
399.  	/* we only need to check for this if we did an attack_checks()
400.  	 * and it returned 0 (it's okay to attack), and the monster didn't
401.  	 * evade.
402.  	 */
403.  	if (flags.forcefight && mtmp->mhp > 0 && !canspotmon(mtmp) &&
404.  	    !glyph_is_invisible(levl[u.ux+u.dx][u.uy+u.dy].glyph) &&
405.  	    !(u.uswallow && mtmp == u.ustuck))
406.  		map_invisible(u.ux+u.dx, u.uy+u.dy);
407.  
408.  	return(TRUE);
409.  }
410.  

known_hitum Edit

411.  STATIC_OVL boolean
412.  known_hitum(mon, mhit, uattk)	/* returns TRUE if monster still lives */
413.  register struct monst *mon;
414.  register int *mhit;
415.  struct attack *uattk;
416.  {
417.  	register boolean malive = TRUE;
418.  
419.  	if (override_confirmation) {
420.  	    /* this may need to be generalized if weapons other than
421.  	       Stormbringer acquire similar anti-social behavior... */
422.  	    if (flags.verbose) Your("bloodthirsty blade attacks!");
423.  	}
424.  
425.  	if(!*mhit) {
426.  	    missum(mon, uattk);
427.  	} else {
428.  	    int oldhp = mon->mhp,
429.  		x = u.ux + u.dx, y = u.uy + u.dy;
430.  
431.  	    /* KMH, conduct */
432.  	    if (uwep && (uwep->oclass == WEAPON_CLASS || is_weptool(uwep)))
433.  		u.uconduct.weaphit++;
434.  
435.  	    /* we hit the monster; be careful: it might die or
436.  	       be knocked into a different location */
437.  	    notonhead = (mon->mx != x || mon->my != y);
438.  	    malive = hmon(mon, uwep, 0);
439.  	    /* this assumes that Stormbringer was uwep not uswapwep */ 
440.  	    if (malive && u.twoweap && !override_confirmation &&
441.  		    m_at(x, y) == mon)
442.  		malive = hmon(mon, uswapwep, 0);
443.  	    if (malive) {
444.  		/* monster still alive */
445.  		if(!rn2(25) && mon->mhp < mon->mhpmax/2
446.  			    && !(u.uswallow && mon == u.ustuck)) {
447.  		    /* maybe should regurgitate if swallowed? */
448.  		    if(!rn2(3)) {
449.  			monflee(mon, rnd(100), FALSE, TRUE);
450.  		    } else monflee(mon, 0, FALSE, TRUE);
451.  
452.  		    if(u.ustuck == mon && !u.uswallow && !sticks(youmonst.data))
453.  			u.ustuck = 0;
454.  		}
455.  		/* Vorpal Blade hit converted to miss */
456.  		/* could be headless monster or worm tail */
457.  		if (mon->mhp == oldhp) {
458.  		    *mhit = 0;
459.  		    /* a miss does not break conduct */
460.  		    if (uwep &&
461.  			(uwep->oclass == WEAPON_CLASS || is_weptool(uwep)))
462.  			--u.uconduct.weaphit;
463.  		}
464.  		if (mon->wormno && *mhit)
465.  		    cutworm(mon, x, y, uwep);
466.  	    }
467.  	}
468.  	return(malive);
469.  }
470.  

hitum Edit

471.  STATIC_OVL boolean
472.  hitum(mon, tmp, uattk)		/* returns TRUE if monster still lives */
473.  struct monst *mon;
474.  int tmp;
475.  struct attack *uattk;
476.  {
477.  	boolean malive;
478.  	int mhit = (tmp > (dieroll = rnd(20)) || u.uswallow);
479.  
480.  	if(tmp > dieroll) exercise(A_DEX, TRUE);
481.  	malive = known_hitum(mon, &mhit, uattk);
482.  	(void) passive(mon, mhit, malive, AT_WEAP);
483.  	return(malive);
484.  }
485.  

hmon Edit

486.  boolean			/* general "damage monster" routine */
487.  hmon(mon, obj, thrown)		/* return TRUE if mon still alive */
488.  struct monst *mon;
489.  struct obj *obj;
490.  int thrown;
491.  {
492.  	boolean result, anger_guards;
493.  
494.  	anger_guards = (mon->mpeaceful &&
495.  			    (mon->ispriest || mon->isshk ||
496.  			     mon->data == &mons[PM_WATCHMAN] ||
497.  			     mon->data == &mons[PM_WATCH_CAPTAIN]));
498.  	result = hmon_hitmon(mon, obj, thrown);
499.  	if (mon->ispriest && !rn2(2)) ghod_hitsu(mon);
500.  	if (anger_guards) (void)angry_guards(!flags.soundok);
501.  	return result;
502.  }
503.  

hmon_hitmon Edit

504.  /* guts of hmon() */
505.  STATIC_OVL boolean
506.  hmon_hitmon(mon, obj, thrown)
507.  struct monst *mon;
508.  struct obj *obj;
509.  int thrown;
510.  {
511.  	int tmp;
512.  	struct permonst *mdat = mon->data;
513.  	int barehand_silver_rings = 0;
514.  	/* The basic reason we need all these booleans is that we don't want
515.  	 * a "hit" message when a monster dies, so we have to know how much
516.  	 * damage it did _before_ outputting a hit message, but any messages
517.  	 * associated with the damage don't come out until _after_ outputting
518.  	 * a hit message.
519.  	 */
520.  	boolean hittxt = FALSE, destroyed = FALSE, already_killed = FALSE;
521.  	boolean get_dmg_bonus = TRUE;
522.  	boolean ispoisoned = FALSE, needpoismsg = FALSE, poiskilled = FALSE;
523.  	boolean silvermsg = FALSE, silverobj = FALSE;
524.  	boolean valid_weapon_attack = FALSE;
525.  	boolean unarmed = !uwep && !uarm && !uarms;
526.  #ifdef STEED
527.  	int jousting = 0;
528.  #endif
529.  	int wtype;
530.  	struct obj *monwep;
531.  	char yourbuf[BUFSZ];
532.  	char unconventional[BUFSZ];	/* substituted for word "attack" in msg */
533.  	char saved_oname[BUFSZ];
534.  
535.  	unconventional[0] = '\0';
536.  	saved_oname[0] = '\0';
537.  
538.  	wakeup(mon);
539.  	if(!obj) {	/* attack with bare hands */
540.  	    if (mdat == &mons[PM_SHADE])
541.  		tmp = 0;
542.  	    else if (martial_bonus())
543.  		tmp = rnd(4);	/* bonus for martial arts */
544.  	    else
545.  		tmp = rnd(2);
546.  	    valid_weapon_attack = (tmp > 1);
547.  	    /* blessed gloves give bonuses when fighting 'bare-handed' */
548.  	    if (uarmg && uarmg->blessed && (is_undead(mdat) || is_demon(mdat)))
549.  		tmp += rnd(4);
550.  	    /* So do silver rings.  Note: rings are worn under gloves, so you
551.  	     * don't get both bonuses.
552.  	     */
553.  	    if (!uarmg) {
554.  		if (uleft && objects[uleft->otyp].oc_material == SILVER)
555.  		    barehand_silver_rings++;
556.  		if (uright && objects[uright->otyp].oc_material == SILVER)
557.  		    barehand_silver_rings++;
558.  		if (barehand_silver_rings && hates_silver(mdat)) {
559.  		    tmp += rnd(20);
560.  		    silvermsg = TRUE;
561.  		}
562.  	    }
563.  	} else {
564.  	    Strcpy(saved_oname, cxname(obj));
565.  	    if(obj->oclass == WEAPON_CLASS || is_weptool(obj) ||
566.  	       obj->oclass == GEM_CLASS) {
567.  
568.  		/* is it not a melee weapon? */
569.  		if (/* if you strike with a bow... */
570.  		    is_launcher(obj) ||
571.  		    /* or strike with a missile in your hand... */
572.  		    (!thrown && (is_missile(obj) || is_ammo(obj))) ||
573.  		    /* or use a pole at short range and not mounted... */
574.  		    (!thrown &&
575.  #ifdef STEED
576.  		     !u.usteed &&
577.  #endif
578.  		     is_pole(obj)) ||
579.  		    /* or throw a missile without the proper bow... */
580.  		    (is_ammo(obj) && !ammo_and_launcher(obj, uwep))) {
581.  		    /* then do only 1-2 points of damage */
582.  		    if (mdat == &mons[PM_SHADE] && obj->otyp != SILVER_ARROW)
583.  			tmp = 0;
584.  		    else
585.  			tmp = rnd(2);
586.  		    if (!thrown && obj == uwep && obj->otyp == BOOMERANG &&
587.  			    rnl(4) == 4-1) {
588.  			boolean more_than_1 = (obj->quan > 1L);
589.  
590.  			pline("As you hit %s, %s%s %s breaks into splinters.",
591.  			      mon_nam(mon), more_than_1 ? "one of " : "",
592.  			      shk_your(yourbuf, obj), xname(obj));
593.  			if (!more_than_1) uwepgone();	/* set unweapon */
594.  			useup(obj);
595.  			if (!more_than_1) obj = (struct obj *) 0;
596.  			hittxt = TRUE;
597.  			if (mdat != &mons[PM_SHADE])
598.  			    tmp++;
599.  		    }
600.  		} else {
601.  		    tmp = dmgval(obj, mon);
602.  		    /* a minimal hit doesn't exercise proficiency */
603.  		    valid_weapon_attack = (tmp > 1);
604.  		    if (!valid_weapon_attack || mon == u.ustuck || u.twoweap) {
605.  			;	/* no special bonuses */
606.  		    } else if (mon->mflee && Role_if(PM_ROGUE) && !Upolyd) {
607.  			You("strike %s from behind!", mon_nam(mon));
608.  			tmp += rnd(u.ulevel);
609.  			hittxt = TRUE;
610.  		    } else if (dieroll == 2 && obj == uwep &&
611.  			  obj->oclass == WEAPON_CLASS &&
612.  			  (bimanual(obj) ||
613.  			    (Role_if(PM_SAMURAI) && obj->otyp == KATANA && !uarms)) &&
614.  			  ((wtype = uwep_skill_type()) != P_NONE &&
615.  			    P_SKILL(wtype) >= P_SKILLED) &&
616.  			  ((monwep = MON_WEP(mon)) != 0 &&
617.  			   !is_flimsy(monwep) &&
618.  			   !obj_resists(monwep,
619.  				 50 + 15 * greatest_erosion(obj), 100))) {
620.  			/*
621.  			 * 2.5% chance of shattering defender's weapon when
622.  			 * using a two-handed weapon; less if uwep is rusted.
623.  			 * [dieroll == 2 is most successful non-beheading or
624.  			 * -bisecting hit, in case of special artifact damage;
625.  			 * the percentage chance is (1/20)*(50/100).]
626.  			 */
627.  			setmnotwielded(mon,monwep);
628.  			MON_NOWEP(mon);
629.  			mon->weapon_check = NEED_WEAPON;
630.  			pline("%s %s %s from the force of your blow!",
631.  			      s_suffix(Monnam(mon)), xname(monwep),
632.  			      otense(monwep, "shatter"));
633.  			m_useup(mon, monwep);
634.  			/* If someone just shattered MY weapon, I'd flee! */
635.  			if (rn2(4)) {
636.  			    monflee(mon, d(2,3), TRUE, TRUE);
637.  			}
638.  			hittxt = TRUE;
639.  		    }
640.  
641.  		    if (obj->oartifact &&
642.  			artifact_hit(&youmonst, mon, obj, &tmp, dieroll)) {
643.  			if(mon->mhp <= 0) /* artifact killed monster */
644.  			    return FALSE;
645.  			if (tmp == 0) return TRUE;
646.  			hittxt = TRUE;
647.  		    }
648.  		    if (objects[obj->otyp].oc_material == SILVER
649.  				&& hates_silver(mdat)) {
650.  			silvermsg = TRUE; silverobj = TRUE;
651.  		    }
652.  #ifdef STEED
653.  		    if (u.usteed && !thrown && tmp > 0 &&
654.  			    weapon_type(obj) == P_LANCE && mon != u.ustuck) {
655.  			jousting = joust(mon, obj);
656.  			/* exercise skill even for minimal damage hits */
657.  			if (jousting) valid_weapon_attack = TRUE;
658.  		    }
659.  #endif
660.  		    if (thrown && (is_ammo(obj) || is_missile(obj))) {
661.  			if (ammo_and_launcher(obj, uwep)) {
662.  			    /* Elves and Samurai do extra damage using
663.  			     * their bows&arrows; they're highly trained.
664.  			     */
665.  			    if (Role_if(PM_SAMURAI) &&
666.  				obj->otyp == YA && uwep->otyp == YUMI)
667.  				tmp++;
668.  			    else if (Race_if(PM_ELF) &&
669.  				     obj->otyp == ELVEN_ARROW &&
670.  				     uwep->otyp == ELVEN_BOW)
671.  				tmp++;
672.  			}
673.  			if(obj->opoisoned && is_poisonable(obj))
674.  			    ispoisoned = TRUE;
675.  		    }
676.  		}
677.  	    } else if(obj->oclass == POTION_CLASS) {
678.  		if (obj->quan > 1L)
679.  		    obj = splitobj(obj, 1L);
680.  		else
681.  		    setuwep((struct obj *)0);
682.  		freeinv(obj);
683.  		potionhit(mon, obj, TRUE);
684.  		if (mon->mhp <= 0) return FALSE;	/* killed */
685.  		hittxt = TRUE;
686.  		/* in case potion effect causes transformation */
687.  		mdat = mon->data;
688.  		tmp = (mdat == &mons[PM_SHADE]) ? 0 : 1;
689.  	    } else {
690.  		if (mdat == &mons[PM_SHADE] && !shade_aware(obj)) {
691.  		    tmp = 0;
692.  		    Strcpy(unconventional, cxname(obj));
693.  		} else {
694.  		    switch(obj->otyp) {
695.  		    case BOULDER:		/* 1d20 */
696.  		    case HEAVY_IRON_BALL:	/* 1d25 */
697.  		    case IRON_CHAIN:		/* 1d4+1 */
698.  			tmp = dmgval(obj, mon);
699.  			break;
700.  		    case MIRROR:
701.  			if (breaktest(obj)) {
702.  			    You("break %s mirror.  That's bad luck!",
703.  				shk_your(yourbuf, obj));
704.  			    change_luck(-2);
705.  			    useup(obj);
706.  			    obj = (struct obj *) 0;
707.  			    unarmed = FALSE;	/* avoid obj==0 confusion */
708.  			    get_dmg_bonus = FALSE;
709.  			    hittxt = TRUE;
710.  			}
711.  			tmp = 1;
712.  			break;
713.  #ifdef TOURIST
714.  		    case EXPENSIVE_CAMERA:
715.  			You("succeed in destroying %s camera.  Congratulations!",
716.  			        shk_your(yourbuf, obj));
717.  			useup(obj);
718.  			return(TRUE);
719.  			/*NOTREACHED*/
720.  			break;
721.  #endif
722.  		    case CORPSE:		/* fixed by polder@cs.vu.nl */
723.  			if (touch_petrifies(&mons[obj->corpsenm])) {
724.  			    static const char withwhat[] = "corpse";
725.  			    tmp = 1;
726.  			    hittxt = TRUE;
727.  			    You("hit %s with %s %s.", mon_nam(mon),
728.  				obj->dknown ? the(mons[obj->corpsenm].mname) :
729.  				an(mons[obj->corpsenm].mname),
730.  				(obj->quan > 1) ? makeplural(withwhat) : withwhat);
731.  			    if (!munstone(mon, TRUE))
732.  				minstapetrify(mon, TRUE);
733.  			    if (resists_ston(mon)) break;
734.  			    /* note: hp may be <= 0 even if munstoned==TRUE */
735.  			    return (boolean) (mon->mhp > 0);
736.  #if 0
737.  			} else if (touch_petrifies(mdat)) {
738.  			    /* maybe turn the corpse into a statue? */
739.  #endif
740.  			}
741.  			tmp = (obj->corpsenm >= LOW_PM ?
742.  					mons[obj->corpsenm].msize : 0) + 1;
743.  			break;
744.  		    case EGG:
745.  		      {
746.  #define useup_eggs(o)	{ if (thrown) obfree(o,(struct obj *)0); \
747.  			  else useupall(o); \
748.  			  o = (struct obj *)0; }	/* now gone */
749.  			long cnt = obj->quan;
750.  
751.  			tmp = 1;		/* nominal physical damage */
752.  			get_dmg_bonus = FALSE;
753.  			hittxt = TRUE;		/* message always given */
754.  			/* egg is always either used up or transformed, so next
755.  			   hand-to-hand attack should yield a "bashing" mesg */
756.  			if (obj == uwep) unweapon = TRUE;
757.  			if (obj->spe && obj->corpsenm >= LOW_PM) {
758.  			    if (obj->quan < 5)
759.  				change_luck((schar) -(obj->quan));
760.  			    else
761.  				change_luck(-5);
762.  			}
763.  
764.  			if (touch_petrifies(&mons[obj->corpsenm])) {
765.  			    /*learn_egg_type(obj->corpsenm);*/
766.  			    pline("Splat! You hit %s with %s %s egg%s!",
767.  				mon_nam(mon),
768.  				obj->known ? "the" : cnt > 1L ? "some" : "a",
769.  				obj->known ? mons[obj->corpsenm].mname : "petrifying",
770.  				plur(cnt));
771.  			    obj->known = 1;	/* (not much point...) */
772.  			    useup_eggs(obj);
773.  			    if (!munstone(mon, TRUE))
774.  				minstapetrify(mon, TRUE);
775.  			    if (resists_ston(mon)) break;
776.  			    return (boolean) (mon->mhp > 0);
777.  			} else {	/* ordinary egg(s) */
778.  			    const char *eggp =
779.  				     (obj->corpsenm != NON_PM && obj->known) ?
780.  					      the(mons[obj->corpsenm].mname) :
781.  					      (cnt > 1L) ? "some" : "an";
782.  			    You("hit %s with %s egg%s.",
783.  				mon_nam(mon), eggp, plur(cnt));
784.  			    if (touch_petrifies(mdat) && !stale_egg(obj)) {
785.  				pline_The("egg%s %s alive any more...",
786.  				      plur(cnt),
787.  				      (cnt == 1L) ? "isn't" : "aren't");
788.  				if (obj->timed) obj_stop_timers(obj);
789.  				obj->otyp = ROCK;
790.  				obj->oclass = GEM_CLASS;
791.  				obj->oartifact = 0;
792.  				obj->spe = 0;
793.  				obj->known = obj->dknown = obj->bknown = 0;
794.  				obj->owt = weight(obj);
795.  				if (thrown) place_object(obj, mon->mx, mon->my);
796.  			    } else {
797.  				pline("Splat!");
798.  				useup_eggs(obj);
799.  				exercise(A_WIS, FALSE);
800.  			    }
801.  			}
802.  			break;
803.  #undef useup_eggs
804.  		      }
805.  		    case CLOVE_OF_GARLIC:	/* no effect against demons */
806.  			if (is_undead(mdat)) {
807.  			    monflee(mon, d(2, 4), FALSE, TRUE);
808.  			}
809.  			tmp = 1;
810.  			break;
811.  		    case CREAM_PIE:
812.  		    case BLINDING_VENOM:
813.  			mon->msleeping = 0;
814.  			if (can_blnd(&youmonst, mon, (uchar)
815.  				    (obj->otyp == BLINDING_VENOM
816.  				     ? AT_SPIT : AT_WEAP), obj)) {
817.  			    if (Blind) {
818.  				pline(obj->otyp == CREAM_PIE ?
819.  				      "Splat!" : "Splash!");
820.  			    } else if (obj->otyp == BLINDING_VENOM) {
821.  				pline_The("venom blinds %s%s!", mon_nam(mon),
822.  					  mon->mcansee ? "" : " further");
823.  			    } else {
824.  				char *whom = mon_nam(mon);
825.  				char *what = The(xname(obj));
826.  				if (!thrown && obj->quan > 1)
827.  				    what = An(singular(obj, xname));
828.  				/* note: s_suffix returns a modifiable buffer */
829.  				if (haseyes(mdat)
830.  				    && mdat != &mons[PM_FLOATING_EYE])
831.  				    whom = strcat(strcat(s_suffix(whom), " "),
832.  						  mbodypart(mon, FACE));
833.  				pline("%s %s over %s!",
834.  				      what, vtense(what, "splash"), whom);
835.  			    }
836.  			    setmangry(mon);
837.  			    mon->mcansee = 0;
838.  			    tmp = rn1(25, 21);
839.  			    if(((int) mon->mblinded + tmp) > 127)
840.  				mon->mblinded = 127;
841.  			    else mon->mblinded += tmp;
842.  			} else {
843.  			    pline(obj->otyp==CREAM_PIE ? "Splat!" : "Splash!");
844.  			    setmangry(mon);
845.  			}
846.  			if (thrown) obfree(obj, (struct obj *)0);
847.  			else useup(obj);
848.  			hittxt = TRUE;
849.  			get_dmg_bonus = FALSE;
850.  			tmp = 0;
851.  			break;
852.  		    case ACID_VENOM: /* thrown (or spit) */
853.  			if (resists_acid(mon)) {
854.  				Your("venom hits %s harmlessly.",
855.  					mon_nam(mon));
856.  				tmp = 0;
857.  			} else {
858.  				Your("venom burns %s!", mon_nam(mon));
859.  				tmp = dmgval(obj, mon);
860.  			}
861.  			if (thrown) obfree(obj, (struct obj *)0);
862.  			else useup(obj);
863.  			hittxt = TRUE;
864.  			get_dmg_bonus = FALSE;
865.  			break;
866.  		    default:
867.  			/* non-weapons can damage because of their weight */
868.  			/* (but not too much) */
869.  			tmp = obj->owt/100;
870.  			if(tmp < 1) tmp = 1;
871.  			else tmp = rnd(tmp);
872.  			if(tmp > 6) tmp = 6;
873.  			/*
874.  			 * Things like silver wands can arrive here so
875.  			 * so we need another silver check.
876.  			 */
877.  			if (objects[obj->otyp].oc_material == SILVER
878.  						&& hates_silver(mdat)) {
879.  				tmp += rnd(20);
880.  				silvermsg = TRUE; silverobj = TRUE;
881.  			}
882.  		    }
883.  		}
884.  	    }
885.  	}
886.  
887.  	/****** NOTE: perhaps obj is undefined!! (if !thrown && BOOMERANG)
888.  	 *      *OR* if attacking bare-handed!! */
889.  
890.  	if (get_dmg_bonus && tmp > 0) {
891.  		tmp += u.udaminc;
892.  		/* If you throw using a propellor, you don't get a strength
893.  		 * bonus but you do get an increase-damage bonus.
894.  		 */
895.  		if(!thrown || !obj || !uwep || !ammo_and_launcher(obj, uwep))
896.  		    tmp += dbon();
897.  	}
898.  
899.  	if (valid_weapon_attack) {
900.  	    struct obj *wep;
901.  
902.  	    /* to be valid a projectile must have had the correct projector */
903.  	    wep = PROJECTILE(obj) ? uwep : obj;
904.  	    tmp += weapon_dam_bonus(wep);
905.  	    /* [this assumes that `!thrown' implies wielded...] */
906.  	    wtype = thrown ? weapon_type(wep) : uwep_skill_type();
907.  	    use_skill(wtype, 1);
908.  	}
909.  
910.  	if (ispoisoned) {
911.  	    int nopoison = (10 - (obj->owt/10));            
912.  	    if(nopoison < 2) nopoison = 2;
913.  	    if Role_if(PM_SAMURAI) {
914.  		You("dishonorably use a poisoned weapon!");
915.  		adjalign(-sgn(u.ualign.type));
916.  	    } else if ((u.ualign.type == A_LAWFUL) && (u.ualign.record > -10)) {
917.  		You_feel("like an evil coward for using a poisoned weapon.");
918.  		adjalign(-1);
919.  	    }
920.  	    if (obj && !rn2(nopoison)) {
921.  		obj->opoisoned = FALSE;
922.  		Your("%s %s no longer poisoned.", xname(obj),
923.  		     otense(obj, "are"));
924.  	    }
925.  	    if (resists_poison(mon))
926.  		needpoismsg = TRUE;
927.  	    else if (rn2(10))
928.  		tmp += rnd(6);
929.  	    else poiskilled = TRUE;
930.  	}
931.  	if (tmp < 1) {
932.  	    /* make sure that negative damage adjustment can't result
933.  	       in inadvertently boosting the victim's hit points */
934.  	    tmp = 0;
935.  	    if (mdat == &mons[PM_SHADE]) {
936.  		if (!hittxt) {
937.  		    const char *what = unconventional[0] ? unconventional : "attack";
938.  		    Your("%s %s harmlessly through %s.",
939.  		    	what, vtense(what, "pass"),
940.  			mon_nam(mon));
941.  		    hittxt = TRUE;
942.  		}
943.  	    } else {
944.  		if (get_dmg_bonus) tmp = 1;
945.  	    }
946.  	}
947.  
948.  #ifdef STEED
949.  	if (jousting) {
950.  	    tmp += d(2, (obj == uwep) ? 10 : 2);	/* [was in dmgval()] */
951.  	    You("joust %s%s",
952.  			 mon_nam(mon), canseemon(mon) ? exclam(tmp) : ".");
953.  	    if (jousting < 0) {
954.  		Your("%s shatters on impact!", xname(obj));
955.  		/* (must be either primary or secondary weapon to get here) */
956.  		u.twoweap = FALSE;	/* untwoweapon() is too verbose here */
957.  		if (obj == uwep) uwepgone();		/* set unweapon */
958.  		/* minor side-effect: broken lance won't split puddings */
959.  		useup(obj);
960.  		obj = 0;
961.  	    }
962.  	    /* avoid migrating a dead monster */
963.  	    if (mon->mhp > tmp) {
964.  		mhurtle(mon, u.dx, u.dy, 1);
965.  		mdat = mon->data; /* in case of a polymorph trap */
966.  		if (DEADMONSTER(mon)) already_killed = TRUE;
967.  	    }
968.  	    hittxt = TRUE;
969.  	} else
970.  #endif
971.  
972.  	/* VERY small chance of stunning opponent if unarmed. */
973.  	if (unarmed && tmp > 1 && !thrown && !obj && !Upolyd) {
974.  	    if (rnd(100) < P_SKILL(P_BARE_HANDED_COMBAT) &&
975.  			!bigmonst(mdat) && !thick_skinned(mdat)) {
976.  		if (canspotmon(mon))
977.  		    pline("%s %s from your powerful strike!", Monnam(mon),
978.  			  makeplural(stagger(mon->data, "stagger")));
979.  		/* avoid migrating a dead monster */
980.  		if (mon->mhp > tmp) {
981.  		    mhurtle(mon, u.dx, u.dy, 1);
982.  		    mdat = mon->data; /* in case of a polymorph trap */
983.  		    if (DEADMONSTER(mon)) already_killed = TRUE;
984.  		}
985.  		hittxt = TRUE;
986.  	    }
987.  	}
988.  
989.  	if (!already_killed) mon->mhp -= tmp;
990.  	/* adjustments might have made tmp become less than what
991.  	   a level draining artifact has already done to max HP */
992.  	if (mon->mhp > mon->mhpmax) mon->mhp = mon->mhpmax;
993.  	if (mon->mhp < 1)
994.  		destroyed = TRUE;
995.  	if (mon->mtame && (!mon->mflee || mon->mfleetim) && tmp > 0) {
996.  		abuse_dog(mon);
997.  		monflee(mon, 10 * rnd(tmp), FALSE, FALSE);
998.  	}
999.  	if((mdat == &mons[PM_BLACK_PUDDING] || mdat == &mons[PM_BROWN_PUDDING])
1000. 		   && obj && obj == uwep
1001. 		   && objects[obj->otyp].oc_material == IRON
1002. 		   && mon->mhp > 1 && !thrown && !mon->mcan
1003. 		   /* && !destroyed  -- guaranteed by mhp > 1 */ ) {
1004. 		if (clone_mon(mon, 0, 0)) {
1005. 			pline("%s divides as you hit it!", Monnam(mon));
1006. 			hittxt = TRUE;
1007. 		}
1008. 	}
1009. 
1010. 	if (!hittxt &&			/*( thrown => obj exists )*/
1011. 	  (!destroyed || (thrown && m_shot.n > 1 && m_shot.o == obj->otyp))) {
1012. 		if (thrown) hit(mshot_xname(obj), mon, exclam(tmp));
1013. 		else if (!flags.verbose) You("hit it.");
1014. 		else You("%s %s%s", Role_if(PM_BARBARIAN) ? "smite" : "hit",
1015. 			 mon_nam(mon), canseemon(mon) ? exclam(tmp) : ".");
1016. 	}
1017. 
1018. 	if (silvermsg) {
1019. 		const char *fmt;
1020. 		char *whom = mon_nam(mon);
1021. 		char silverobjbuf[BUFSZ];
1022. 
1023. 		if (canspotmon(mon)) {
1024. 		    if (barehand_silver_rings == 1)
1025. 			fmt = "Your silver ring sears %s!";
1026. 		    else if (barehand_silver_rings == 2)
1027. 			fmt = "Your silver rings sear %s!";
1028. 		    else if (silverobj && saved_oname[0]) {
1029. 		    	Sprintf(silverobjbuf, "Your %s%s %s %%s!",
1030. 		    		strstri(saved_oname, "silver") ?
1031. 					"" : "silver ",
1032. 				saved_oname, vtense(saved_oname, "sear"));
1033. 		    	fmt = silverobjbuf;
1034. 		    } else
1035. 			fmt = "The silver sears %s!";
1036. 		} else {
1037. 		    *whom = highc(*whom);	/* "it" -> "It" */
1038. 		    fmt = "%s is seared!";
1039. 		}
1040. 		/* note: s_suffix returns a modifiable buffer */
1041. 		if (!noncorporeal(mdat))
1042. 		    whom = strcat(s_suffix(whom), " flesh");
1043. 		pline(fmt, whom);
1044. 	}
1045. 
1046. 	if (needpoismsg)
1047. 		pline_The("poison doesn't seem to affect %s.", mon_nam(mon));
1048. 	if (poiskilled) {
1049. 		pline_The("poison was deadly...");
1050. 		if (!already_killed) xkilled(mon, 0);
1051. 		return FALSE;
1052. 	} else if (destroyed) {
1053. 		if (!already_killed)
1054. 		    killed(mon);	/* takes care of most messages */
1055. 	} else if(u.umconf && !thrown) {
1056. 		nohandglow(mon);
1057. 		if (!mon->mconf && !resist(mon, SPBOOK_CLASS, 0, NOTELL)) {
1058. 			mon->mconf = 1;
1059. 			if (!mon->mstun && mon->mcanmove && !mon->msleeping &&
1060. 				canseemon(mon))
1061. 			    pline("%s appears confused.", Monnam(mon));
1062. 		}
1063. 	}
1064. 
1065. 	return((boolean)(destroyed ? FALSE : TRUE));
1066. }
1067. 

shade_aware Edit

1068. STATIC_OVL boolean
1069. shade_aware(obj)
1070. struct obj *obj;
1071. {
1072. 	if (!obj) return FALSE;
1073. 	/*
1074. 	 * The things in this list either
1075. 	 * 1) affect shades.
1076. 	 *  OR
1077. 	 * 2) are dealt with properly by other routines
1078. 	 *    when it comes to shades.
1079. 	 */
1080. 	if (obj->otyp == BOULDER || obj->otyp == HEAVY_IRON_BALL
1081. 	    || obj->otyp == IRON_CHAIN		/* dmgval handles those first three */
1082. 	    || obj->otyp == MIRROR		/* silver in the reflective surface */
1083. 	    || obj->otyp == CLOVE_OF_GARLIC	/* causes shades to flee */
1084. 	    || objects[obj->otyp].oc_material == SILVER)
1085. 		return TRUE;
1086. 	return FALSE;
1087. }
1088. 

m_slips_free Edit

1089. /* check whether slippery clothing protects from hug or wrap attack */
1090. /* [currently assumes that you are the attacker] */
1091. STATIC_OVL boolean
1092. m_slips_free(mdef, mattk)
1093. struct monst *mdef;
1094. struct attack *mattk;
1095. {
1096. 	struct obj *obj;
1097. 
1098. 	if (mattk->adtyp == AD_DRIN) {
1099. 	    /* intelligence drain attacks the head */
1100. 	    obj = which_armor(mdef, W_ARMH);
1101. 	} else {
1102. 	    /* grabbing attacks the body */
1103. 	    obj = which_armor(mdef, W_ARMC);		/* cloak */
1104. 	    if (!obj) obj = which_armor(mdef, W_ARM);	/* suit */
1105. #ifdef TOURIST
1106. 	    if (!obj) obj = which_armor(mdef, W_ARMU);	/* shirt */
1107. #endif
1108. 	}
1109. 
1110. 	/* if your cloak/armor is greased, monster slips off; this
1111. 	   protection might fail (33% chance) when the armor is cursed */
1112. 	if (obj && (obj->greased || obj->otyp == OILSKIN_CLOAK) &&
1113. 		(!obj->cursed || rn2(3))) {
1114. 	    You("%s %s %s %s!",
1115. 		mattk->adtyp == AD_WRAP ?
1116. 			"slip off of" : "grab, but cannot hold onto",
1117. 		s_suffix(mon_nam(mdef)),
1118. 		obj->greased ? "greased" : "slippery",
1119. 		/* avoid "slippery slippery cloak"
1120. 		   for undiscovered oilskin cloak */
1121. 		(obj->greased || objects[obj->otyp].oc_name_known) ?
1122. 			xname(obj) : cloak_simple_name(obj));
1123. 
1124. 	    if (obj->greased && !rn2(2)) {
1125. 		pline_The("grease wears off.");
1126. 		obj->greased = 0;
1127. 	    }
1128. 	    return TRUE;
1129. 	}
1130. 	return FALSE;
1131. }
1132. 

joust Edit

1133. /* used when hitting a monster with a lance while mounted */
1134. STATIC_OVL int	/* 1: joust hit; 0: ordinary hit; -1: joust but break lance */
1135. joust(mon, obj)
1136. struct monst *mon;	/* target */
1137. struct obj *obj;	/* weapon */
1138. {
1139.     int skill_rating, joust_dieroll;
1140. 
1141.     if (Fumbling || Stunned) return 0;
1142.     /* sanity check; lance must be wielded in order to joust */
1143.     if (obj != uwep && (obj != uswapwep || !u.twoweap)) return 0;
1144. 
1145.     /* if using two weapons, use worse of lance and two-weapon skills */
1146.     skill_rating = P_SKILL(weapon_type(obj));	/* lance skill */
1147.     if (u.twoweap && P_SKILL(P_TWO_WEAPON_COMBAT) < skill_rating)
1148. 	skill_rating = P_SKILL(P_TWO_WEAPON_COMBAT);
1149.     if (skill_rating == P_ISRESTRICTED) skill_rating = P_UNSKILLED; /* 0=>1 */
1150. 
1151.     /* odds to joust are expert:80%, skilled:60%, basic:40%, unskilled:20% */
1152.     if ((joust_dieroll = rn2(5)) < skill_rating) {
1153. 	if (joust_dieroll == 0 && rnl(50) == (50-1) &&
1154. 		!unsolid(mon->data) && !obj_resists(obj, 0, 100))
1155. 	    return -1;	/* hit that breaks lance */
1156. 	return 1;	/* successful joust */
1157.     }
1158.     return 0;	/* no joust bonus; revert to ordinary attack */
1159. }
1160. 

demonpet Edit

1161. /*
1162.  * Send in a demon pet for the hero.  Exercise wisdom.
1163.  *
1164.  * This function used to be inline to damageum(), but the Metrowerks compiler
1165.  * (DR4 and DR4.5) screws up with an internal error 5 "Expression Too Complex."
1166.  * Pulling it out makes it work.
1167.  */
1168. STATIC_OVL void
1169. demonpet()
1170. {
1171. 	int i;
1172. 	struct permonst *pm;
1173. 	struct monst *dtmp;
1174. 
1175. 	pline("Some hell-p has arrived!");
1176. 	i = !rn2(6) ? ndemon(u.ualign.type) : NON_PM;
1177. 	pm = i != NON_PM ? &mons[i] : youmonst.data;
1178. 	if ((dtmp = makemon(pm, u.ux, u.uy, NO_MM_FLAGS)) != 0)
1179. 	    (void)tamedog(dtmp, (struct obj *)0);
1180. 	exercise(A_WIS, TRUE);
1181. }
1182. 

steal_it Edit

1183. /*
1184.  * Player uses theft attack against monster.
1185.  *
1186.  * If the target is wearing body armor, take all of its possesions;
1187.  * otherwise, take one object.  [Is this really the behavior we want?]
1188.  *
1189.  * This routine implicitly assumes that there is no way to be able to
1190.  * resist petfication (ie, be polymorphed into a xorn or golem) at the
1191.  * same time as being able to steal (poly'd into nymph or succubus).
1192.  * If that ever changes, the check for touching a cockatrice corpse
1193.  * will need to be smarter about whether to break out of the theft loop.
1194.  */
1195. STATIC_OVL void
1196. steal_it(mdef, mattk)
1197. struct monst *mdef;
1198. struct attack *mattk;
1199. {
1200. 	struct obj *otmp, *stealoid, **minvent_ptr;
1201. 	long unwornmask;
1202. 
1203. 	if (!mdef->minvent) return;		/* nothing to take */
1204. 
1205. 	/* look for worn body armor */
1206. 	stealoid = (struct obj *)0;
1207. 	if (could_seduce(&youmonst, mdef, mattk)) {
1208. 	    /* find armor, and move it to end of inventory in the process */
1209. 	    minvent_ptr = &mdef->minvent;
1210. 	    while ((otmp = *minvent_ptr) != 0)
1211. 		if (otmp->owornmask & W_ARM) {
1212. 		    if (stealoid) panic("steal_it: multiple worn suits");
1213. 		    *minvent_ptr = otmp->nobj;	/* take armor out of minvent */
1214. 		    stealoid = otmp;
1215. 		    stealoid->nobj = (struct obj *)0;
1216. 		} else {
1217. 		    minvent_ptr = &otmp->nobj;
1218. 		}
1219. 	    *minvent_ptr = stealoid;	/* put armor back into minvent */
1220. 	}
1221. 
1222. 	if (stealoid) {		/* we will be taking everything */
1223. 	    if (gender(mdef) == (int) u.mfemale &&
1224. 			youmonst.data->mlet == S_NYMPH)
1225. 		You("charm %s.  She gladly hands over her possessions.",
1226. 		    mon_nam(mdef));
1227. 	    else
1228. 		You("seduce %s and %s starts to take off %s clothes.",
1229. 		    mon_nam(mdef), mhe(mdef), mhis(mdef));
1230. 	}
1231. 
1232. 	while ((otmp = mdef->minvent) != 0) {
1233. 	    if (!Upolyd) break;		/* no longer have ability to steal */
1234. 	    /* take the object away from the monster */
1235. 	    obj_extract_self(otmp);
1236. 	    if ((unwornmask = otmp->owornmask) != 0L) {
1237. 		mdef->misc_worn_check &= ~unwornmask;
1238. 		if (otmp->owornmask & W_WEP) {
1239. 		    setmnotwielded(mdef,otmp);
1240. 		    MON_NOWEP(mdef);
1241. 		}
1242. 		otmp->owornmask = 0L;
1243. 		update_mon_intrinsics(mdef, otmp, FALSE, FALSE);
1244. 
1245. 		if (otmp == stealoid)	/* special message for final item */
1246. 		    pline("%s finishes taking off %s suit.",
1247. 			  Monnam(mdef), mhis(mdef));
1248. 	    }
1249. 	    /* give the object to the character */
1250. 	    otmp = hold_another_object(otmp, "You snatched but dropped %s.",
1251. 				       doname(otmp), "You steal: ");
1252. 	    if (otmp->where != OBJ_INVENT) continue;
1253. 	    if (otmp->otyp == CORPSE &&
1254. 		    touch_petrifies(&mons[otmp->corpsenm]) && !uarmg) {
1255. 		char kbuf[BUFSZ];
1256. 
1257. 		Sprintf(kbuf, "stolen %s corpse", mons[otmp->corpsenm].mname);
1258. 		instapetrify(kbuf);
1259. 		break;		/* stop the theft even if hero survives */
1260. 	    }
1261. 	    /* more take-away handling, after theft message */
1262. 	    if (unwornmask & W_WEP) {		/* stole wielded weapon */
1263. 		possibly_unwield(mdef, FALSE);
1264. 	    } else if (unwornmask & W_ARMG) {	/* stole worn gloves */
1265. 		mselftouch(mdef, (const char *)0, TRUE);
1266. 		if (mdef->mhp <= 0)	/* it's now a statue */
1267. 		    return;		/* can't continue stealing */
1268. 	    }
1269. 
1270. 	    if (!stealoid) break;	/* only taking one item */
1271. 	}
1272. }
1273. 

damageum Edit

1274. int
1275. damageum(mdef, mattk)
1276. register struct monst *mdef;
1277. register struct attack *mattk;
1278. {
1279. 	register struct permonst *pd = mdef->data;
1280. 	register int	tmp = d((int)mattk->damn, (int)mattk->damd);
1281. 	int armpro;
1282. 	boolean negated;
1283. 
1284. 	armpro = magic_negation(mdef);
1285. 	/* since hero can't be cancelled, only defender's armor applies */
1286. 	negated = !((rn2(3) >= armpro) || !rn2(50));
1287. 
1288. 	if (is_demon(youmonst.data) && !rn2(13) && !uwep
1289. 		&& u.umonnum != PM_SUCCUBUS && u.umonnum != PM_INCUBUS
1290. 		&& u.umonnum != PM_BALROG) {
1291. 	    demonpet();
1292. 	    return(0);
1293. 	}
1294. 	switch(mattk->adtyp) {
1295. 	    case AD_STUN:
1296. 		if(!Blind)
1297. 		    pline("%s %s for a moment.", Monnam(mdef),
1298. 			  makeplural(stagger(mdef->data, "stagger")));
1299. 		mdef->mstun = 1;
1300. 		goto physical;
1301. 	    case AD_LEGS:
1302. 	     /* if (u.ucancelled) { */
1303. 	     /*    tmp = 0;	    */
1304. 	     /*    break;	    */
1305. 	     /* }		    */
1306. 		goto physical;
1307. 	    case AD_WERE:	    /* no special effect on monsters */
1308. 	    case AD_HEAL:	    /* likewise */
1309. 	    case AD_PHYS:
1310.  physical:
1311. 		if(mattk->aatyp == AT_WEAP) {
1312. 		    if(uwep) tmp = 0;
1313. 		} else if(mattk->aatyp == AT_KICK) {
1314. 		    if(thick_skinned(mdef->data)) tmp = 0;
1315. 		    if(mdef->data == &mons[PM_SHADE]) {
1316. 			if (!(uarmf && uarmf->blessed)) {
1317. 			    impossible("bad shade attack function flow?");
1318. 			    tmp = 0;
1319. 			} else
1320. 			    tmp = rnd(4); /* bless damage */
1321. 		    }
1322. 		}
1323. 		break;
1324. 	    case AD_FIRE:
1325. 		if (negated) {
1326. 		    tmp = 0;
1327. 		    break;
1328. 		}
1329. 		if (!Blind)
1330. 		    pline("%s is %s!", Monnam(mdef),
1331. 			  on_fire(mdef->data, mattk));
1332. 		if (pd == &mons[PM_STRAW_GOLEM] ||
1333. 		    pd == &mons[PM_PAPER_GOLEM]) {
1334. 		    if (!Blind)
1335. 			pline("%s burns completely!", Monnam(mdef));
1336. 		    xkilled(mdef,2);
1337. 		    tmp = 0;
1338. 		    break;
1339. 		    /* Don't return yet; keep hp<1 and tmp=0 for pet msg */
1340. 		}
1341. 		tmp += destroy_mitem(mdef, SCROLL_CLASS, AD_FIRE);
1342. 		tmp += destroy_mitem(mdef, SPBOOK_CLASS, AD_FIRE);
1343. 		if (resists_fire(mdef)) {
1344. 		    if (!Blind)
1345. 			pline_The("fire doesn't heat %s!", mon_nam(mdef));
1346. 		    golemeffects(mdef, AD_FIRE, tmp);
1347. 		    shieldeff(mdef->mx, mdef->my);
1348. 		    tmp = 0;
1349. 		}
1350. 		/* only potions damage resistant players in destroy_item */
1351. 		tmp += destroy_mitem(mdef, POTION_CLASS, AD_FIRE);
1352. 		break;
1353. 	    case AD_COLD:
1354. 		if (negated) {
1355. 		    tmp = 0;
1356. 		    break;
1357. 		}
1358. 		if (!Blind) pline("%s is covered in frost!", Monnam(mdef));
1359. 		if (resists_cold(mdef)) {
1360. 		    shieldeff(mdef->mx, mdef->my);
1361. 		    if (!Blind)
1362. 			pline_The("frost doesn't chill %s!", mon_nam(mdef));
1363. 		    golemeffects(mdef, AD_COLD, tmp);
1364. 		    tmp = 0;
1365. 		}
1366. 		tmp += destroy_mitem(mdef, POTION_CLASS, AD_COLD);
1367. 		break;
1368. 	    case AD_ELEC:
1369. 		if (negated) {
1370. 		    tmp = 0;
1371. 		    break;
1372. 		}
1373. 		if (!Blind) pline("%s is zapped!", Monnam(mdef));
1374. 		tmp += destroy_mitem(mdef, WAND_CLASS, AD_ELEC);
1375. 		if (resists_elec(mdef)) {
1376. 		    if (!Blind)
1377. 			pline_The("zap doesn't shock %s!", mon_nam(mdef));
1378. 		    golemeffects(mdef, AD_ELEC, tmp);
1379. 		    shieldeff(mdef->mx, mdef->my);
1380. 		    tmp = 0;
1381. 		}
1382. 		/* only rings damage resistant players in destroy_item */
1383. 		tmp += destroy_mitem(mdef, RING_CLASS, AD_ELEC);
1384. 		break;
1385. 	    case AD_ACID:
1386. 		if (resists_acid(mdef)) tmp = 0;
1387. 		break;
1388. 	    case AD_STON:
1389. 		if (!munstone(mdef, TRUE))
1390. 		    minstapetrify(mdef, TRUE);
1391. 		tmp = 0;
1392. 		break;
1393. #ifdef SEDUCE
1394. 	    case AD_SSEX:
1395. #endif
1396. 	    case AD_SEDU:
1397. 	    case AD_SITM:
1398. 		steal_it(mdef, mattk);
1399. 		tmp = 0;
1400. 		break;
1401. 	    case AD_SGLD:
1402. #ifndef GOLDOBJ
1403. 		if (mdef->mgold) {
1404. 		    u.ugold += mdef->mgold;
1405. 		    mdef->mgold = 0;
1406. 		    Your("purse feels heavier.");
1407. 		}
1408. #else
1409.                 /* This you as a leprechaun, so steal
1410.                    real gold only, no lesser coins */
1411. 	        {
1412. 		    struct obj *mongold = findgold(mdef->minvent);
1413. 	            if (mongold) {
1414. 		        obj_extract_self(mongold);  
1415. 		        if (merge_choice(invent, mongold) || inv_cnt() < 52) {
1416. 			    addinv(mongold);
1417. 			    Your("purse feels heavier.");
1418. 			} else {
1419.                             You("grab %s's gold, but find no room in your knapsack.", mon_nam(mdef));
1420. 			    dropy(mongold);
1421. 		        }
1422. 		    }
1423. 	        }
1424. #endif
1425. 		exercise(A_DEX, TRUE);
1426. 		tmp = 0;
1427. 		break;
1428. 	    case AD_TLPT:
1429. 		if (tmp <= 0) tmp = 1;
1430. 		if (!negated && tmp < mdef->mhp) {
1431. 		    char nambuf[BUFSZ];
1432. 		    boolean u_saw_mon = canseemon(mdef) ||
1433. 					(u.uswallow && u.ustuck == mdef);
1434. 		    /* record the name before losing sight of monster */
1435. 		    Strcpy(nambuf, Monnam(mdef));
1436. 		    if (u_teleport_mon(mdef, FALSE) &&
1437. 			    u_saw_mon && !canseemon(mdef))
1438. 			pline("%s suddenly disappears!", nambuf);
1439. 		}
1440. 		break;
1441. 	    case AD_BLND:
1442. 		if (can_blnd(&youmonst, mdef, mattk->aatyp, (struct obj*)0)) {
1443. 		    if(!Blind && mdef->mcansee)
1444. 			pline("%s is blinded.", Monnam(mdef));
1445. 		    mdef->mcansee = 0;
1446. 		    tmp += mdef->mblinded;
1447. 		    if (tmp > 127) tmp = 127;
1448. 		    mdef->mblinded = tmp;
1449. 		}
1450. 		tmp = 0;
1451. 		break;
1452. 	    case AD_CURS:
1453. 		if (night() && !rn2(10) && !mdef->mcan) {
1454. 		    if (mdef->data == &mons[PM_CLAY_GOLEM]) {
1455. 			if (!Blind)
1456. 			    pline("Some writing vanishes from %s head!",
1457. 				s_suffix(mon_nam(mdef)));
1458. 			xkilled(mdef, 0);
1459. 			/* Don't return yet; keep hp<1 and tmp=0 for pet msg */
1460. 		    } else {
1461. 			mdef->mcan = 1;
1462. 			You("chuckle.");
1463. 		    }
1464. 		}
1465. 		tmp = 0;
1466. 		break;
1467. 	    case AD_DRLI:
1468. 		if (!negated && !rn2(3) && !resists_drli(mdef)) {
1469. 			int xtmp = d(2,6);
1470. 			pline("%s suddenly seems weaker!", Monnam(mdef));
1471. 			mdef->mhpmax -= xtmp;
1472. 			if ((mdef->mhp -= xtmp) <= 0 || !mdef->m_lev) {
1473. 				pline("%s dies!", Monnam(mdef));
1474. 				xkilled(mdef,0);
1475. 			} else
1476. 				mdef->m_lev--;
1477. 			tmp = 0;
1478. 		}
1479. 		break;
1480. 	    case AD_RUST:
1481. 		if (pd == &mons[PM_IRON_GOLEM]) {
1482. 			pline("%s falls to pieces!", Monnam(mdef));
1483. 			xkilled(mdef,0);
1484. 		}
1485. 		hurtmarmor(mdef, AD_RUST);
1486. 		tmp = 0;
1487. 		break;
1488. 	    case AD_CORR:
1489. 		hurtmarmor(mdef, AD_CORR);
1490. 		tmp = 0;
1491. 		break;
1492. 	    case AD_DCAY:
1493. 		if (pd == &mons[PM_WOOD_GOLEM] ||
1494. 		    pd == &mons[PM_LEATHER_GOLEM]) {
1495. 			pline("%s falls to pieces!", Monnam(mdef));
1496. 			xkilled(mdef,0);
1497. 		}
1498. 		hurtmarmor(mdef, AD_DCAY);
1499. 		tmp = 0;
1500. 		break;
1501. 	    case AD_DRST:
1502. 	    case AD_DRDX:
1503. 	    case AD_DRCO:
1504. 		if (!negated && !rn2(8)) {
1505. 		    Your("%s was poisoned!", mpoisons_subj(&youmonst, mattk));
1506. 		    if (resists_poison(mdef))
1507. 			pline_The("poison doesn't seem to affect %s.",
1508. 				mon_nam(mdef));
1509. 		    else {
1510. 			if (!rn2(10)) {
1511. 			    Your("poison was deadly...");
1512. 			    tmp = mdef->mhp;
1513. 			} else tmp += rn1(10,6);
1514. 		    }
1515. 		}
1516. 		break;
1517. 	    case AD_DRIN:
1518. 		if (notonhead || !has_head(mdef->data)) {
1519. 		    pline("%s doesn't seem harmed.", Monnam(mdef));
1520. 		    tmp = 0;
1521. 		    if (!Unchanging && mdef->data == &mons[PM_GREEN_SLIME]) {
1522. 			if (!Slimed) {
1523. 			    You("suck in some slime and don't feel very well.");
1524. 			    Slimed = 10L;
1525. 			}
1526. 		    }
1527. 		    break;
1528. 		}
1529. 		if (m_slips_free(mdef, mattk)) break;
1530. 
1531. 		if ((mdef->misc_worn_check & W_ARMH) && rn2(8)) {
1532. 		    pline("%s helmet blocks your attack to %s head.",
1533. 			  s_suffix(Monnam(mdef)), mhis(mdef));
1534. 		    break;
1535. 		}
1536. 
1537. 		You("eat %s brain!", s_suffix(mon_nam(mdef)));
1538. 		u.uconduct.food++;
1539. 		if (touch_petrifies(mdef->data) && !Stone_resistance && !Stoned) {
1540. 		    Stoned = 5;
1541. 		    killer_format = KILLED_BY_AN;
1542. 		    delayed_killer = mdef->data->mname;
1543. 		}
1544. 		if (!vegan(mdef->data))
1545. 		    u.uconduct.unvegan++;
1546. 		if (!vegetarian(mdef->data))
1547. 		    violated_vegetarian();
1548. 		if (mindless(mdef->data)) {
1549. 		    pline("%s doesn't notice.", Monnam(mdef));
1550. 		    break;
1551. 		}
1552. 		tmp += rnd(10);
1553. 		morehungry(-rnd(30)); /* cannot choke */
1554. 		if (ABASE(A_INT) < AMAX(A_INT)) {
1555. 			ABASE(A_INT) += rnd(4);
1556. 			if (ABASE(A_INT) > AMAX(A_INT))
1557. 				ABASE(A_INT) = AMAX(A_INT);
1558. 			flags.botl = 1;
1559. 		}
1560. 		exercise(A_WIS, TRUE);
1561. 		break;
1562. 	    case AD_STCK:
1563. 		if (!negated && !sticks(mdef->data))
1564. 		    u.ustuck = mdef; /* it's now stuck to you */
1565. 		break;
1566. 	    case AD_WRAP:
1567. 		if (!sticks(mdef->data)) {
1568. 		    if (!u.ustuck && !rn2(10)) {
1569. 			if (m_slips_free(mdef, mattk)) {
1570. 			    tmp = 0;
1571. 			} else {
1572. 			    You("swing yourself around %s!",
1573. 				  mon_nam(mdef));
1574. 			    u.ustuck = mdef;
1575. 			}
1576. 		    } else if(u.ustuck == mdef) {
1577. 			/* Monsters don't wear amulets of magical breathing */
1578. 			if (is_pool(u.ux,u.uy) && !is_swimmer(mdef->data) &&
1579. 			    !amphibious(mdef->data)) {
1580. 			    You("drown %s...", mon_nam(mdef));
1581. 			    tmp = mdef->mhp;
1582. 			} else if(mattk->aatyp == AT_HUGS)
1583. 			    pline("%s is being crushed.", Monnam(mdef));
1584. 		    } else {
1585. 			tmp = 0;
1586. 			if (flags.verbose)
1587. 			    You("brush against %s %s.",
1588. 				s_suffix(mon_nam(mdef)),
1589. 				mbodypart(mdef, LEG));
1590. 		    }
1591. 		} else tmp = 0;
1592. 		break;
1593. 	    case AD_PLYS:
1594. 		if (!negated && mdef->mcanmove && !rn2(3) && tmp < mdef->mhp) {
1595. 		    if (!Blind) pline("%s is frozen by you!", Monnam(mdef));
1596. 		    mdef->mcanmove = 0;
1597. 		    mdef->mfrozen = rnd(10);
1598. 		}
1599. 		break;
1600. 	    case AD_SLEE:
1601. 		if (!negated && !mdef->msleeping &&
1602. 			    sleep_monst(mdef, rnd(10), -1)) {
1603. 		    if (!Blind)
1604. 			pline("%s is put to sleep by you!", Monnam(mdef));
1605. 		    slept_monst(mdef);
1606. 		}
1607. 		break;
1608. 	    case AD_SLIM:
1609. 		if (negated) break;	/* physical damage only */
1610. 		if (!rn2(4) && !flaming(mdef->data) &&
1611. 				mdef->data != &mons[PM_GREEN_SLIME]) {
1612. 		    You("turn %s into slime.", mon_nam(mdef));
1613. 		    (void) newcham(mdef, &mons[PM_GREEN_SLIME], FALSE, FALSE);
1614. 		    tmp = 0;
1615. 		}
1616. 		break;
1617. 	    case AD_ENCH:	/* KMH -- remove enchantment (disenchanter) */
1618. 		/* there's no msomearmor() function, so just do damage */
1619. 	     /* if (negated) break; */
1620. 		break;
1621. 	    case AD_SLOW:
1622. 		if (!negated && mdef->mspeed != MSLOW) {
1623. 		    unsigned int oldspeed = mdef->mspeed;
1624. 
1625. 		    mon_adjust_speed(mdef, -1, (struct obj *)0);
1626. 		    if (mdef->mspeed != oldspeed && canseemon(mdef))
1627. 			pline("%s slows down.", Monnam(mdef));
1628. 		}
1629. 		break;
1630. 	    case AD_CONF:
1631. 		if (!mdef->mconf) {
1632. 		    if (canseemon(mdef))
1633. 			pline("%s looks confused.", Monnam(mdef));
1634. 		    mdef->mconf = 1;
1635. 		}
1636. 		break;
1637. 	    default:	tmp = 0;
1638. 		break;
1639. 	}
1640. 
1641. 	mdef->mstrategy &= ~STRAT_WAITFORU; /* in case player is very fast */
1642. 	if((mdef->mhp -= tmp) < 1) {
1643. 	    if (mdef->mtame && !cansee(mdef->mx,mdef->my)) {
1644. 		You_feel("embarrassed for a moment.");
1645. 		if (tmp) xkilled(mdef, 0); /* !tmp but hp<1: already killed */
1646. 	    } else if (!flags.verbose) {
1647. 		You("destroy it!");
1648. 		if (tmp) xkilled(mdef, 0);
1649. 	    } else
1650. 		if (tmp) killed(mdef);
1651. 	    return(2);
1652. 	}
1653. 	return(1);
1654. }
1655. 

explum Edit

1656. STATIC_OVL int
1657. explum(mdef, mattk)
1658. register struct monst *mdef;
1659. register struct attack *mattk;
1660. {
1661. 	register int tmp = d((int)mattk->damn, (int)mattk->damd);
1662. 
1663. 	You("explode!");
1664. 	switch(mattk->adtyp) {
1665. 	    boolean resistance; /* only for cold/fire/elec */
1666. 
1667. 	    case AD_BLND:
1668. 		if (!resists_blnd(mdef)) {
1669. 		    pline("%s is blinded by your flash of light!", Monnam(mdef));
1670. 		    mdef->mblinded = min((int)mdef->mblinded + tmp, 127);
1671. 		    mdef->mcansee = 0;
1672. 		}
1673. 		break;
1674. 	    case AD_HALU:
1675. 		if (haseyes(mdef->data) && mdef->mcansee) {
1676. 		    pline("%s is affected by your flash of light!",
1677. 			  Monnam(mdef));
1678. 		    mdef->mconf = 1;
1679. 		}
1680. 		break;
1681. 	    case AD_COLD:
1682. 		resistance = resists_cold(mdef);
1683. 		goto common;
1684. 	    case AD_FIRE:
1685. 		resistance = resists_fire(mdef);
1686. 		goto common;
1687. 	    case AD_ELEC:
1688. 		resistance = resists_elec(mdef);
1689. common:
1690. 		if (!resistance) {
1691. 		    pline("%s gets blasted!", Monnam(mdef));
1692. 		    mdef->mhp -= tmp;
1693. 		    if (mdef->mhp <= 0) {
1694. 			 killed(mdef);
1695. 			 return(2);
1696. 		    }
1697. 		} else {
1698. 		    shieldeff(mdef->mx, mdef->my);
1699. 		    if (is_golem(mdef->data))
1700. 			golemeffects(mdef, (int)mattk->adtyp, tmp);
1701. 		    else
1702. 			pline_The("blast doesn't seem to affect %s.",
1703. 				mon_nam(mdef));
1704. 		}
1705. 		break;
1706. 	    default:
1707. 		break;
1708. 	}
1709. 	return(1);
1710. }
1711. 

start_engulf Edit

1712. STATIC_OVL void
1713. start_engulf(mdef)
1714. struct monst *mdef;
1715. {
1716. 	if (!Invisible) {
1717. 		map_location(u.ux, u.uy, TRUE);
1718. 		tmp_at(DISP_ALWAYS, mon_to_glyph(&youmonst));
1719. 		tmp_at(mdef->mx, mdef->my);
1720. 	}
1721. 	You("engulf %s!", mon_nam(mdef));
1722. 	delay_output();
1723. 	delay_output();
1724. }
1725. 

end_engulf Edit

1726. STATIC_OVL void
1727. end_engulf()
1728. {
1729. 	if (!Invisible) {
1730. 		tmp_at(DISP_END, 0);
1731. 		newsym(u.ux, u.uy);
1732. 	}
1733. }
1734. 

gulpum Edit

1735. STATIC_OVL int
1736. gulpum(mdef,mattk)
1737. register struct monst *mdef;
1738. register struct attack *mattk;
1739. {
1740. 	register int tmp;
1741. 	register int dam = d((int)mattk->damn, (int)mattk->damd);
1742. 	struct obj *otmp;
1743. 	/* Not totally the same as for real monsters.  Specifically, these
1744. 	 * don't take multiple moves.  (It's just too hard, for too little
1745. 	 * result, to program monsters which attack from inside you, which
1746. 	 * would be necessary if done accurately.)  Instead, we arbitrarily
1747. 	 * kill the monster immediately for AD_DGST and we regurgitate them
1748. 	 * after exactly 1 round of attack otherwise.  -KAA
1749. 	 */
1750. 
1751. 	if(mdef->data->msize >= MZ_HUGE) return 0;
1752. 
1753. 	if(u.uhunger < 1500 && !u.uswallow) {
1754. 	    for (otmp = mdef->minvent; otmp; otmp = otmp->nobj)
1755. 		(void) snuff_lit(otmp);
1756. 
1757. 	    if(!touch_petrifies(mdef->data) || Stone_resistance) {
1758. #ifdef LINT	/* static char msgbuf[BUFSZ]; */
1759. 		char msgbuf[BUFSZ];
1760. #else
1761. 		static char msgbuf[BUFSZ];
1762. #endif
1763. 		start_engulf(mdef);
1764. 		switch(mattk->adtyp) {
1765. 		    case AD_DGST:
1766. 			/* eating a Rider or its corpse is fatal */
1767. 			if (is_rider(mdef->data)) {
1768. 			 pline("Unfortunately, digesting any of it is fatal.");
1769. 			    end_engulf();
1770. 			    Sprintf(msgbuf, "unwisely tried to eat %s",
1771. 				    mdef->data->mname);
1772. 			    killer = msgbuf;
1773. 			    killer_format = NO_KILLER_PREFIX;
1774. 			    done(DIED);
1775. 			    return 0;		/* lifesaved */
1776. 			}
1777. 
1778. 			if (Slow_digestion) {
1779. 			    dam = 0;
1780. 			    break;
1781. 			}
1782. 
1783. 			/* KMH, conduct */
1784. 			u.uconduct.food++;
1785. 			if (!vegan(mdef->data))
1786. 			     u.uconduct.unvegan++;
1787. 			if (!vegetarian(mdef->data))
1788. 			     violated_vegetarian();
1789. 
1790. 			/* Use up amulet of life saving */
1791. 			if (!!(otmp = mlifesaver(mdef))) m_useup(mdef, otmp);
1792. 
1793. 			newuhs(FALSE);
1794. 			xkilled(mdef,2);
1795. 			if (mdef->mhp > 0) { /* monster lifesaved */
1796. 			    You("hurriedly regurgitate the sizzling in your %s.",
1797. 				body_part(STOMACH));
1798. 			} else {
1799. 			    tmp = 1 + (mdef->data->cwt >> 8);
1800. 			    if (corpse_chance(mdef, &youmonst, TRUE) &&
1801. 				!(mvitals[monsndx(mdef->data)].mvflags &
1802. 				  G_NOCORPSE)) {
1803. 				/* nutrition only if there can be a corpse */
1804. 				u.uhunger += (mdef->data->cnutrit+1) / 2;
1805. 			    } else tmp = 0;
1806. 			    Sprintf(msgbuf, "You totally digest %s.",
1807. 					    mon_nam(mdef));
1808. 			    if (tmp != 0) {
1809. 				/* setting afternmv = end_engulf is tempting,
1810. 				 * but will cause problems if the player is
1811. 				 * attacked (which uses his real location) or
1812. 				 * if his See_invisible wears off
1813. 				 */
1814. 				You("digest %s.", mon_nam(mdef));
1815. 				if (Slow_digestion) tmp *= 2;
1816. 				nomul(-tmp);
1817. 				nomovemsg = msgbuf;
1818. 			    } else pline("%s", msgbuf);
1819. 			    if (mdef->data == &mons[PM_GREEN_SLIME]) {
1820. 				Sprintf(msgbuf, "%s isn't sitting well with you.",
1821. 					The(mdef->data->mname));
1822. 				if (!Unchanging) {
1823. 					Slimed = 5L;
1824. 					flags.botl = 1;
1825. 				}
1826. 			    } else
1827. 			    exercise(A_CON, TRUE);
1828. 			}
1829. 			end_engulf();
1830. 			return(2);
1831. 		    case AD_PHYS:
1832. 			if (youmonst.data == &mons[PM_FOG_CLOUD]) {
1833. 			    pline("%s is laden with your moisture.",
1834. 				  Monnam(mdef));
1835. 			    if (amphibious(mdef->data) &&
1836. 				!flaming(mdef->data)) {
1837. 				dam = 0;
1838. 				pline("%s seems unharmed.", Monnam(mdef));
1839. 			    }
1840. 			} else
1841. 			    pline("%s is pummeled with your debris!",
1842. 				  Monnam(mdef));
1843. 			break;
1844. 		    case AD_ACID:
1845. 			pline("%s is covered with your goo!", Monnam(mdef));
1846. 			if (resists_acid(mdef)) {
1847. 			    pline("It seems harmless to %s.", mon_nam(mdef));
1848. 			    dam = 0;
1849. 			}
1850. 			break;
1851. 		    case AD_BLND:
1852. 			if (can_blnd(&youmonst, mdef, mattk->aatyp, (struct obj *)0)) {
1853. 			    if (mdef->mcansee)
1854. 				pline("%s can't see in there!", Monnam(mdef));
1855. 			    mdef->mcansee = 0;
1856. 			    dam += mdef->mblinded;
1857. 			    if (dam > 127) dam = 127;
1858. 			    mdef->mblinded = dam;
1859. 			}
1860. 			dam = 0;
1861. 			break;
1862. 		    case AD_ELEC:
1863. 			if (rn2(2)) {
1864. 			    pline_The("air around %s crackles with electricity.", mon_nam(mdef));
1865. 			    if (resists_elec(mdef)) {
1866. 				pline("%s seems unhurt.", Monnam(mdef));
1867. 				dam = 0;
1868. 			    }
1869. 			    golemeffects(mdef,(int)mattk->adtyp,dam);
1870. 			} else dam = 0;
1871. 			break;
1872. 		    case AD_COLD:
1873. 			if (rn2(2)) {
1874. 			    if (resists_cold(mdef)) {
1875. 				pline("%s seems mildly chilly.", Monnam(mdef));
1876. 				dam = 0;
1877. 			    } else
1878. 				pline("%s is freezing to death!",Monnam(mdef));
1879. 			    golemeffects(mdef,(int)mattk->adtyp,dam);
1880. 			} else dam = 0;
1881. 			break;
1882. 		    case AD_FIRE:
1883. 			if (rn2(2)) {
1884. 			    if (resists_fire(mdef)) {
1885. 				pline("%s seems mildly hot.", Monnam(mdef));
1886. 				dam = 0;
1887. 			    } else
1888. 				pline("%s is burning to a crisp!",Monnam(mdef));
1889. 			    golemeffects(mdef,(int)mattk->adtyp,dam);
1890. 			} else dam = 0;
1891. 			break;
1892. 		}
1893. 		end_engulf();
1894. 		if ((mdef->mhp -= dam) <= 0) {
1895. 		    killed(mdef);
1896. 		    if (mdef->mhp <= 0)	/* not lifesaved */
1897. 			return(2);
1898. 		}
1899. 		You("%s %s!", is_animal(youmonst.data) ? "regurgitate"
1900. 			: "expel", mon_nam(mdef));
1901. 		if (Slow_digestion || is_animal(youmonst.data)) {
1902. 		    pline("Obviously, you didn't like %s taste.",
1903. 			  s_suffix(mon_nam(mdef)));
1904. 		}
1905. 	    } else {
1906. 		char kbuf[BUFSZ];
1907. 
1908. 		You("bite into %s.", mon_nam(mdef));
1909. 		Sprintf(kbuf, "swallowing %s whole", an(mdef->data->mname));
1910. 		instapetrify(kbuf);
1911. 	    }
1912. 	}
1913. 	return(0);
1914. }
1915. 

missum Edit

1916. void
1917. missum(mdef,mattk)
1918. register struct monst *mdef;
1919. register struct attack *mattk;
1920. {
1921. 	if (could_seduce(&youmonst, mdef, mattk))
1922. 		You("pretend to be friendly to %s.", mon_nam(mdef));
1923. 	else if(canspotmon(mdef) && flags.verbose)
1924. 		You("miss %s.", mon_nam(mdef));
1925. 	else
1926. 		You("miss it.");
1927. 	if (!mdef->msleeping && mdef->mcanmove)
1928. 		wakeup(mdef);
1929. }
1930. 

hmonas Edit

1931. STATIC_OVL boolean
1932. hmonas(mon, tmp)		/* attack monster as a monster. */
1933. register struct monst *mon;
1934. register int tmp;
1935. {
1936. 	struct attack *mattk, alt_attk;
1937. 	int	i, sum[NATTK], hittmp = 0;
1938. 	int	nsum = 0;
1939. 	int	dhit = 0;
1940. 
1941. 	for(i = 0; i < NATTK; i++) {
1942. 
1943. 	    sum[i] = 0;
1944. 	    mattk = getmattk(youmonst.data, i, sum, &alt_attk);
1945. 	    switch(mattk->aatyp) {
1946. 		case AT_WEAP:
1947. use_weapon:
1948. 	/* Certain monsters don't use weapons when encountered as enemies,
1949. 	 * but players who polymorph into them have hands or claws and thus
1950. 	 * should be able to use weapons.  This shouldn't prohibit the use
1951. 	 * of most special abilities, either.
1952. 	 */
1953. 	/* Potential problem: if the monster gets multiple weapon attacks,
1954. 	 * we currently allow the player to get each of these as a weapon
1955. 	 * attack.  Is this really desirable?
1956. 	 */
1957. 			if (uwep) {
1958. 			    hittmp = hitval(uwep, mon);
1959. 			    hittmp += weapon_hit_bonus(uwep);
1960. 			    tmp += hittmp;
1961. 			}
1962. 			dhit = (tmp > (dieroll = rnd(20)) || u.uswallow);
1963. 			/* KMH -- Don't accumulate to-hit bonuses */
1964. 			if (uwep) tmp -= hittmp;
1965. 			/* Enemy dead, before any special abilities used */
1966. 			if (!known_hitum(mon,&dhit,mattk)) {
1967. 			    sum[i] = 2;
1968. 			    break;
1969. 			} else sum[i] = dhit;
1970. 			/* might be a worm that gets cut in half */
1971. 			if (m_at(u.ux+u.dx, u.uy+u.dy) != mon) return((boolean)(nsum != 0));
1972. 			/* Do not print "You hit" message, since known_hitum
1973. 			 * already did it.
1974. 			 */
1975. 			if (dhit && mattk->adtyp != AD_SPEL
1976. 				&& mattk->adtyp != AD_PHYS)
1977. 				sum[i] = damageum(mon,mattk);
1978. 			break;
1979. 		case AT_CLAW:
1980. 			if (i==0 && uwep && !cantwield(youmonst.data)) goto use_weapon;
1981. #ifdef SEDUCE
1982. 			/* succubi/incubi are humanoid, but their _second_
1983. 			 * attack is AT_CLAW, not their first...
1984. 			 */
1985. 			if (i==1 && uwep && (u.umonnum == PM_SUCCUBUS ||
1986. 				u.umonnum == PM_INCUBUS)) goto use_weapon;
1987. #endif
1988. 		case AT_KICK:
1989. 		case AT_BITE:
1990. 		case AT_STNG:
1991. 		case AT_TUCH:
1992. 		case AT_BUTT:
1993. 		case AT_TENT:
1994. 			if (i==0 && uwep && (youmonst.data->mlet==S_LICH)) goto use_weapon;
1995. 			if ((dhit = (tmp > rnd(20) || u.uswallow)) != 0) {
1996. 			    int compat;
1997. 
1998. 			    if (!u.uswallow &&
1999. 				(compat=could_seduce(&youmonst, mon, mattk))) {
2000. 				You("%s %s %s.",
2001. 				    mon->mcansee && haseyes(mon->data)
2002. 				    ? "smile at" : "talk to",
2003. 				    mon_nam(mon),
2004. 				    compat == 2 ? "engagingly":"seductively");
2005. 				/* doesn't anger it; no wakeup() */
2006. 				sum[i] = damageum(mon, mattk);
2007. 				break;
2008. 			    }
2009. 			    wakeup(mon);
2010. 			    /* maybe this check should be in damageum()? */
2011. 			    if (mon->data == &mons[PM_SHADE] &&
2012. 					!(mattk->aatyp == AT_KICK &&
2013. 					    uarmf && uarmf->blessed)) {
2014. 				Your("attack passes harmlessly through %s.",
2015. 				    mon_nam(mon));
2016. 				break;
2017. 			    }
2018. 			    if (mattk->aatyp == AT_KICK)
2019. 				    You("kick %s.", mon_nam(mon));
2020. 			    else if (mattk->aatyp == AT_BITE)
2021. 				    You("bite %s.", mon_nam(mon));
2022. 			    else if (mattk->aatyp == AT_STNG)
2023. 				    You("sting %s.", mon_nam(mon));
2024. 			    else if (mattk->aatyp == AT_BUTT)
2025. 				    You("butt %s.", mon_nam(mon));
2026. 			    else if (mattk->aatyp == AT_TUCH)
2027. 				    You("touch %s.", mon_nam(mon));
2028. 			    else if (mattk->aatyp == AT_TENT)
2029. 				    Your("tentacles suck %s.", mon_nam(mon));
2030. 			    else You("hit %s.", mon_nam(mon));
2031. 			    sum[i] = damageum(mon, mattk);
2032. 			} else
2033. 			    missum(mon, mattk);
2034. 			break;
2035. 
2036. 		case AT_HUGS:
2037. 			/* automatic if prev two attacks succeed, or if
2038. 			 * already grabbed in a previous attack
2039. 			 */
2040. 			dhit = 1;
2041. 			wakeup(mon);
2042. 			if (mon->data == &mons[PM_SHADE])
2043. 			    Your("hug passes harmlessly through %s.",
2044. 				mon_nam(mon));
2045. 			else if (!sticks(mon->data) && !u.uswallow) {
2046. 			    if (mon==u.ustuck) {
2047. 				pline("%s is being %s.", Monnam(mon),
2048. 				    u.umonnum==PM_ROPE_GOLEM ? "choked":
2049. 				    "crushed");
2050. 				sum[i] = damageum(mon, mattk);
2051. 			    } else if(i >= 2 && sum[i-1] && sum[i-2]) {
2052. 				You("grab %s!", mon_nam(mon));
2053. 				u.ustuck = mon;
2054. 				sum[i] = damageum(mon, mattk);
2055. 			    }
2056. 			}
2057. 			break;
2058. 
2059. 		case AT_EXPL:	/* automatic hit if next to */
2060. 			dhit = -1;
2061. 			wakeup(mon);
2062. 			sum[i] = explum(mon, mattk);
2063. 			break;
2064. 
2065. 		case AT_ENGL:
2066. 			if((dhit = (tmp > rnd(20+i)))) {
2067. 				wakeup(mon);
2068. 				if (mon->data == &mons[PM_SHADE])
2069. 				    Your("attempt to surround %s is harmless.",
2070. 					mon_nam(mon));
2071. 				else {
2072. 				    sum[i]= gulpum(mon,mattk);
2073. 				    if (sum[i] == 2 &&
2074. 					    (mon->data->mlet == S_ZOMBIE ||
2075. 						mon->data->mlet == S_MUMMY) &&
2076. 					    rn2(5) &&
2077. 					    !Sick_resistance) {
2078. 					You_feel("%ssick.",
2079. 					    (Sick) ? "very " : "");
2080. 					mdamageu(mon, rnd(8));
2081. 				    }
2082. 				}
2083. 			} else
2084. 				missum(mon, mattk);
2085. 			break;
2086. 
2087. 		case AT_MAGC:
2088. 			/* No check for uwep; if wielding nothing we want to
2089. 			 * do the normal 1-2 points bare hand damage...
2090. 			 */
2091. 			if (i==0 && (youmonst.data->mlet==S_KOBOLD
2092. 				|| youmonst.data->mlet==S_ORC
2093. 				|| youmonst.data->mlet==S_GNOME
2094. 				)) goto use_weapon;
2095. 
2096. 		case AT_NONE:
2097. 		case AT_BOOM:
2098. 			continue;
2099. 			/* Not break--avoid passive attacks from enemy */
2100. 
2101. 		case AT_BREA:
2102. 		case AT_SPIT:
2103. 		case AT_GAZE:	/* all done using #monster command */
2104. 			dhit = 0;
2105. 			break;
2106. 
2107. 		default: /* Strange... */
2108. 			impossible("strange attack of yours (%d)",
2109. 				 mattk->aatyp);
2110. 	    }
2111. 	    if (dhit == -1) {
2112. 		u.mh = -1;	/* dead in the current form */
2113. 		rehumanize();
2114. 	    }
2115. 	    if (sum[i] == 2)
2116. 		return((boolean)passive(mon, 1, 0, mattk->aatyp));
2117. 							/* defender dead */
2118. 	    else {
2119. 		(void) passive(mon, sum[i], 1, mattk->aatyp);
2120. 		nsum |= sum[i];
2121. 	    }
2122. 	    if (!Upolyd)
2123. 		break; /* No extra attacks if no longer a monster */
2124. 	    if (multi < 0)
2125. 		break; /* If paralyzed while attacking, i.e. floating eye */
2126. 	}
2127. 	return((boolean)(nsum != 0));
2128. }
2129. 

passive Edit

2130. /*	Special (passive) attacks on you by monsters done here.		*/
2131. 
2132. int
2133. passive(mon, mhit, malive, aatyp)
2134. register struct monst *mon;
2135. register boolean mhit;
2136. register int malive;
2137. uchar aatyp;
2138. {
2139. 	register struct permonst *ptr = mon->data;
2140. 	register int i, tmp;
2141. 
2142. 	for(i = 0; ; i++) {
2143. 	    if(i >= NATTK) return(malive | mhit);	/* no passive attacks */
2144. 	    if(ptr->mattk[i].aatyp == AT_NONE) break;	/* try this one */
2145. 	}
2146. 	/* Note: tmp not always used */
2147. 	if (ptr->mattk[i].damn)
2148. 	    tmp = d((int)ptr->mattk[i].damn, (int)ptr->mattk[i].damd);
2149. 	else if(ptr->mattk[i].damd)
2150. 	    tmp = d((int)mon->m_lev+1, (int)ptr->mattk[i].damd);
2151. 	else
2152. 	    tmp = 0;
2153. 
2154. /*	These affect you even if they just died */
2155. 
2156. 	switch(ptr->mattk[i].adtyp) {
2157. 
2158. 	  case AD_ACID:
2159. 	    if(mhit && rn2(2)) {
2160. 		if (Blind || !flags.verbose) You("are splashed!");
2161. 		else	You("are splashed by %s acid!",
2162. 			                s_suffix(mon_nam(mon)));
2163. 
2164. 		if (!Acid_resistance)
2165. 			mdamageu(mon, tmp);
2166. 		if(!rn2(30)) erode_armor(&youmonst, TRUE);
2167. 	    }
2168. 	    if (mhit) {
2169. 		if (aatyp == AT_KICK) {
2170. 		    if (uarmf && !rn2(6))
2171. 			(void)rust_dmg(uarmf, xname(uarmf), 3, TRUE, &youmonst);
2172. 		} else if (aatyp == AT_WEAP || aatyp == AT_CLAW ||
2173. 			   aatyp == AT_MAGC || aatyp == AT_TUCH)
2174. 		    passive_obj(mon, (struct obj*)0, &(ptr->mattk[i]));
2175. 	    }
2176. 	    exercise(A_STR, FALSE);
2177. 	    break;
2178. 	  case AD_STON:
2179. 	    if (mhit) {		/* successful attack */
2180. 		long protector = attk_protection((int)aatyp);
2181. 
2182. 		/* hero using monsters' AT_MAGC attack is hitting hand to
2183. 		   hand rather than casting a spell */
2184. 		if (aatyp == AT_MAGC) protector = W_ARMG;
2185. 
2186. 		if (protector == 0L ||		/* no protection */
2187. 			(protector == W_ARMG && !uarmg && !uwep) ||
2188. 			(protector == W_ARMF && !uarmf) ||
2189. 			(protector == W_ARMH && !uarmh) ||
2190. 			(protector == (W_ARMC|W_ARMG) && (!uarmc || !uarmg))) {
2191. 		    if (!Stone_resistance &&
2192. 			    !(poly_when_stoned(youmonst.data) &&
2193. 				polymon(PM_STONE_GOLEM))) {
2194. 			You("turn to stone...");
2195. 			done_in_by(mon);
2196. 			return 2;
2197. 		    }
2198. 		}
2199. 	    }
2200. 	    break;
2201. 	  case AD_RUST:
2202. 	    if(mhit && !mon->mcan) {
2203. 		if (aatyp == AT_KICK) {
2204. 		    if (uarmf)
2205. 			(void)rust_dmg(uarmf, xname(uarmf), 1, TRUE, &youmonst);
2206. 		} else if (aatyp == AT_WEAP || aatyp == AT_CLAW ||
2207. 			   aatyp == AT_MAGC || aatyp == AT_TUCH)
2208. 		    passive_obj(mon, (struct obj*)0, &(ptr->mattk[i]));
2209. 	    }
2210. 	    break;
2211. 	  case AD_CORR:
2212. 	    if(mhit && !mon->mcan) {
2213. 		if (aatyp == AT_KICK) {
2214. 		    if (uarmf)
2215. 			(void)rust_dmg(uarmf, xname(uarmf), 3, TRUE, &youmonst);
2216. 		} else if (aatyp == AT_WEAP || aatyp == AT_CLAW ||
2217. 			   aatyp == AT_MAGC || aatyp == AT_TUCH)
2218. 		    passive_obj(mon, (struct obj*)0, &(ptr->mattk[i]));
2219. 	    }
2220. 	    break;
2221. 	  case AD_MAGM:
2222. 	    /* wrath of gods for attacking Oracle */
2223. 	    if(Antimagic) {
2224. 		shieldeff(u.ux, u.uy);
2225. 		pline("A hail of magic missiles narrowly misses you!");
2226. 	    } else {
2227. 		You("are hit by magic missiles appearing from thin air!");
2228. 		mdamageu(mon, tmp);
2229. 	    }
2230. 	    break;
2231. 	  case AD_ENCH:	/* KMH -- remove enchantment (disenchanter) */
2232. 	    if (mhit) {
2233. 		struct obj *obj = (struct obj *)0;
2234. 
2235. 		if (aatyp == AT_KICK) {
2236. 		    obj = uarmf;
2237. 		    if (!obj) break;
2238. 		} else if (aatyp == AT_BITE || aatyp == AT_BUTT ||
2239. 			   (aatyp >= AT_STNG && aatyp < AT_WEAP)) {
2240. 		    break;		/* no object involved */
2241. 		}
2242. 		passive_obj(mon, obj, &(ptr->mattk[i]));
2243. 	    }
2244. 	    break;
2245. 	  default:
2246. 	    break;
2247. 	}
2248. 
2249. /*	These only affect you if they still live */
2250. 
2251. 	if(malive && !mon->mcan && rn2(3)) {
2252. 
2253. 	    switch(ptr->mattk[i].adtyp) {
2254. 
2255. 	      case AD_PLYS:
2256. 		if(ptr == &mons[PM_FLOATING_EYE]) {
2257. 		    if (!canseemon(mon)) {
2258. 			break;
2259. 		    }
2260. 		    if(mon->mcansee) {
2261. 			if (ureflects("%s gaze is reflected by your %s.",
2262. 				    s_suffix(Monnam(mon))))
2263. 			    ;
2264. 			else if (Free_action)
2265. 			    You("momentarily stiffen under %s gaze!",
2266. 				    s_suffix(mon_nam(mon)));
2267. 			else {
2268. 			    You("are frozen by %s gaze!",
2269. 				  s_suffix(mon_nam(mon)));
2270. 			    nomul((ACURR(A_WIS) > 12 || rn2(4)) ? -tmp : -127);
2271. 			}
2272. 		    } else {
2273. 			pline("%s cannot defend itself.",
2274. 				Adjmonnam(mon,"blind"));
2275. 			if(!rn2(500)) change_luck(-1);
2276. 		    }
2277. 		} else if (Free_action) {
2278. 		    You("momentarily stiffen.");
2279. 		} else { /* gelatinous cube */
2280. 		    You("are frozen by %s!", mon_nam(mon));
2281. 	    	    nomovemsg = 0;	/* default: "you can move again" */
2282. 		    nomul(-tmp);
2283. 		    exercise(A_DEX, FALSE);
2284. 		}
2285. 		break;
2286. 	      case AD_COLD:		/* brown mold or blue jelly */
2287. 		if(monnear(mon, u.ux, u.uy)) {
2288. 		    if(Cold_resistance) {
2289. 			shieldeff(u.ux, u.uy);
2290. 			You_feel("a mild chill.");
2291. 			ugolemeffects(AD_COLD, tmp);
2292. 			break;
2293. 		    }
2294. 		    You("are suddenly very cold!");
2295. 		    mdamageu(mon, tmp);
2296. 		/* monster gets stronger with your heat! */
2297. 		    mon->mhp += tmp / 2;
2298. 		    if (mon->mhpmax < mon->mhp) mon->mhpmax = mon->mhp;
2299. 		/* at a certain point, the monster will reproduce! */
2300. 		    if(mon->mhpmax > ((int) (mon->m_lev+1) * 8))
2301. 			(void)split_mon(mon, &youmonst);
2302. 		}
2303. 		break;
2304. 	      case AD_STUN:		/* specifically yellow mold */
2305. 		if(!Stunned)
2306. 		    make_stunned((long)tmp, TRUE);
2307. 		break;
2308. 	      case AD_FIRE:
2309. 		if(monnear(mon, u.ux, u.uy)) {
2310. 		    if(Fire_resistance) {
2311. 			shieldeff(u.ux, u.uy);
2312. 			You_feel("mildly warm.");
2313. 			ugolemeffects(AD_FIRE, tmp);
2314. 			break;
2315. 		    }
2316. 		    You("are suddenly very hot!");
2317. 		    mdamageu(mon, tmp);
2318. 		}
2319. 		break;
2320. 	      case AD_ELEC:
2321. 		if(Shock_resistance) {
2322. 		    shieldeff(u.ux, u.uy);
2323. 		    You_feel("a mild tingle.");
2324. 		    ugolemeffects(AD_ELEC, tmp);
2325. 		    break;
2326. 		}
2327. 		You("are jolted with electricity!");
2328. 		mdamageu(mon, tmp);
2329. 		break;
2330. 	      default:
2331. 		break;
2332. 	    }
2333. 	}
2334. 	return(malive | mhit);
2335. }
2336. 

passive_obj Edit

2337. /*
2338.  * Special (passive) attacks on an attacking object by monsters done here.
2339.  * Assumes the attack was successful.
2340.  */
2341. void
2342. passive_obj(mon, obj, mattk)
2343. register struct monst *mon;
2344. register struct obj *obj;	/* null means pick uwep, uswapwep or uarmg */
2345. struct attack *mattk;		/* null means we find one internally */
2346. {
2347. 	register struct permonst *ptr = mon->data;
2348. 	register int i;
2349. 
2350. 	/* if caller hasn't specified an object, use uwep, uswapwep or uarmg */
2351. 	if (!obj) {
2352. 	    obj = (u.twoweap && uswapwep && !rn2(2)) ? uswapwep : uwep;
2353. 	    if (!obj && mattk->adtyp == AD_ENCH)
2354. 		obj = uarmg;		/* no weapon? then must be gloves */
2355. 	    if (!obj) return;		/* no object to affect */
2356. 	}
2357. 
2358. 	/* if caller hasn't specified an attack, find one */
2359. 	if (!mattk) {
2360. 	    for(i = 0; ; i++) {
2361. 		if(i >= NATTK) return;	/* no passive attacks */
2362. 		if(ptr->mattk[i].aatyp == AT_NONE) break; /* try this one */
2363. 	    }
2364. 	    mattk = &(ptr->mattk[i]);
2365. 	}
2366. 
2367. 	switch(mattk->adtyp) {
2368. 
2369. 	case AD_ACID:
2370. 	    if(!rn2(6)) {
2371. 		erode_obj(obj, TRUE, FALSE);
2372. 	    }
2373. 	    break;
2374. 	case AD_RUST:
2375. 	    if(!mon->mcan) {
2376. 		erode_obj(obj, FALSE, FALSE);
2377. 	    }
2378. 	    break;
2379. 	case AD_CORR:
2380. 	    if(!mon->mcan) {
2381. 		erode_obj(obj, TRUE, FALSE);
2382. 	    }
2383. 	    break;
2384. 	case AD_ENCH:
2385. 	    if (!mon->mcan) {
2386. 		if (drain_item(obj) && carried(obj) &&
2387. 		    (obj->known || obj->oclass == ARMOR_CLASS)) {
2388. 		    Your("%s less effective.", aobjnam(obj, "seem"));
2389. 	    	}
2390. 	    	break;
2391. 	    }
2392. 	  default:
2393. 	    break;
2394. 	}
2395. 
2396. 	if (carried(obj)) update_inventory();
2397. }
2398. 

stumble_onto_mimic Edit

2399. /* Note: caller must ascertain mtmp is mimicking... */
2400. void
2401. stumble_onto_mimic(mtmp)
2402. struct monst *mtmp;
2403. {
2404. 	const char *fmt = "Wait!  That's %s!",
2405. 		   *generic = "a monster",
2406. 		   *what = 0;
2407. 
2408. 	if(!u.ustuck && !mtmp->mflee && dmgtype(mtmp->data,AD_STCK))
2409. 	    u.ustuck = mtmp;
2410. 
2411. 	if (Blind) {
2412. 	    if (!Blind_telepat)
2413. 		what = generic;		/* with default fmt */
2414. 	    else if (mtmp->m_ap_type == M_AP_MONSTER)
2415. 		what = a_monnam(mtmp);	/* differs from what was sensed */
2416. 	} else {
2417. 	    int glyph = levl[u.ux+u.dx][u.uy+u.dy].glyph;
2418. 
2419. 	    if (glyph_is_cmap(glyph) &&
2420. 		    (glyph_to_cmap(glyph) == S_hcdoor ||
2421. 		     glyph_to_cmap(glyph) == S_vcdoor))
2422. 		fmt = "The door actually was %s!";
2423. 	    else if (glyph_is_object(glyph) &&
2424. 		    glyph_to_obj(glyph) == GOLD_PIECE)
2425. 		fmt = "That gold was %s!";
2426. 
2427. 	    /* cloned Wiz starts out mimicking some other monster and
2428. 	       might make himself invisible before being revealed */
2429. 	    if (mtmp->minvis && !See_invisible)
2430. 		what = generic;
2431. 	    else
2432. 		what = a_monnam(mtmp);
2433. 	}
2434. 	if (what) pline(fmt, what);
2435. 
2436. 	wakeup(mtmp);	/* clears mimicking */
2437. }
2438. 

nohandglow Edit

2439. STATIC_OVL void
2440. nohandglow(mon)
2441. struct monst *mon;
2442. {
2443. 	char *hands=makeplural(body_part(HAND));
2444. 
2445. 	if (!u.umconf || mon->mconf) return;
2446. 	if (u.umconf == 1) {
2447. 		if (Blind)
2448. 			Your("%s stop tingling.", hands);
2449. 		else
2450. 			Your("%s stop glowing %s.", hands, hcolor(NH_RED));
2451. 	} else {
2452. 		if (Blind)
2453. 			pline_The("tingling in your %s lessens.", hands);
2454. 		else
2455. 			Your("%s no longer glow so brightly %s.", hands,
2456. 				hcolor(NH_RED));
2457. 	}
2458. 	u.umconf--;
2459. }
2460. 

flash_hits_mon Edit

2461. int
2462. flash_hits_mon(mtmp, otmp)
2463. struct monst *mtmp;
2464. struct obj *otmp;	/* source of flash */
2465. {
2466. 	int tmp, amt, res = 0, useeit = canseemon(mtmp);
2467. 
2468. 	if (mtmp->msleeping) {
2469. 	    mtmp->msleeping = 0;
2470. 	    if (useeit) {
2471. 		pline_The("flash awakens %s.", mon_nam(mtmp));
2472. 		res = 1;
2473. 	    }
2474. 	} else if (mtmp->data->mlet != S_LIGHT) {
2475. 	    if (!resists_blnd(mtmp)) {
2476. 		tmp = dist2(otmp->ox, otmp->oy, mtmp->mx, mtmp->my);
2477. 		if (useeit) {
2478. 		    pline("%s is blinded by the flash!", Monnam(mtmp));
2479. 		    res = 1;
2480. 		}
2481. 		if (mtmp->data == &mons[PM_GREMLIN]) {
2482. 		    /* Rule #1: Keep them out of the light. */
2483. 		    amt = otmp->otyp == WAN_LIGHT ? d(1 + otmp->spe, 4) :
2484. 		          rn2(min(mtmp->mhp,4));
2485. 		    pline("%s %s!", Monnam(mtmp), amt > mtmp->mhp / 2 ?
2486. 			  "wails in agony" : "cries out in pain");
2487. 		    if ((mtmp->mhp -= amt) <= 0) {
2488. 			if (flags.mon_moving)
2489. 			    monkilled(mtmp, (char *)0, AD_BLND);
2490. 			else
2491. 			    killed(mtmp);
2492. 		    } else if (cansee(mtmp->mx,mtmp->my) && !canspotmon(mtmp)){
2493. 			map_invisible(mtmp->mx, mtmp->my);
2494. 		    }
2495. 		}
2496. 		if (mtmp->mhp > 0) {
2497. 		    if (!flags.mon_moving) setmangry(mtmp);
2498. 		    if (tmp < 9 && !mtmp->isshk && rn2(4)) {
2499. 			if (rn2(4))
2500. 			    monflee(mtmp, rnd(100), FALSE, TRUE);
2501. 			else
2502. 			    monflee(mtmp, 0, FALSE, TRUE);
2503. 		    }
2504. 		    mtmp->mcansee = 0;
2505. 		    mtmp->mblinded = (tmp < 3) ? 0 : rnd(1 + 50/tmp);
2506. 		}
2507. 	    }
2508. 	}
2509. 	return res;
2510. }
2511. 
2512. /*uhitm.c*/

Around Wikia's network

Random Wiki