Blindfold removal fix
[slashemextended.git] / src / mthrowu.c
blobb20f911e73e12b4a7089ecdc5e56ada6d2e6af05
1 /* SCCS Id: @(#)mthrowu.c 3.4 2003/05/09 */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* NetHack may be freely redistributed. See license for details. */
5 #include "hack.h"
7 STATIC_DCL int drop_throw(struct monst *, struct obj *,BOOLEAN_P,int,int);
9 #define URETREATING(x,y) (distmin(u.ux,u.uy,x,y) > distmin(u.ux0,u.uy0,x,y))
11 #define POLE_LIM 8 /* How far monsters can use pole-weapons */
13 #ifndef OVLB
15 const char *breathwep[];
17 #else /* OVLB */
20 * Keep consistent with breath weapons in zap.c, and AD_* in monattk.h.
22 NEARDATA const char *breathwep[] = {
23 "fragments",
24 "fire",
25 "frost",
26 "sleep gas",
27 "a disintegration blast",
28 "lightning",
29 "poison gas",
30 "acid",
31 "light",
32 "a psionic blast"
35 NEARDATA const char *hallubreathwep[] = {"fragments", "fire", "frost", "sleep gas", "a disintegration blast", "lightning", "poison gas", "acid", "light", "strange breath #9", "sizzle", "nexus", "slaying", "vomit", "nausea", "repetition", "nether", "chaos", "confusion", "smoke", "--More-- You have died. DYWYPI?", "darkness", "sound", "gravity", "vibration", "penetration", "spitballs", "fart gas", "stinking gas", "slow gas", "rainbows", "air", "balloons", "nitrogen", "chloroform", "prussic acid", "ozone", "spill", "litter", "garbage", "trash", "heat", "cold", "ice", "water", "earth", "hell", "sky", "astral", "stars", "asterisks", "exclamation marks!!!", "feathers", "springs", "fog", "dew", "snow", "drugs", "rock'n'roll", "smog", "sludge", "waste", "temperature", "humidity", "vortices", "clouds", "a psionic blast", "cotton candy", "butterflies", "asteroids", "beads", "bubbles", "champagne", "coins", "crumbs", "dark matter", "dust specks", "emoticons", "emotions", "entropy", "corona viri", "flowers", "foam", "gamma rays", "gelatin", "gemstones", "ghosts", "glass shards", "glitter", "good vibes", "gravel", "gravy", "grawlixes", "holy light", "hornets", "hot air", "hyphens", "hypnosis", "infrared", "insects", "laser beams", "leaves", "lightening", "logic gates", "magma", "marbles", "mathematics", "megabytes", "metal shavings", "metapatterns", "meteors", "mist", "mud", "music", "nanites", "needles", "noise", "nostalgia", "oil", "paint", "photons", "pixels", "plasma", "polarity", "powder", "powerups", "prismatic light", "pure logic", "purple", "radio waves", "rock music", "rocket fuel", "rope", "sadness", "salt", "sand", "scrolls", "smileys", "snowflakes", "sparkles", "specularity", "spores", "steam", "tetrahedrons", "text", "the past", "tornadoes", "toxic waste", "ultraviolet light", "viruses", "waveforms", "wind", "X-rays", "zorkmids", "shoes", "high heels", "hail", "etherwind", "game over", "taunts", "wouwou taunts", "conversion sermon", "perfume", "gramar cheker", "venom", "anti-teleportation fields", "perish songs", "a kick in the nuts", "cuddle", "cloth", "wheels", "dictators", "nasty traps", "crosses", "NHK-fire", "BFG ammo", "green flames", "carbon monoxide", "icicles", "error messages", "segfaults", "queefing gas", "menstruational liquid", "some icky bodily fluid", "pus", "necrosis",
40 /* hero is hit by something other than a monster */
41 int
42 thitu(tlev, dam, obj, name)
43 int tlev, dam;
44 struct obj *obj;
45 const char *name; /* if null, then format `obj' */
47 const char *onm, *knm;
48 boolean is_acid;
49 boolean is_tailspike;
50 boolean is_egg;
51 boolean is_polearm;
52 boolean is_thrown_weapon;
53 boolean is_bulletammo;
54 int kprefix = KILLED_BY_AN;
55 char onmbuf[BUFSZ], knmbuf[BUFSZ];
57 int shieldblockrate = 0;
58 int saberblockrate = 0;
59 int enchrequired = 0;
60 int enchhave = 0;
61 int columnarevasion = 0;
63 int extrachance = 1;
65 if (u.twoweap && uswapwep && (uswapwep->oartifact == ART_BLOCKPARRY || uswapwep->otyp == PARRY_DAGGER || uswapwep->otyp == PARRY_SWORD) ) {
66 shieldblockrate = 30;
67 if (uswapwep->spe > 0) shieldblockrate += (uswapwep->spe * 2);
68 if (!(PlayerCannotUseSkills)) {
69 switch (P_SKILL(P_TWO_WEAPON_COMBAT)) {
70 case P_BASIC: shieldblockrate += 2; break;
71 case P_SKILLED: shieldblockrate += 4; break;
72 case P_EXPERT: shieldblockrate += 6; break;
73 case P_MASTER: shieldblockrate += 8; break;
74 case P_GRAND_MASTER: shieldblockrate += 10; break;
75 case P_SUPREME_MASTER: shieldblockrate += 12; break;
81 if (u.twoweap && uswapwep && uswapwep->oartifact == ART_TOTAL_PARRY_GAUCHE) {
82 shieldblockrate = 40;
84 if (u.twoweap && uwep && uswapwep && (tech_inuse(T_WEAPON_BLOCKER)) ) {
85 shieldblockrate += 25;
87 if (u.martialstyle == MARTIALSTYLE_TAEKWONDO && !uwep && !uarms && (!u.twoweap || !uswapwep) ) {
88 shieldblockrate = 20;
89 if (!(PlayerCannotUseSkills)) {
90 switch (P_SKILL(P_MARTIAL_ARTS)) {
91 case P_BASIC: shieldblockrate += 5; break;
92 case P_SKILLED: shieldblockrate += 10; break;
93 case P_EXPERT: shieldblockrate += 13; break;
94 case P_MASTER: shieldblockrate += 16; break;
95 case P_GRAND_MASTER: shieldblockrate += 20; break;
96 case P_SUPREME_MASTER: shieldblockrate += 25; break;
102 if (u.martialstyle == MARTIALSTYLE_BOJUTSU && uwep && weapon_type(uwep) == P_QUARTERSTAFF) {
103 shieldblockrate = 25;
104 if (uwep->spe > 0) shieldblockrate += (uwep->spe * 2);
105 if (!(PlayerCannotUseSkills)) {
106 switch (P_SKILL(P_QUARTERSTAFF)) {
107 case P_BASIC: shieldblockrate += 2; break;
108 case P_SKILLED: shieldblockrate += 4; break;
109 case P_EXPERT: shieldblockrate += 6; break;
110 case P_MASTER: shieldblockrate += 8; break;
111 case P_GRAND_MASTER: shieldblockrate += 10; break;
112 case P_SUPREME_MASTER: shieldblockrate += 12; break;
117 if (uarms) {
119 shieldblockrate = shield_block_rate(uarms);
120 if (uarms->otyp == ELVEN_SHIELD) {
121 if (Race_if(PM_ELF) || Race_if(PM_PLAYER_MYRKALFR) || Race_if(PM_DROW) || Role_if(PM_ELPH) || Role_if(PM_TWELPH)) shieldblockrate += 5;
124 if (uarms->otyp == URUK_HAI_SHIELD || uarms->otyp == ORCISH_SHIELD || uarms->otyp == ORCISH_GUARD_SHIELD) {
125 if (Race_if(PM_ORC)) shieldblockrate += 5;
127 if (uarms->otyp == DWARVISH_ROUNDSHIELD) {
128 if (Race_if(PM_DWARF)) shieldblockrate += 5;
129 if (Role_if(PM_MIDGET)) shieldblockrate += 5;
132 if (!(PlayerCannotUseSkills)) {
133 switch (P_SKILL(P_SHIELD)) {
134 case P_BASIC: shieldblockrate += 2; break;
135 case P_SKILLED: shieldblockrate += 4; break;
136 case P_EXPERT: shieldblockrate += 6; break;
137 case P_MASTER: shieldblockrate += 8; break;
138 case P_GRAND_MASTER: shieldblockrate += 10; break;
139 case P_SUPREME_MASTER: shieldblockrate += 12; break;
144 if (uarms->oartifact == ART_LURTZ_S_WALL) shieldblockrate += 20;
145 if (uarm && uarm->oartifact == ART_MOEBIUS_ARMOR) shieldblockrate += 10;
146 if (uarms->oartifact == ART_I_M_GETTING_HUNGRY) shieldblockrate += 20;
147 if (uarms->oartifact == ART_WHANG_CLINK_CLONK) shieldblockrate += 10;
148 if (uarms->oartifact == ART_BLOCKBETTER) shieldblockrate += 5;
149 if (uarms->oartifact == ART_VITALITY_STORM) shieldblockrate += 2;
150 if (uarms->oartifact == ART_SUPER_SKELLIE) shieldblockrate += 10;
151 if (uarms->oartifact == ART_WHO_CARES_ABOUT_A_LITTLE_R) shieldblockrate += 15;
152 if (uarms->oartifact == ART_LOOK_HOW_IT_BLOCKS) shieldblockrate += 20;
153 if (uarms->oartifact == ART_BLOCKING_EXTREME) shieldblockrate += 10;
154 if (uarms->oartifact == ART_TSCHINGFIRM) shieldblockrate += 10;
155 if (uarms->oartifact == ART_CUTTING_THROUGH) shieldblockrate += 5;
156 if (uarms->oartifact == ART_LITTLE_PROTECTER) shieldblockrate += 5;
157 if (uwep && uwep->oartifact == ART_VEST_REPLACEMENT) shieldblockrate += 10;
158 if (uwep && uwep->oartifact == ART_THOSE_LAZY_PROGRAMMERS) shieldblockrate += 10;
159 if (Race_if(PM_MACTHEIST)) shieldblockrate += 10;
161 if (u.holyshield) shieldblockrate += (3 + spell_damage_bonus(SPE_HOLY_SHIELD));
163 if (uarms->spe > 0) shieldblockrate += (uarms->spe * 2);
165 if (uarms->cursed) shieldblockrate /= 2;
166 if (uarms->blessed) shieldblockrate += 5;
168 if (uarms->spe < 0) shieldblockrate += (uarms->spe * 2);
170 if (uarm && uarm->oartifact == ART_WOODSTOCK) shieldblockrate += 5;
171 if (uwep && uwep->oartifact == ART_HOLD_IT_OUT) shieldblockrate += 20;
172 if (uwep && uwep->oartifact == ART_SECANTED) shieldblockrate += 5;
173 if (uarm && uarm->oartifact == ART_FARTHER_INTO_THE_JUNGLE) shieldblockrate += 10;
174 if (uwep && uwep->oartifact == ART_BIMMSELIMMELIMM) shieldblockrate += 10;
175 if (Numbed) shieldblockrate -= 10;
177 if (tlev > 10) shieldblockrate -= (rn2(tlev - 9));
179 if (!PlayerCannotUseSkills) {
180 switch (P_SKILL(P_SHIEN)) {
181 case P_BASIC: shieldblockrate += 1; break;
182 case P_SKILLED: shieldblockrate += 2; break;
183 case P_EXPERT: shieldblockrate += 3; break;
184 case P_MASTER: shieldblockrate += 4; break;
185 case P_GRAND_MASTER: shieldblockrate += 5; break;
186 case P_SUPREME_MASTER: shieldblockrate += 6; break;
190 if (Conflict && shieldblockrate > 0) {
191 shieldblockrate *= 2;
192 shieldblockrate /= 3;
194 if (StrongConflict && shieldblockrate > 0) {
195 shieldblockrate *= 2;
196 shieldblockrate /= 3;
199 if (Role_if(PM_DANCER)) shieldblockrate /= 2;
201 if (uarms && uarms->oartifact == ART_THERMO_NUCLEAR_CHAMBER) shieldblockrate = 0;
202 if (uarms && uarms->oartifact == ART_SUPER_ENERGY_LINES) shieldblockrate = 0;
203 if (uarms && uarms->otyp == BROKEN_SHIELD) shieldblockrate = 0;
205 if (shieldblockrate < 0) shieldblockrate = 0;
207 /* If you're berserk, you cannot block at all. We will still show your actual chance to block in enlightenment,
208 so this line should not be copied over to cmd.c --Amy */
209 if (u.berserktime) shieldblockrate = 0;
210 if (uarmf && uarmf->otyp == CATWALK_SANDALS) shieldblockrate = 0;
214 if (!name) {
215 if (!obj) panic("thitu: name & obj both null?");
216 name = strcpy(onmbuf,
217 (obj->quan > 1L) ? doname(obj) : mshot_xname(obj));
218 knm = strcpy(knmbuf, killer_xname(obj));
219 kprefix = KILLED_BY; /* killer_name supplies "an" if warranted */
220 } else {
221 knm = name;
222 /* [perhaps ought to check for plural here to] */
223 if (!strncmpi(name, "the ", 4) ||
224 !strncmpi(name, "an ", 3) ||
225 !strncmpi(name, "a ", 2)) kprefix = KILLED_BY;
227 onm = (obj && obj_is_pname(obj)) ? the(name) :
228 (obj && obj->quan > 1L) ? name : an(name);
229 is_acid = (obj && obj->otyp == ACID_VENOM);
230 is_tailspike = (obj && obj->otyp == TAIL_SPIKES);
231 is_egg = (obj && obj->otyp == EGG);
232 is_polearm = (obj && (objects[obj->otyp].oc_skill == P_POLEARMS || objects[obj->otyp].oc_skill == P_LANCE || objects[obj->otyp].oc_skill == P_GRINDER || obj->otyp == AKLYS || obj->otyp == BLOW_AKLYS || obj->otyp == REACH_TRIDENT || obj->otyp == SPINED_BALL || obj->otyp == CHAIN_AND_SICKLE || obj->otyp == LAJATANG || obj->otyp == LASER_CHAIN));
233 is_thrown_weapon = (obj && (objects[obj->otyp].oc_skill == P_DART || objects[obj->otyp].oc_skill == P_SHURIKEN || objects[obj->otyp].oc_skill == -P_DART || objects[obj->otyp].oc_skill == -P_SHURIKEN) );
234 is_bulletammo = (obj && obj->otyp >= PISTOL_BULLET && obj->otyp <= GAS_GRENADE);
236 if (is_bulletammo) extrachance = 1;
237 else if (is_acid || is_tailspike || is_egg || is_polearm || (obj && obj->oclass == VENOM_CLASS) ) extrachance = 10;
238 else if (is_thrown_weapon) extrachance = 3;
239 else extrachance = 2;
241 if (uwep && is_lightsaber(uwep) && uwep->lamplit) {
242 saberblockrate = 5;
243 if (!PlayerCannotUseSkills) {
244 switch (P_SKILL(P_SHIEN)) {
246 case P_BASIC: saberblockrate += 10; break;
247 case P_SKILLED: saberblockrate += 20; break;
248 case P_EXPERT: saberblockrate += 30; break;
249 case P_MASTER: saberblockrate += 40; break;
250 case P_GRAND_MASTER: saberblockrate += 50; break;
251 case P_SUPREME_MASTER: saberblockrate += 60; break;
252 default: saberblockrate += 0; break;
255 /* shien and djem so are both "form V" so they boost each other --Amy
256 * bonus to lightsaber blocking chance if you've enhanced both */
257 if (P_SKILL(P_SHIEN) >= P_BASIC && P_SKILL(P_DJEM_SO) >= P_BASIC) saberblockrate++;
258 if (P_SKILL(P_SHIEN) >= P_SKILLED && P_SKILL(P_DJEM_SO) >= P_SKILLED) saberblockrate++;
259 if (P_SKILL(P_SHIEN) >= P_EXPERT && P_SKILL(P_DJEM_SO) >= P_EXPERT) saberblockrate++;
260 if (P_SKILL(P_SHIEN) >= P_MASTER && P_SKILL(P_DJEM_SO) >= P_MASTER) saberblockrate++;
261 if (P_SKILL(P_SHIEN) >= P_GRAND_MASTER && P_SKILL(P_DJEM_SO) >= P_GRAND_MASTER) saberblockrate++;
262 if (P_SKILL(P_SHIEN) >= P_SUPREME_MASTER && P_SKILL(P_DJEM_SO) >= P_SUPREME_MASTER) saberblockrate++;
265 if (P_SKILL(weapon_type(uwep)) >= P_SKILLED && !(PlayerCannotUseSkills) ) {
266 saberblockrate += 30;
267 if (Role_if(PM_JEDI)) {
268 saberblockrate += ((100 - saberblockrate) / 2);
270 if (Role_if(PM_SHADOW_JEDI)) {
271 saberblockrate += ((100 - saberblockrate) / 2);
273 if (Role_if(PM_HEDDERJEDI)) {
274 saberblockrate += ((100 - saberblockrate) / 2);
276 if (Race_if(PM_BORG)) {
277 saberblockrate += ((100 - saberblockrate) / 5);
281 if (tlev > 10) saberblockrate -= (rn3(tlev - 9));
285 if (PlayerInColumnarHeels) {
286 columnarevasion = 0;
288 if (!PlayerCannotUseSkills) {
289 switch (P_SKILL(P_HIGH_HEELS)) {
291 case P_BASIC: columnarevasion += 5; break;
292 case P_SKILLED: columnarevasion += 10; break;
293 case P_EXPERT: columnarevasion += 15; break;
294 case P_MASTER: columnarevasion += 20; break;
295 case P_GRAND_MASTER: columnarevasion += 25; break;
296 case P_SUPREME_MASTER: columnarevasion += 30; break;
297 default: columnarevasion += 0; break;
304 if (uwep && is_lightsaber(uwep) && !uwep->lamplit && Role_if(PM_SHADOW_JEDI)) {
305 saberblockrate = 1;
306 if (!PlayerCannotUseSkills) {
307 switch (P_SKILL(P_SHIEN)) {
309 case P_BASIC: saberblockrate += 1; break;
310 case P_SKILLED: saberblockrate += 2; break;
311 case P_EXPERT: saberblockrate += 3; break;
312 case P_MASTER: saberblockrate += 4; break;
313 case P_GRAND_MASTER: saberblockrate += 5; break;
314 case P_SUPREME_MASTER: saberblockrate += 6; break;
315 default: saberblockrate += 0; break;
319 if (tlev > 10) saberblockrate -= (rn3(tlev - 9));
323 /* don't let the player become completely impervious --Amy */
324 if (shieldblockrate > 75) shieldblockrate = 75;
325 if (saberblockrate > 95) saberblockrate = 95;
327 if((u.uac + tlev <= rnd(20)) && (!rn2(StrongConflict ? 5 : Conflict ? 4 : 3))) {
328 if(Blind || !flags.verbose) pline("It misses.");
329 else You("are almost hit by %s.", onm);
330 return(0);
331 } else if ( (u.uac < 0) && (!rn2(StrongConflict ? 4 : Conflict ? 3 : 2)) && !rn2(extrachance) && (rnd(100) < (-(u.uac))) ) {
332 /* more negative AC means a higher chance to deflect projectiles with armor --Amy */
333 if(Blind || !flags.verbose) pline("Your armor deflects a projectile.");
334 else You("deflect %s with your armor.", onm);
336 u.ubodyarmorturns++;
337 if (u.ubodyarmorturns >= 5) {
338 u.ubodyarmorturns = 0;
339 use_skill(P_BODY_ARMOR, 1);
342 return(0);
344 } else if (uarms && uarms->oartifact == ART_HAVENER && rn2(2) && obj && (objects[obj->otyp].oc_skill == -P_BOW || objects[obj->otyp].oc_skill == P_BOW) ) {
346 goto shieldblockboo;
348 } else if (!rn2(extrachance) && (rnd(100) < shieldblockrate) ) {
350 if (u.martialstyle == MARTIALSTYLE_TAEKWONDO && !uwep && !uarms && (!u.twoweap || !uswapwep)) {
352 Your("fists block a projectile.");
353 use_skill(P_MARTIAL_ARTS, 1);
355 } else if (u.martialstyle == MARTIALSTYLE_BOJUTSU && uwep && weapon_type(uwep) == P_QUARTERSTAFF) {
357 Your("quarterstaff blocks a projectile.");
358 use_skill(P_QUARTERSTAFF, 1);
360 } else if (u.twoweap && uwep && uswapwep && (tech_inuse(T_WEAPON_BLOCKER) ) ) {
362 Your("weapons block a projectile.");
363 if (evilfriday && multi >= 0) nomul(-2, "blocking with both weapons", TRUE);
364 use_skill(P_TWO_WEAPON_COMBAT, 1);
366 } else if (u.twoweap && uswapwep && (uswapwep->oartifact == ART_BLOCKPARRY || uswapwep->oartifact == ART_TOTAL_PARRY_GAUCHE || uswapwep->otyp == PARRY_DAGGER || uswapwep->otyp == PARRY_SWORD) ) {
368 Your("parrying weapon blocks a projectile.");
369 use_skill(P_TWO_WEAPON_COMBAT, 1);
371 } else {
373 shieldblockboo:
374 /* a good shield allows you to block projectiles --Amy */
375 if(Blind || !flags.verbose) pline("You block a projectile with your shield.");
376 else You("block %s with your shield.", onm);
377 use_skill(P_SHIELD, 1);
378 if (uarms && uarms->oartifact == ART_SHIENSIDE) use_skill(P_SHIEN, 1);
379 if (uarms && uarms->oartifact == ART_SPICKAR && uarms->invoketimer <= monstermoves) {
380 int artitimeout = rnz(2000);
381 if (!rn2(5)) artitimeout = rnz(20000);
382 int mmstrength = (GushLevel / 3);
383 if (mmstrength < 1) mmstrength = 1;
384 /* squeaking does not help here, as it's not an actual invoke --Amy */
385 uarms->invoketimer = (monstermoves + artitimeout);
387 Your("shield fires a magic missile!");
388 getdir(NULL);
389 buzz(20,mmstrength,u.ux,u.uy,u.dx,u.dy); /* 20 = magic missile */
392 if (uarms && uarms->oartifact == ART_KLUUSCH) {
393 if (Upolyd) {
394 u.mh++;
395 if (u.mh > u.mhmax) u.mh = u.mhmax;
396 } else {
397 u.uhp++;
398 if (u.uhp > u.uhpmax) u.uhp = u.uhpmax;
400 flags.botl = TRUE;
402 if (uwep && uwep->oartifact == ART_BIMMSELIMMELIMM && !rn2(50) && uarms && uarms->spe > -20) {
403 uarms->spe--;
404 pline("Bimmselimmelimm! Splinters of your shield are flying everywhere!");
407 u.ubodyarmorturns++;
408 if (u.ubodyarmorturns >= 5) {
409 u.ubodyarmorturns = 0;
410 use_skill(P_BODY_ARMOR, 1);
415 return(0);
417 } else if (uwep && is_lightsaber(uwep) && (3 > rnd(extrachance)) && (uwep->lamplit || Role_if(PM_SHADOW_JEDI)) && (saberblockrate > rn2(100))) {
419 /* dodge missiles, even when blind; see "A new hope" for blindness reference */
420 You("dodge %s with %s.", onm, yname(uwep));
421 use_skill(P_SHIEN, rnd(4)); /* would take forever to train otherwise --Amy */
423 if (tech_inuse(T_ABSORBER_SHIELD) && uwep && is_lightsaber(uwep) && uwep->lamplit) {
424 pline("Energy surges into the lightsaber as the projectile is blocked.");
425 uwep->age += 25;
426 if (uwep->otyp == ORANGE_LIGHTSABER) uwep->age += (25 * rnd(2));
427 if (uwep->oartifact == ART_DESANN_S_WRATH) uwep->age += (25 * rnd(2));
430 return(0);
432 } else if (uarmc && uarmc->oartifact == ART_DOEDOEDOEDOEDOEDOEDOE_TEST && rn2(3)) {
434 if(Blind || !flags.verbose) You("are not hit by the missile.");
435 else You("are not hit by %s.", onm);
436 return(0);
438 } else if (uarmf && uarmf->oartifact == ART_YELLY && !rn2(2)) {
440 if(Blind || !flags.verbose) You("skillfully evade a projectile.");
441 else You("skillfully evade %s.", onm);
442 return(0);
444 } else if (uarm && uarm->oartifact == ART_BACKOBLOK && !rn2(2)) {
446 if(Blind || !flags.verbose) You("skillfully evade a projectile.");
447 else You("skillfully evade %s.", onm);
448 return(0);
450 } else if (powerfulimplants() && (!rn2(extrachance) || !rn2(extrachance) || !rn2(extrachance)) && uimplant && uimplant->oartifact == ART_GYMNASTIC_LOVE && !rn2(3)) {
452 if(Blind || !flags.verbose) You("skillfully evade a projectile.");
453 else You("skillfully evade %s.", onm);
454 return(0);
456 } else if (uimplant && uimplant->oartifact == ART_IRON_OF_INNERMOST_JOY && rnd(10) < ( ((moves % 13) > 9) ? 6 : (powerfulimplants()) ? 11 : 10) ) {
457 if(Blind || !flags.verbose) You("skillfully evade a projectile.");
458 else You("skillfully evade %s.", onm);
459 return(0);
461 } else if (uarm && uarm->oartifact == ART_IS_ONLY_OWWE && !rn2(10)) {
462 if(Blind || !flags.verbose) You("skillfully evade a projectile.");
463 else You("skillfully evade %s.", onm);
464 return(0);
466 } else if (uarm && uarm->oartifact == ART_BULLETSTOPPER && !rn2(2) && obj && is_bullet(obj) ) {
467 pline_The("armor deflects the shot.");
468 return(0);
470 } else if (uarmc && itemhasappearance(uarmc, APP_KEVLAR_CLOAK) && !rn2(10)) {
471 pline_The("kevlar cloak deflects the projectile.");
472 return(0);
474 } else if (uarmc && uarmc->otyp == KEVLAR_VEST && !rn2(5)) {
475 pline_The("kevlar vest deflects the projectile.");
476 makeknown(KEVLAR_VEST);
477 return(0);
479 } else if (uarm && uarm->otyp == BULLETPROOF_VEST && !rn2(3) ) {
480 pline_The("bulletproof vest deflects the projectile.");
481 return(0);
483 } else if (uarmf && uarmf->otyp == FLECHETTE_BOOTS && !rn2(5) ) {
484 if(Blind || !flags.verbose) You("sidestep a projectile.");
485 else You("sidestep %s.", onm);
486 return(0);
488 } else if (Race_if(PM_CUPID) && !rn2(5)) {
490 if(Blind || !flags.verbose) You("sidestep a projectile.");
491 else You("sidestep %s.", onm);
492 return(0);
494 } else if (uarmf && uarmf->oartifact == ART_FIND_THE_COMBAT_STANCE && !rn2(5)) {
496 if(Blind || !flags.verbose) You("sidestep a projectile.");
497 else You("sidestep %s.", onm);
498 return(0);
500 } else if (columnarevasion > rnd(100)) {
501 if(Blind || !flags.verbose) You("skillfully evade a projectile.");
502 else You("skillfully evade %s.", onm);
503 return(0);
505 } else if (uwep && uwep->oartifact == ART_SYLVIE_S_INVENTION && rn2(3)) {
507 if(Blind || !flags.verbose) You("skillfully evade a projectile.");
508 else You("skillfully evade %s.", onm);
509 return(0);
511 } else if (tech_inuse(T_FORCE_FIELD) && rn2(4)) {
513 if(Blind || !flags.verbose) pline("Your force field causes a projectile to miss you.");
514 else pline("Your force field causes %s to miss you.", onm);
515 return(0);
517 } else if (Race_if(PM_PLAYER_ATLANTEAN) && rn2(2)) {
519 if(Blind || !flags.verbose) pline("Your force field causes a projectile to miss you.");
520 else pline("Your force field causes %s to miss you.", onm);
521 return(0);
523 } else if (Race_if(PM_PLAYER_DYNAMO) && !rn2(3)) {
525 if(Blind || !flags.verbose) pline("You absorb a projectile.");
526 else pline("You absorb %s.", onm);
527 healup(rnd(u.ulevel), 0, FALSE, FALSE);
528 return(0);
530 } else if (!rn2(extrachance) && rnd(30) < (2 + (GushLevel / 2) ) ) {
532 /* depending on your character level, you may be able to dodge --Amy */
533 if(Blind || !flags.verbose) pline("You dodge a projectile.");
534 else You("dodge %s.", onm);
535 return(0);
537 } else {
538 if(Blind || !flags.verbose) You("are hit!");
539 else You("are hit by %s%s", onm, exclam(dam));
541 if (obj && obj->otyp == YITH_TENTACLE) {
542 increasesanity(rnz(monster_difficulty() + 1));
544 if (obj && obj->otyp == NASTYPOLE && !rn2(10)) {
545 badeffect();
548 if (obj && obj->otyp == PETRIFYIUM_BAR) {
549 if ((!Stone_resistance || (!IntStone_resistance && !rn2(20)) ) &&
550 !(poly_when_stoned(youmonst.data) && polymon(PM_STONE_GOLEM))) {
551 if (!Stoned) {
552 if (Hallucination && rn2(10)) pline("Thankfully you are already stoned.");
553 else {
554 Stoned = Race_if(PM_EROSATOR) ? 3 : 7;
555 u.cnd_stoningcount++;
556 pline("You start turning to stone!");
559 sprintf(killer_buf, "petrifyium bar");
560 delayed_killer = killer_buf;
565 if (obj && obj->otyp == DISINTEGRATION_BAR) {
567 if ((!Disint_resistance || !rn2(StrongDisint_resistance ? 1000 : 100) || (evilfriday && (uarms || uarmc || uarm || uarmu)) ) && !rn2(10)) {
568 You_feel("like you're falling apart!");
570 if (uarms) {
571 /* destroy shield; other possessions are safe */
572 if (!(EDisint_resistance & W_ARMS) && !(itemsurvivedestruction(uarms, 12)) ) (void) destroy_arm(uarms);
573 } else if (uarmc) {
574 /* destroy cloak; other possessions are safe */
575 if (!(EDisint_resistance & W_ARMC) && !(itemsurvivedestruction(uarmc, 12)) ) (void) destroy_arm(uarmc);
576 } else if (uarm) {
577 /* destroy suit */
578 if (!(EDisint_resistance & W_ARM) && !(itemsurvivedestruction(uarm, 12)) ) (void) destroy_arm(uarm);
579 } else if (uarmu) {
580 /* destroy shirt */
581 if (!(EDisint_resistance & W_ARMU) && !(itemsurvivedestruction(uarmu, 12)) ) (void) destroy_arm(uarmu);
582 } else {
583 if (u.uhpmax > 20) {
584 u.uhpmax -= rnd(20);
585 if (u.uhp > u.uhpmax) u.uhp = u.uhpmax;
586 losehp(rnz(100 + level_difficulty()), "click click click click click you died", KILLED_BY);
588 } else {
589 u.youaredead = 1;
590 done(DIED);
591 u.youaredead = 0;
599 if (obj && objects[obj->otyp].oc_material == MT_SILVER && (hates_silver(youmonst.data) || (uarmf && uarmf->oartifact == ART_IRIS_S_HIDDEN_ALLERGY) || (uarmh && uarmh->oartifact == ART_IRIS_S_SECRET_VULNERABILIT) || (uarmc && uarmc->oartifact == ART_IRIS_S_UNREVEALED_LOVE) || (uarmg && uarmg->oartifact == ART_IRIS_S_FAVORED_MATERIAL) || autismweaponcheck(ART_PORKMAN_S_BALLS_OF_STEEL) ) ) {
600 dam += rnd(20);
601 pline_The("silver sears your flesh!");
602 exercise(A_CON, FALSE);
604 if (obj && objects[obj->otyp].oc_material == MT_COPPER && hates_copper(youmonst.data)) {
605 dam += 20;
606 pline_The("copper decomposes you!");
607 exercise(A_CON, FALSE);
609 if (obj && objects[obj->otyp].oc_material == MT_MERCURIAL && !rn2(10) && !Poison_resistance) {
610 dam += rnd(4);
611 pline_The("mercury poisons you!");
612 exercise(A_CON, FALSE);
614 if (obj && objects[obj->otyp].oc_material == MT_PLATINUM && (hates_platinum(youmonst.data) || u.contamination >= 1000) ) {
615 dam += 20;
616 pline_The("platinum smashes you!");
617 exercise(A_CON, FALSE);
619 if (obj && obj->cursed && (hates_cursed(youmonst.data) || youmonst.data->mlet == S_ANGEL || Race_if(PM_HUMANOID_ANGEL))) {
620 dam += 4;
621 if (obj->hvycurse) dam += 4;
622 if (obj->prmcurse) dam += 7;
623 if (obj->bbrcurse) dam += 15;
624 if (obj->evilcurse) dam += 15;
625 if (obj->morgcurse) dam += 15;
626 pline("An unholy aura blasts you!");
627 exercise(A_CON, FALSE);
629 if (obj && objects[obj->otyp].oc_material == MT_VIVA && hates_viva(youmonst.data)) {
630 dam += 20;
631 pline_The("irradiation severely hurts you!");
632 exercise(A_CON, FALSE);
634 if (obj && objects[obj->otyp].oc_material == MT_INKA) {
635 dam += 5;
636 pline_The("inka string hurts you!");
637 exercise(A_CON, FALSE);
639 if (obj && obj->otyp == ODOR_SHOT) {
640 dam += rnd(10);
641 pline("You inhale the horrific odor!");
642 if (tlev < 1) increasesanity(rnz(5));
643 else increasesanity(rnz(tlev * 5));
644 exercise(A_CON, FALSE);
647 if (obj && objects[obj->otyp].oc_skill == P_POLEARMS && (u.usteed || youmonst.data->mlet == S_CENTAUR || youmonst.data->mlet == S_UNICORN) || (!Upolyd && Race_if(PM_PLAYER_UNICORN)) || (!Upolyd && Race_if(PM_HUMANOID_CENTAUR)) || (!Upolyd && Race_if(PM_THUNDERLORD)) ) {
648 dam += rnd(10);
649 if (u.usteed && !rn2(25)) {
650 if (!mayfalloffsteed()) {
651 pline("The polearm lifts you out of your saddle!");
652 dismount_steed(DISMOUNT_FELL);
658 if (uarmf && uarmf->oartifact == ART_STAR_SOLES) enchrequired = 1;
659 if (uarmf && uarmf->oartifact == ART_SHE_REALLY_LIKES_IT) enchrequired = 1;
660 if (uarmf && uarmf->oartifact == ART_HERSAY_PRICE) enchrequired = 1;
661 if (Race_if(PM_PLAYER_SKELETON)) enchrequired = 2;
662 if (uarmf && uarmf->oartifact == ART_PHANTO_S_RETARDEDNESS) enchrequired = 4;
664 if (obj && obj->spe > enchhave) enchhave = obj->spe;
665 if (obj && obj->oartifact == ART_MAGICBANE && enchhave < 4) enchhave = 4;
666 if (obj && is_lightsaber(obj) && enchhave < 4) enchhave = 4;
667 if (obj && obj->opoisoned && enchhave < 4) enchhave = 4;
668 if (obj && obj->oartifact) enchhave += 2;
670 if (is_acid && ((Acid_resistance && (StrongAcid_resistance || rn2(10))) ) || AcidImmunity ) {
671 pline("It doesn't seem to hurt you.");
672 if (Stoned) fix_petrification();
673 } else if ((enchrequired > 0) && rn2(3) && (enchhave < enchrequired) ) {
674 pline("The attack doesn't seem to harm you.");
676 else {
677 if (is_acid) {pline("It burns!");
678 if (tlev > 0) dam += rnd(tlev);
679 if (Stoned) fix_petrification();
681 else if (is_tailspike && (tlev > 0) ) dam += rnd(tlev * 2);
682 else if (is_polearm && !rn2(2) && (tlev > 10) ) dam += rnd(tlev - 10);
683 else if (!is_bulletammo && (tlev > 10) && !rn2(3)) dam += rnd(tlev - 10);
685 if (Half_physical_damage && (rn2(2) || (uwep && uwep->oartifact == ART_SOOTHE_)) ) dam = (dam+1) / 2;
686 if (StrongHalf_physical_damage && (rn2(2) || (uwep && uwep->oartifact == ART_SOOTHE_)) ) dam = (dam+1) / 2;
688 if (dam && u.uac < /*-1*/0) { /* AC protects against this damage now, at least a bit --Amy */
690 int tempval;
692 int effectiveac = (-(u.uac));
693 if (issoviet) {
694 effectiveac -= 20;
695 if (effectiveac < 1) effectiveac = 1;
697 if (effectiveac > (issoviet ? 100 : 120)) {
698 if (issoviet) effectiveac -= rn3(effectiveac - 99);
699 else effectiveac -= rn3(effectiveac - 119);
701 if (effectiveac > (issoviet ? 60 : 80)) {
702 if (issoviet) effectiveac -= rn3(effectiveac - 59);
703 else effectiveac -= rn3(effectiveac - 79);
705 if (effectiveac > (issoviet ? 20 : 40)) {
706 if (issoviet) effectiveac -= rn2(effectiveac - 19);
707 else effectiveac -= rn2(effectiveac - 39);
710 tempval = rnd((effectiveac / (issoviet ? 5 : 4)) + 1);
711 if (tempval < 1) tempval = 1;
712 if (tempval > (issoviet ? 20 : 50)) tempval = (issoviet ? 20 : 50); /* max limit increased --Amy */
714 if (issoviet) {
715 dam -= tempval;
716 if (dam < 1) dam = 1;
719 if (dam > 1 && tempval > 0) {
720 dam *= (100 - rnd(tempval));
721 dam++;
722 dam /= 100;
723 if (dam < 1) dam = 1;
728 if (dam >= 2 && GushLevel > rnd(100)) dam = (dam+1) / 2;
730 losehp(dam, knm, kprefix);
731 exercise(A_STR, FALSE);
734 if (obj && (objects[obj->otyp].oc_skill == P_SHURIKEN || objects[obj->otyp].oc_skill == -P_SHURIKEN) && dam > 0) {
735 You("get a cut.");
736 playerbleed(dam);
739 /* evil patch: antimatter bullets will damage the player's inventory --Amy */
740 if (obj && obj->otyp == ANTIMATTER_PISTOL_BULLET) {
741 antimatter_damage(invent, FALSE, FALSE);
743 if (obj && obj->otyp == ANTIMATTER_FIVE_SEVEN_BULLET) {
744 antimatter_damage(invent, FALSE, FALSE);
746 if (obj && obj->otyp == ANTIMATTER_SMG_BULLET) {
747 antimatter_damage(invent, FALSE, FALSE);
749 if (obj && obj->otyp == ANTIMATTER_MG_BULLET) {
750 antimatter_damage(invent, FALSE, FALSE);
752 if (obj && obj->otyp == ANTIMATTER_SNIPER_BULLET) {
753 antimatter_damage(invent, FALSE, FALSE);
755 if (obj && obj->otyp == ANTIMATTER_RIFLE_BULLET) {
756 antimatter_damage(invent, FALSE, FALSE);
758 if (obj && obj->otyp == ANTIMATTER_ASSAULT_RIFLE_BULLE) {
759 antimatter_damage(invent, FALSE, FALSE);
762 /* evil patch: darts of disintegration can disintegrate the player
763 * only have a 10% chance of actually doing so, because otherwise it would be really unbalanced --Amy */
764 if (obj && obj->otyp == DART_OF_DISINTEGRATION) {
765 if ((!Disint_resistance || !rn2(StrongDisint_resistance ? 1000 : 100) || (evilfriday && (uarms || uarmc || uarm || uarmu)) ) && !rn2(10)) {
766 You_feel("like you're falling apart!");
768 if (uarms) {
769 /* destroy shield; other possessions are safe */
770 if (!(EDisint_resistance & W_ARMS) && !(itemsurvivedestruction(uarms, 12)) ) (void) destroy_arm(uarms);
771 } else if (uarmc) {
772 /* destroy cloak; other possessions are safe */
773 if (!(EDisint_resistance & W_ARMC) && !(itemsurvivedestruction(uarmc, 12)) ) (void) destroy_arm(uarmc);
774 } else if (uarm) {
775 /* destroy suit */
776 if (!(EDisint_resistance & W_ARM) && !(itemsurvivedestruction(uarm, 12)) ) (void) destroy_arm(uarm);
777 } else if (uarmu) {
778 /* destroy shirt */
779 if (!(EDisint_resistance & W_ARMU) && !(itemsurvivedestruction(uarmu, 12)) ) (void) destroy_arm(uarmu);
780 } else {
781 if (u.uhpmax > 20) {
782 u.uhpmax -= rnd(20);
783 if (u.uhp > u.uhpmax) u.uhp = u.uhpmax;
784 losehp(rnz(100 + level_difficulty()), "click click click click click you died", KILLED_BY);
786 } else {
787 u.youaredead = 1;
788 done(DIED);
789 u.youaredead = 0;
796 if (obj && obj->oartifact == ART_SIEGFRIED_S_DEATHBOLT) {
797 if ((!Disint_resistance || !rn2(StrongDisint_resistance ? 1000 : 100) || (evilfriday && (uarms || uarmc || uarm || uarmu)) ) ) {
798 You_feel("like you're falling apart!");
800 if (uarms) {
801 /* destroy shield; other possessions are safe */
802 if (!(EDisint_resistance & W_ARMS) && !(itemsurvivedestruction(uarms, 12)) ) (void) destroy_arm(uarms);
803 } else if (uarmc) {
804 /* destroy cloak; other possessions are safe */
805 if (!(EDisint_resistance & W_ARMC) && !(itemsurvivedestruction(uarmc, 12)) ) (void) destroy_arm(uarmc);
806 } else if (uarm) {
807 /* destroy suit */
808 if (!(EDisint_resistance & W_ARM) && !(itemsurvivedestruction(uarm, 12)) ) (void) destroy_arm(uarm);
809 } else if (uarmu) {
810 /* destroy shirt */
811 if (!(EDisint_resistance & W_ARMU) && !(itemsurvivedestruction(uarmu, 12)) ) (void) destroy_arm(uarmu);
812 } else {
813 if (u.uhpmax > 20) {
814 u.uhpmax -= rnd(20);
815 if (u.uhp > u.uhpmax) u.uhp = u.uhpmax;
816 losehp(rnz(100 + level_difficulty()), "Siegfried's murderous crossbow", KILLED_BY);
818 } else {
819 u.youaredead = 1;
820 done(DIED);
821 u.youaredead = 0;
828 if (obj && obj->otyp == FLAMETHROWER) {
829 if (FireImmunity || (Fire_resistance && rn2(StrongFire_resistance ? 20 : 5)) ) {
830 pline_The("fire doesn't seem to harm you.");
831 } else {
832 losehp(rnd(6), "being flamethrowered", KILLED_BY);
836 if (obj && objects[obj->otyp].oc_skill == P_GRINDER) {
837 You("are grinded!");
838 losehp(rnd(10), "grinding", KILLED_BY);
841 return(1);
845 /* Be sure this corresponds with what happens to player-thrown objects in
846 * dothrow.c (for consistency). --KAA
847 * Returns 0 if object still exists (not destroyed).
850 STATIC_OVL int
851 drop_throw(mon, obj, ohit, x, y)
852 register struct monst *mon;
853 register struct obj *obj;
854 boolean ohit;
855 int x,y;
857 struct obj *mwep = (struct obj *) 0;
859 int retvalu = 1;
860 int create, chance;
861 struct monst *mtmp;
862 struct trap *t;
864 if (mon) mwep = MON_WEP(mon);
866 if (issegfaulter) { /* used to cause segfault panics but that's just malicious... cause fake segfault instead --Amy */
867 if (obj->oclass == VENOM_CLASS) {
868 if (obj->otyp == SEGFAULT_VENOM && !rn2(5) ) {
869 u.segfaultpanic = TRUE;
874 if ((obj->otyp == CREAM_PIE || obj->oclass == VENOM_CLASS ||
875 /* WAC added Spoon throw code */
876 (obj->oartifact == ART_HOUCHOU) ||
877 /* WAC -- assume monsters don't throw without
878 using the right propellor */
879 (is_bullet(obj) && !(objects[obj->otyp].oc_material == MT_LEAD && !rn2(2))) ||
880 (ohit && obj->otyp == EGG)))
881 create = 0;
882 else if (ohit && (is_multigen(obj) || obj->otyp == ROCK)) {
884 /* copying over the dothrow.c code, because it makes no sense for blessed +10 ammo to break 2 out of 3 times --Amy */
885 chance = greatest_erosionX(obj) - obj->spe;
886 chance -= rnd(2);
888 if (chance > 1) {
889 if (chance == 3) chance = 2;
890 else if (chance == 4) chance = 3;
891 else if (chance == 5) chance = 3;
892 else if (chance > 5) chance /= 2;
893 create = !rn2(chance);
894 } else {
895 chance = 3 + obj->spe - greatest_erosionX(obj);
896 if (chance > 3) chance = 2 + rno(chance - 2);
897 if (chance < 2) chance = 2; /* fail safe */
898 if (Race_if(PM_MONGUNG)) chance *= 2;
900 create = rn2(chance);
903 if (obj->blessed && !rnl(6))
904 create = 1;
905 if (!obj->blessed && !obj->cursed && !rn2(3) && !rnl(6))
906 create = 1;
908 if (!(PlayerCannotUseSkills)) {
909 switch (P_SKILL(P_MISSILE_WEAPONS)) {
910 default: break;
911 case P_BASIC: if (rn2(10) < 1) create = 1; break;
912 case P_SKILLED: if (rn2(10) < 2) create = 1; break;
913 case P_EXPERT: if (rn2(10) < 3) create = 1; break;
914 case P_MASTER: if (rn2(10) < 4) create = 1; break;
915 case P_GRAND_MASTER: if (rn2(10) < 5) create = 1; break;
916 case P_SUPREME_MASTER: if (rn2(10) < 6) create = 1; break;
920 if (!(PlayerCannotUseSkills)) {
922 if (objects[obj->otyp].oc_skill == -P_BOW && (P_SKILL(P_BOW) >= P_BASIC) && rn2(P_SKILL(P_BOW)) )
923 create = 1;
924 if (objects[obj->otyp].oc_skill == -P_CROSSBOW && (P_SKILL(P_CROSSBOW) >= P_BASIC) && rn2(P_SKILL(P_CROSSBOW)) )
925 create = 1;
926 if (objects[obj->otyp].oc_skill == -P_SLING && (P_SKILL(P_SLING) >= P_BASIC) && rn2(P_SKILL(P_SLING)) )
927 create = 1;
928 if (objects[obj->otyp].oc_skill == -P_DART && (P_SKILL(P_DART) >= P_BASIC) && rn2(P_SKILL(P_DART)) )
929 create = 1;
930 if (objects[obj->otyp].oc_skill == -P_SHURIKEN && (P_SKILL(P_SHURIKEN) >= P_BASIC) && rn2(P_SKILL(P_SHURIKEN)) )
931 create = 1;
935 if (objects[obj->otyp].oc_skill == -P_BOW && uarm && uarm->oartifact == ART_WOODSTOCK && !create && !rn2(2))
936 create = 1;
937 if (objects[obj->otyp].oc_material == MT_MINERAL && uarm && uarm->oartifact == ART_QUARRY && !create && !rn2(2))
938 create = 1;
939 if (uarmc && uarmc->oartifact == ART_ARABELLA_S_WEAPON_STORAGE && !create && !rn2(2))
940 create = 1;
941 if (Race_if(PM_MACTHEIST) && objects[obj->otyp].oc_skill == P_SLING && !create && !rn2(2))
942 create = 1;
943 if (Race_if(PM_MACTHEIST) && objects[obj->otyp].oc_skill == -P_SLING && !create && !rn2(2))
944 create = 1;
946 if (objects[obj->otyp].oc_material == MT_LEAD && !create && !rn2(4)) create = 1;
947 if (objects[obj->otyp].oc_material == MT_BAMBOO && !create && !rn2(4)) create = 1;
948 if (obj->otyp == DART_OF_DISINTEGRATION && rn2(10)) create = 0;
950 } else create = 1;
952 if (obj->mstartinventB && obj->otyp != ROCKET && obj->otyp != MINI_NUKE && !is_grenade(obj) && !(obj->oartifact) && !(obj->fakeartifact && timebasedlowerchance() && rn2(4) ) && (!rn2(4) || (rn2(100) < u.equipmentremovechance) || !timebasedlowerchance() ) ) create = 0;
953 if (obj->mstartinventC && obj->otyp != ROCKET && obj->otyp != MINI_NUKE && !is_grenade(obj) && !(obj->oartifact) && !(obj->fakeartifact && !rn2(10)) && rn2(10)) create = 0;
954 if (obj->mstartinventE && obj->otyp != ROCKET && obj->otyp != MINI_NUKE && !is_grenade(obj) && !(obj->oartifact) && !(obj->fakeartifact && !rn2(20)) && rn2(20)) create = 0;
955 if (obj->mstartinventD && obj->otyp != ROCKET && obj->otyp != MINI_NUKE && !is_grenade(obj) && !(obj->oartifact) && !(obj->fakeartifact && !rn2(4)) && rn2(4)) create = 0;
956 if (obj->mstartinventX && obj->otyp != ROCKET && obj->otyp != MINI_NUKE && !is_grenade(obj)) create = 0;
958 /* Detonate rockets */
959 if (is_grenade(obj)) {
961 if (rn2(5)) verbalize("Fire in the hole!");
962 else if (rn2(3)) verbalize("Fire in the ass hole!");
963 else if (rn2(2)) verbalize("Fire in your ass hole %s!", playeraliasname);
964 else verbalize("Here is a grenade four you!"); /* sic */
966 if (!ohit) {
967 create = 1; /* Don't destroy */
968 arm_bomb(obj, FALSE);
969 } else {
970 grenade_explode(obj, bhitpos.x, bhitpos.y, FALSE, 0);
971 obj = (struct obj *)0;
973 } else if (objects[obj->otyp].oc_dir & EXPLOSION) {
974 if (cansee(bhitpos.x,bhitpos.y))
975 pline("%s explodes in a ball of fire!", Doname2(obj));
976 else You_hear("an explosion");
977 explode(bhitpos.x, bhitpos.y, -ZT_SPELL(ZT_FIRE), d(3,8),
978 WEAPON_CLASS, EXPL_FIERY);
980 if (obj && obj->otyp == MINI_NUKE) fatman_explosion(bhitpos.x, bhitpos.y, obj);
984 /* D: Detonate crossbow bolts from Hellfire if they hit */
985 if (ohit && mwep && (mwep->oartifact == ART_HELLFIRE || mwep->oartifact == ART_EVERCONSUMING_HELLFIRE || (obj && obj->oartifact == ART_BAKUHATSU_SEI_MISAIRU) || mwep->oartifact == ART_UNIDENTIFIED_HELLCAST || mwep->oartifact == ART_SEVENTH_SCRIPTURE)
986 && is_ammo(obj) && ammo_and_launcher(obj, mwep)) {
988 if (cansee(bhitpos.x,bhitpos.y))
989 pline("%s explodes in a ball of fire!", Doname2(obj));
990 else
991 You_hear("an explosion");
993 explode(bhitpos.x, bhitpos.y, -ZT_SPELL(ZT_FIRE),
994 d(2,6), WEAPON_CLASS, EXPL_FIERY);
996 /* D: Exploding bolts will be destroyed */
997 create = 0;
1000 if (create && !((mtmp = m_at(x, y)) && (mtmp->mtrapped) &&
1001 (t = t_at(x, y)) && ((t->ttyp == PIT) || (t->ttyp == SHIT_PIT) || (t->ttyp == MANA_PIT) || (t->ttyp == ANOXIC_PIT) || (t->ttyp == HYPOXIC_PIT) || (t->ttyp == GIANT_CHASM) || (t->ttyp == ACID_PIT) ||
1002 (t->ttyp == SPIKED_PIT)))) {
1003 int objgone = 0;
1004 obj->mstartinventB = 0;
1005 obj->mstartinventC = 0;
1006 obj->mstartinventD = 0;
1007 obj->mstartinventE = 0;
1008 if (obj->mstartinventX) u.itemcleanupneeded = TRUE;
1010 if (down_gate(x, y) != -1)
1011 objgone = ship_object(obj, x, y, FALSE);
1012 if (!objgone) {
1013 if (!flooreffects(obj,x,y,"fall")) { /* don't double-dip on damage */
1014 place_object(obj, x, y);
1016 if (!mtmp && x == u.ux && y == u.uy)
1017 mtmp = &youmonst;
1018 if (mtmp && ohit)
1019 passive_obj(mtmp, obj, (struct attack *)0);
1021 /* evil patch idea: monsters shooting nasty gray stones cause them to end up in your pack --Amy */
1022 if (obj && x == u.ux && y == u.uy && is_nastygraystone(obj)) {
1023 pline("%s lands in your knapsack!", Doname2(obj));
1024 (void) pickup_object(obj, obj->quan, TRUE, TRUE);
1025 } else if (obj && x == u.ux && y == u.uy && is_feminismstone(obj)) {
1026 pline("%s stays in your inventory, and you get a bad feeling about it.", Doname2(obj));
1027 (void) pickup_object(obj, obj->quan, TRUE, TRUE);
1028 } else stackobj(obj);
1029 retvalu = 0;
1033 } else if (obj) obfree(obj, (struct obj*) 0);
1035 return retvalu;
1038 #endif /* OVLB */
1039 #ifdef OVL1
1041 /* an object launched by someone/thing other than player attacks a monster;
1042 return 1 if the object has stopped moving (hit or its range used up) */
1044 ohitmon(mon, mtmp, otmp, range, verbose)
1045 struct monst *mon; /* monster thrower (if applicable) */
1046 struct monst *mtmp; /* accidental target */
1047 struct obj *otmp; /* missile; might be destroyed by drop_throw */
1048 int range; /* how much farther will object travel if it misses */
1049 /* Use -1 to signify to keep going even after hit, */
1050 /* unless its gone (used for rolling_boulder_traps) */
1051 boolean verbose; /* give message(s) even when you can't see what happened */
1053 int damage, tmp;
1054 boolean vis, ismimic;
1055 int objgone = 1;
1056 register struct obj *blocker = (struct obj *)0;
1057 int shieldblockrate = 0;
1059 ismimic = mtmp->m_ap_type && mtmp->m_ap_type != M_AP_MONSTER;
1060 vis = cansee(bhitpos.x, bhitpos.y);
1062 tmp = 5 + find_mac(mtmp) + omon_adj(mtmp, otmp, FALSE);
1064 /* Amy edit: if a pet is the target and the monster is high-level, add to-hit to make sure it can actually hit */
1065 if (mtmp->mtame && mon) {
1066 int armordifferential = 0;
1067 if (mon->m_lev > 0) armordifferential += mon->m_lev;
1068 if (mtmp->m_lev > mon->m_lev) armordifferential -= (mtmp->m_lev - mon->m_lev);
1069 if (armordifferential < 0) armordifferential = 0; /* fail safe */
1070 tmp += armordifferential;
1071 if (otmp && otmp->oclass == VENOM_CLASS) tmp += 10;
1073 if (verysmall(mtmp->data) && !rn2(8)) {
1074 if (!ismimic) {
1075 if (vis) pline("%s avoids a projectile.", Monnam(mtmp));
1077 if (!range) { /* Last position; object drops */
1078 (void) drop_throw(mon, otmp, 0, mtmp->mx, mtmp->my);
1079 return 1;
1081 } else if (rathersmall(mtmp->data) && !verysmall(mtmp->data) && !rn2(20)) {
1082 if (!ismimic) {
1083 if (vis) pline("%s avoids a projectile.", Monnam(mtmp));
1085 if (!range) { /* Last position; object drops */
1086 (void) drop_throw(mon, otmp, 0, mtmp->mx, mtmp->my);
1087 return 1;
1089 } else if (hugemonst(mtmp->data) && !rn2(8)) {
1090 if (!ismimic) {
1091 if (vis) pline("%s shrugs off a projectile.", Monnam(mtmp));
1093 if (!range) { /* Last position; object drops */
1094 (void) drop_throw(mon, otmp, 0, mtmp->mx, mtmp->my);
1095 return 1;
1097 } else if (bigmonst(mtmp->data) && !hugemonst(mtmp->data) && !rn2(15)) {
1098 if (!ismimic) {
1099 if (vis) pline("%s shrugs off a projectile.", Monnam(mtmp));
1101 if (!range) { /* Last position; object drops */
1102 (void) drop_throw(mon, otmp, 0, mtmp->mx, mtmp->my);
1103 return 1;
1105 } else if (amorphous(mtmp->data) && !rn2(10)) {
1106 if (!ismimic) {
1107 if (vis) pline("%s's amorphous body skillfully dodges a projectile.", Monnam(mtmp));
1109 if (!range) { /* Last position; object drops */
1110 (void) drop_throw(mon, otmp, 0, mtmp->mx, mtmp->my);
1111 return 1;
1113 } else if (noncorporeal(mtmp->data) && !rn2(2)) {
1114 if (!ismimic) {
1115 if (vis) pline("%s avoids a projectile due to being noncorporeal.", Monnam(mtmp));
1117 if (!range) { /* Last position; object drops */
1118 (void) drop_throw(mon, otmp, 0, mtmp->mx, mtmp->my);
1119 return 1;
1121 } else if (unsolid(mtmp->data) && !rn2(8)) {
1122 if (!ismimic) {
1123 if (vis) pline("%s's unsolid body lets a projectile pass through harmlessly.", Monnam(mtmp));
1125 if (!range) { /* Last position; object drops */
1126 (void) drop_throw(mon, otmp, 0, mtmp->mx, mtmp->my);
1127 return 1;
1129 } else if (ecm_monster(mtmp->data)) { /* will never be hit by monsters' ranged attacks */
1130 if (!ismimic) {
1131 pline("%s uses an ECM system to divert a projectile.", Monnam(mtmp));
1133 if (!range) { /* Last position; object drops */
1134 (void) drop_throw(mon, otmp, 0, mtmp->mx, mtmp->my);
1135 return 1;
1137 } else if (swatting_monster(mtmp->data)) { /* will never be hit by monsters' ranged attacks */
1138 if (!ismimic) {
1139 pline("%s swats a projectile away.", Monnam(mtmp));
1141 if (!range) { /* Last position; object drops */
1142 (void) drop_throw(mon, otmp, 0, mtmp->mx, mtmp->my);
1143 return 1;
1145 } else if (mtmp->data == &mons[PM_XXXXXXXXXXXXXXXXXXXX] || mtmp->data == &mons[PM_IDE_BY__]) { /* will never be hit by monsters' ranged attacks */
1146 if (!ismimic) {
1147 pline("%s swats a projectile away.", Monnam(mtmp));
1149 if (!range) { /* Last position; object drops */
1150 (void) drop_throw(mon, otmp, 0, mtmp->mx, mtmp->my);
1151 return 1;
1153 } else if (blocker = (which_armor(mtmp, W_ARMS))) {
1155 shieldblockrate = shield_block_rate(blocker);
1156 shieldblockrate += 10; /* monsters can simply block better --Amy */
1158 if (blocker->otyp == ELVEN_SHIELD && is_elf(mtmp->data)) shieldblockrate += 5;
1159 if (blocker->otyp == URUK_HAI_SHIELD && is_orc(mtmp->data)) shieldblockrate += 5;
1160 if (blocker->otyp == ORCISH_SHIELD && is_orc(mtmp->data)) shieldblockrate += 5;
1161 if (blocker->otyp == ORCISH_GUARD_SHIELD && is_orc(mtmp->data)) shieldblockrate += 5;
1162 if (blocker->otyp == DWARVISH_ROUNDSHIELD && is_dwarf(mtmp->data)) shieldblockrate += 5;
1164 if (shieldblockrate && (blocker->spe > 0)) shieldblockrate += (blocker->spe * 2);
1165 if (blocker->blessed) shieldblockrate += 5;
1167 if (shieldblockrate > 75) shieldblockrate = 75;
1169 if (blocker->otyp == BROKEN_SHIELD) shieldblockrate = 0;
1171 if (rnd(100) < shieldblockrate) {
1172 if (!ismimic) {
1173 pline("%s's shield blocks a projectile.", Monnam(mtmp));
1175 if (!range) { /* Last position; object drops */
1176 (void) drop_throw(mon, otmp, 0, mtmp->mx, mtmp->my);
1177 return 1;
1180 else goto blockingdone;
1181 } else
1182 blockingdone:
1183 if (tmp < rnd(20)) {
1184 if (!ismimic) {
1185 if (vis) miss(distant_name(otmp, mshot_xname), mtmp);
1186 else if (verbose) pline("It is missed.");
1188 if (!range) { /* Last position; object drops */
1189 (void) drop_throw(mon, otmp, 0, mtmp->mx, mtmp->my);
1190 return 1;
1192 } else if (otmp->oclass == POTION_CLASS) {
1193 if (ismimic) seemimic(mtmp);
1194 mtmp->msleeping = 0;
1195 if (vis) otmp->dknown = 1;
1196 potionhit(mtmp, otmp, FALSE);
1197 if (mon && !DEADMONSTER(mon) && !DEADMONSTER(mtmp) &&
1198 mtmp->movement >= NORMAL_SPEED && rn2(4)) {
1199 /* retaliate */
1200 mtmp->movement -= NORMAL_SPEED;
1201 mattackm(mtmp, mon);
1203 return 1;
1204 } else {
1205 damage = dmgval(otmp, mtmp);
1206 if (mtmp->mtame && mon) {
1207 if (mon->m_lev >= 5) damage += ((mon->m_lev - 4) / 2);
1208 if (otmp->otyp == TAIL_SPIKES) damage += rnd((mon->m_lev * 2) + 30);
1209 if (otmp->otyp == DART_OF_DISINTEGRATION) damage += rnd(50);
1210 if (otmp->otyp == DISINTEGRATION_BAR) damage += rnd(50);
1211 if (otmp->otyp == NASTYPOLE) damage += rnd(10);
1212 if (otmp->otyp == PETRIFYIUM_BAR && !rn2(4)) damage += rnd(200);
1213 if (otmp && objects[otmp->otyp].oc_skill == P_GRINDER) damage += rnd(10);
1215 if (otmp->otyp == SPOON) {
1216 pline("The spoon flashes brightly as it hits %s.",
1217 the(mon_nam(mtmp)));
1220 if (otmp->otyp == ACID_VENOM && resists_acid(mtmp) && !player_will_pierce_resistance())
1221 damage = 0;
1222 if (ismimic) seemimic(mtmp);
1223 mtmp->msleeping = 0;
1224 if (vis) hit(distant_name(otmp,mshot_xname), mtmp, exclam(damage));
1225 else if (verbose) pline("%s is hit%s", Monnam(mtmp), exclam(damage));
1227 if (otmp->opoisoned) {
1228 if (resists_poison(mtmp) && !player_will_pierce_resistance()) {
1229 if (vis) pline_The("poison doesn't seem to affect %s.",
1230 mon_nam(mtmp));
1231 } else {
1232 if (rn2(150) || resists_poison(mtmp)) {
1233 damage += rnd(mtmp->mtame ? 15 : 6);
1234 } else {
1235 if (vis) pline_The("poison was deadly...");
1236 damage = mtmp->mhp;
1240 if (objects[otmp->otyp].oc_material == MT_SILVER &&
1241 hates_silver(mtmp->data)) {
1242 if (vis) pline_The("silver sears %s flesh!",
1243 s_suffix(mon_nam(mtmp)));
1244 else if (verbose) pline("Its flesh is seared!");
1246 if (objects[otmp->otyp].oc_material == MT_VIVA && hates_viva(mtmp->data)) {
1247 if (verbose) pline("It is irradiated!");
1249 if (objects[otmp->otyp].oc_material == MT_COPPER && hates_copper(mtmp->data)) {
1250 if (verbose) pline("It is decomposed!");
1252 if (objects[otmp->otyp].oc_material == MT_PLATINUM && hates_platinum(mtmp->data)) {
1253 if (verbose) pline("It is smashed!");
1255 if (otmp->cursed && hates_cursed(mtmp->data)) {
1256 if (verbose) pline("It is blasted by darkness!");
1258 if (objects[otmp->otyp].oc_material == MT_INKA && hates_inka(mtmp->data)) {
1259 if (verbose) pline("It is hurt!");
1261 if (otmp->otyp == ODOR_SHOT && hates_odor(mtmp->data)) {
1262 if (verbose) pline("It is beguiled!");
1264 if (otmp->otyp == ACID_VENOM && cansee(mtmp->mx,mtmp->my)) {
1265 if (resists_acid(mtmp) && !player_will_pierce_resistance()) {
1266 if (vis || verbose)
1267 pline("%s is unaffected.", Monnam(mtmp));
1268 damage = 0;
1269 } else {
1270 if (vis) pline_The("acid burns %s!", mon_nam(mtmp));
1271 else if (verbose) pline("It is burned!");
1274 mtmp->mhp -= damage;
1275 if (mtmp->mhp < 1) {
1276 if (vis || verbose)
1277 pline("%s is %s!", Monnam(mtmp),
1278 (nonliving(mtmp->data) || !canspotmon(mtmp))
1279 ? "destroyed" : "killed");
1280 /* don't blame hero for unknown rolling boulder trap */
1281 if (!flags.mon_moving &&
1282 (otmp->otyp != BOULDER || range >= 0 || !otmp->otrapped))
1283 xkilled(mtmp,0);
1284 else mondied(mtmp);
1286 if (mtmp->mhp > 0) monster_pain(mtmp);
1288 if (can_blnd((struct monst*)0, mtmp,
1289 (uchar)(otmp->otyp == BLINDING_VENOM ? AT_SPIT : AT_WEAP),
1290 otmp)) {
1291 if (vis && mtmp->mcansee)
1292 pline("%s is blinded by %s.", Monnam(mtmp), the(xname(otmp)));
1293 mtmp->mcansee = 0;
1294 tmp = (int)mtmp->mblinded + rnd(25) + 20;
1295 if (tmp > 127) tmp = 127;
1296 mtmp->mblinded = tmp;
1299 if (mon && !DEADMONSTER(mon) && !DEADMONSTER(mtmp) &&
1300 mtmp->movement >= NORMAL_SPEED && rn2(4)) {
1301 /* retaliate */
1302 mtmp->movement -= NORMAL_SPEED;
1303 mattackm(mtmp, mon);
1306 objgone = drop_throw(mon, otmp, 1, bhitpos.x, bhitpos.y);
1307 if (!objgone && range == -1) { /* special case */
1308 obj_extract_self(otmp); /* free it for motion again */
1309 return 0;
1311 return 1;
1313 return 0;
1316 void
1317 m_throw(mon, x, y, dx, dy, range, obj)
1318 register struct monst *mon;
1319 register int x,y,dx,dy,range; /* direction and range */
1320 register struct obj *obj;
1322 register struct monst *mtmp;
1323 struct obj *singleobj, *mwep;
1324 char sym = obj->oclass;
1325 int hitu, blindinc = 0;
1326 int tmpwpndmg = 0;
1328 bhitpos.x = x;
1329 bhitpos.y = y;
1331 if (DEADMONSTER(mon)) return;
1333 if (obj->quan == 1L) {
1335 * Remove object from minvent. This cannot be done later on;
1336 * what if the player dies before then, leaving the monster
1337 * with 0 daggers? (This caused the infamous 2^32-1 orcish
1338 * dagger bug).
1340 * VENOM is not in minvent - it should already be OBJ_FREE.
1341 * The extract below does nothing.
1344 /* not possibly_unwield, which checks the object's */
1345 /* location, not its existence */
1346 if (MON_WEP(mon) == obj) {
1347 setmnotwielded(mon,obj);
1348 MON_NOWEP(mon);
1350 obj_extract_self(obj);
1351 singleobj = obj;
1352 obj = (struct obj *) 0;
1353 } else {
1354 singleobj = splitobj(obj, 1L);
1355 obj_extract_self(singleobj);
1358 singleobj->owornmask = 0; /* threw one of multiple weapons in hand? */
1360 if (mon) mwep = MON_WEP(mon);
1361 else mwep = (struct obj *) 0;
1363 /* D: Special launcher effects */
1364 if (mwep && is_ammo(singleobj) && ammo_and_launcher(singleobj, mwep)) {
1365 if ((mwep->oartifact == ART_PLAGUE || mwep->oartifact == ART_BOW_OF_VINDERRE || mwep->oartifact == ART_SHAKING_BOW || mwep->oartifact == ART_BIBLICAL_PLAGUE || mwep->oartifact == ART_BOW_OF_HERCULES) && is_poisonable(singleobj))
1366 singleobj->opoisoned = 1;
1368 /* D: Hellfire is handled in drop_throw */
1371 if (mwep && singleobj && ammo_and_launcher(singleobj, mwep) && is_ammo(singleobj) && singleobj->otyp == POISON_BOLT) {
1372 singleobj->opoisoned = 1;
1375 if (mwep && singleobj && ammo_and_launcher(singleobj, mwep) && is_ammo(singleobj) && singleobj->otyp == CHROME_PELLET) {
1376 singleobj->opoisoned = 1;
1380 if (singleobj->cursed && (dx || dy) && !rn2(7)) {
1381 if(canseemon(mon) && flags.verbose) {
1382 if(is_ammo(singleobj))
1383 pline("%s misfires!", Monnam(mon));
1384 else
1385 pline("%s as %s throws it!",
1386 Tobjnam(singleobj, "slip"), mon_nam(mon));
1388 dx = rn2(3)-1;
1389 dy = rn2(3)-1;
1390 /* check validity of new direction */
1391 if (!dx && !dy) {
1392 (void) drop_throw(mon, singleobj, 0, bhitpos.x, bhitpos.y);
1393 return;
1397 /* pre-check for doors, walls and boundaries.
1398 Also need to pre-check for bars regardless of direction;
1399 the random chance for small objects hitting bars is
1400 skipped when reaching them at point blank range */
1401 if (!isok(bhitpos.x+dx,bhitpos.y+dy)
1402 || (IS_ROCK(levl[bhitpos.x+dx][bhitpos.y+dy].typ) && !IS_FARMLAND(levl[bhitpos.x+dx][bhitpos.y+dy].typ) )
1403 || IS_WATERTUNNEL(levl[bhitpos.x+dx][bhitpos.y+dy].typ)
1404 || closed_door(bhitpos.x+dx, bhitpos.y+dy)
1405 || (levl[bhitpos.x + dx][bhitpos.y + dy].typ == IRONBARS &&
1406 hits_bars(&singleobj, bhitpos.x, bhitpos.y, 0, 0))) {
1408 if (!isok(bhitpos.x+dx,bhitpos.y+dy) || !((u.ux == bhitpos.x+dx) && (u.uy == bhitpos.y+dy)) ) {
1409 (void) drop_throw(mon, singleobj, 0, bhitpos.x, bhitpos.y);
1410 return;
1414 /* Note: drop_throw may destroy singleobj. Since obj must be destroyed
1415 * early to avoid the dagger bug, anyone who modifies this code should
1416 * be careful not to use either one after it's been freed.
1418 if (sym) tmp_at(DISP_FLASH, obj_to_glyph(singleobj));
1419 while(range-- > 0) { /* Actually the loop is always exited by break */
1420 bhitpos.x += dx;
1421 bhitpos.y += dy;
1423 if (!singleobj) { /* destroyed by hits_bars, bug discovered by amateurhour --Amy */
1424 pline("Some thin air brushes you!");
1425 break;
1428 if ((mtmp = m_at(bhitpos.x, bhitpos.y)) != 0) {
1429 if (ohitmon(mon, mtmp, singleobj, range, TRUE))
1430 break;
1431 } else if (bhitpos.x == u.ux && bhitpos.y == u.uy) {
1432 if (multi) nomul(0, 0, FALSE);
1434 if (singleobj->oclass == GEM_CLASS &&
1435 singleobj->otyp <= LAST_GEM+9 /* 9 glass colors */
1436 && is_unicorn(youmonst.data)) {
1437 if (singleobj->otyp > LAST_GEM) {
1438 You("catch the %s.", xname(singleobj));
1439 You("are not interested in %s junk.",
1440 s_suffix(mon_nam(mon)));
1441 makeknown(singleobj->otyp);
1442 dropy(singleobj);
1443 } else {
1444 You("accept %s gift in the spirit in which it was intended.",
1445 s_suffix(mon_nam(mon)));
1446 (void)hold_another_object(singleobj,
1447 "You catch, but drop, %s.", xname(singleobj),
1448 "You catch:");
1450 break;
1452 if (singleobj->oclass == POTION_CLASS) {
1453 if (!Blind) singleobj->dknown = 1;
1454 potionhit(&youmonst, singleobj, FALSE);
1455 break;
1457 switch(singleobj->otyp) {
1458 int dam, hitv;
1459 case EGG:
1460 if (!touch_petrifies(&mons[singleobj->corpsenm])) {
1461 impossible("monster throwing egg type %d",
1462 singleobj->corpsenm);
1463 hitu = 0;
1464 break;
1466 /* fall through */
1467 case CREAM_PIE:
1468 case BLINDING_VENOM:
1469 hitu = thitu(8 + (mon->m_lev / 2), 0, singleobj, (char *)0);
1470 break;
1471 default:
1473 tmpwpndmg = dmgval(singleobj, &youmonst);
1474 if (tmpwpndmg > 0) {
1475 if (mon->m_lev < 2 && u.urmaxlvlUP < 4) tmpwpndmg /= 2;
1476 if (mon->m_lev == 2 && u.urmaxlvlUP < 4) {
1477 tmpwpndmg /= 3;
1478 tmpwpndmg *= 2;
1480 if (mon->m_lev == 3 && u.urmaxlvlUP < 4) {
1481 tmpwpndmg /= 4;
1482 tmpwpndmg *= 3;
1484 if (mon->m_lev == 4 && u.urmaxlvlUP < 4) {
1485 tmpwpndmg /= 5;
1486 tmpwpndmg *= 4;
1488 if (tmpwpndmg < 1) tmpwpndmg = 1; /* fail safe */
1491 dam = tmpwpndmg;
1492 if (singleobj->otyp == BOULDER && !rn2(2)) dam += (2 * (mon->m_lev));
1494 if (singleobj->otyp == BOULDER && (mon->data == &mons[PM_BOULDER_FART] || mon->data == &mons[PM_FIRM_BOULDER_FART])) {
1495 pline("%s produces %s farting noises with %s %s butt.", Monnam(mon), !rn2(2) ? "loud" : "disgusting", mhis(mon), mon->female ? "sexy" : "ugly");
1496 u.cnd_fartingcount++;
1497 if (Role_if(PM_CLIMACTERIAL)) climtrainsqueaking(1);
1498 if (Role_if(PM_BUTT_LOVER) && !rn2(20)) buttlovertrigger();
1499 if (Role_if(PM_SOCIAL_JUSTICE_WARRIOR)) sjwtrigger();
1500 if (!extralongsqueak()) badeffect();
1503 hitv = 3 - distmin(u.ux,u.uy, mon->mx,mon->my);
1504 if (hitv < -4) hitv = -4;
1505 if (is_elf(mon->data) &&
1506 objects[singleobj->otyp].oc_skill == P_BOW) {
1507 hitv++;
1508 if (MON_WEP(mon) &&
1509 MON_WEP(mon)->otyp == ELVEN_BOW)
1510 hitv++;
1511 if(singleobj->otyp == ELVEN_ARROW) dam++;
1513 if (bigmonst(youmonst.data)) hitv++;
1514 /* high-level monsters sometimes deal extra damage --Amy */
1515 if (mon->m_lev >= 10 && !rn2(2)) {
1516 hitv += 8 + singleobj->spe + ((mon->m_lev - 9) / 2);
1517 } else {
1518 hitv += 8 + singleobj->spe;
1520 if (dam < 1) dam = 1;
1521 if (mon && mon->data == &mons[PM_UTIMA_DESTROYER_OF_XEREN]) dam += rnd(100);
1522 hitu = thitu(hitv, dam, singleobj, (char *)0);
1524 if (hitu && singleobj->opoisoned) {
1525 char onmbuf[BUFSZ], knmbuf[BUFSZ];
1527 strcpy(onmbuf, xname(singleobj));
1528 strcpy(knmbuf, killer_xname(singleobj));
1529 poisoned(onmbuf, A_STR, knmbuf, -10);
1531 if(hitu &&
1532 can_blnd((struct monst*)0, &youmonst,
1533 (uchar)(singleobj->otyp == BLINDING_VENOM ?
1534 AT_SPIT : AT_WEAP), singleobj)) {
1535 blindinc = rnd(25);
1536 if(singleobj->otyp == CREAM_PIE) {
1537 if(!Blind) pline("Yecch! You've been creamed.");
1538 else pline("There's %s sticky all over your %s.",
1539 something,
1540 body_part(FACE));
1541 } else if(singleobj->otyp == BLINDING_VENOM) {
1542 int num_eyes = eyecount(youmonst.data);
1543 /* venom in the eyes */
1544 if(!Blind) pline_The("venom blinds you.");
1545 else Your("%s sting%s.",
1546 (num_eyes == 1) ? body_part(EYE) :
1547 makeplural(body_part(EYE)),
1548 (num_eyes == 1) ? "s" : "");
1551 if (hitu && singleobj->otyp == FAERIE_FLOSS_RHING) {
1552 losexp("a sweet ring of faerie floss", TRUE, FALSE);
1553 } /* This ignores level-drain resistance (not a bug). --Amy */
1555 if (hitu && singleobj->otyp == COLLUSION_KNIFE && !(Race_if(PM_PLAYER_NIBELUNG) && rn2(5))) {
1556 pline("Collusion!");
1557 litroomlite(FALSE);
1559 if (hitu && singleobj->oartifact == ART_CRUCIFIX_OF_THE_MAD_KING && !(Race_if(PM_PLAYER_NIBELUNG) && rn2(5))) {
1560 pline("Collusion!");
1561 litroomlite(FALSE);
1563 if (hitu && singleobj->oartifact == ART_BURGLED_NIGHT_SCYTHE && !(Race_if(PM_PLAYER_NIBELUNG) && rn2(5))) {
1564 pline("Collusion!");
1565 litroomlite(FALSE);
1567 if (hitu && singleobj->oartifact == ART_DARK_CLAYMORE && !(Race_if(PM_PLAYER_NIBELUNG) && rn2(5))) {
1568 pline("Collusion!");
1569 litroomlite(FALSE);
1571 if (hitu && singleobj->otyp == DARKNESS_CLUB && !(Race_if(PM_PLAYER_NIBELUNG) && rn2(5))) {
1572 pline("Collusion!");
1573 litroomlite(FALSE);
1575 if (hitu && singleobj->otyp == JUMPING_FLAMER) {
1576 (void) burnarmor(&youmonst);
1577 if (isevilvariant || !rn2(Race_if(PM_SEA_ELF) ? 1 : issoviet ? 2 : 5)) destroy_item(SCROLL_CLASS, AD_FIRE);
1578 if (isevilvariant || !rn2(Race_if(PM_SEA_ELF) ? 1 : issoviet ? 2 : 5)) destroy_item(SPBOOK_CLASS, AD_FIRE);
1579 if (isevilvariant || !rn2(Race_if(PM_SEA_ELF) ? 1 : issoviet ? 2 : 5)) destroy_item(POTION_CLASS, AD_FIRE);
1581 if (hitu && singleobj->otyp == FLAMETHROWER) {
1582 (void) burnarmor(&youmonst);
1583 if (isevilvariant || !rn2(Race_if(PM_SEA_ELF) ? 1 : issoviet ? 2 : 5)) destroy_item(SCROLL_CLASS, AD_FIRE);
1584 if (isevilvariant || !rn2(Race_if(PM_SEA_ELF) ? 1 : issoviet ? 2 : 5)) destroy_item(SPBOOK_CLASS, AD_FIRE);
1585 if (isevilvariant || !rn2(Race_if(PM_SEA_ELF) ? 1 : issoviet ? 2 : 5)) destroy_item(POTION_CLASS, AD_FIRE);
1587 if (hitu && singleobj->otyp == YITH_TENTACLE) {
1588 increasesanity(rnz(monster_difficulty() + 1));
1590 if (hitu && singleobj->otyp == NASTYPOLE && !rn2(10)) {
1591 badeffect();
1593 if (hitu && singleobj->otyp == DISINTEGRATION_BAR) {
1594 if ((!Disint_resistance || !rn2(StrongDisint_resistance ? 1000 : 100) || (evilfriday && (uarms || uarmc || uarm || uarmu)) ) && !rn2(10)) {
1595 You_feel("like you're falling apart!");
1597 if (uarms) {
1598 /* destroy shield; other possessions are safe */
1599 if (!(EDisint_resistance & W_ARMS) && !(itemsurvivedestruction(uarms, 12)) ) (void) destroy_arm(uarms);
1600 } else if (uarmc) {
1601 /* destroy cloak; other possessions are safe */
1602 if (!(EDisint_resistance & W_ARMC) && !(itemsurvivedestruction(uarmc, 12)) ) (void) destroy_arm(uarmc);
1603 } else if (uarm) {
1604 /* destroy suit */
1605 if (!(EDisint_resistance & W_ARM) && !(itemsurvivedestruction(uarm, 12)) ) (void) destroy_arm(uarm);
1606 } else if (uarmu) {
1607 /* destroy shirt */
1608 if (!(EDisint_resistance & W_ARMU) && !(itemsurvivedestruction(uarmu, 12)) ) (void) destroy_arm(uarmu);
1609 } else {
1610 if (u.uhpmax > 20) {
1611 u.uhpmax -= rnd(20);
1612 if (u.uhp > u.uhpmax) u.uhp = u.uhpmax;
1613 losehp(rnz(100 + level_difficulty()), "click click click click click you died", KILLED_BY);
1615 } else {
1616 u.youaredead = 1;
1617 done(DIED);
1618 u.youaredead = 0;
1624 if (hitu && singleobj->otyp == PETRIFYIUM_BAR) {
1625 if ((!Stone_resistance || (!IntStone_resistance && !rn2(20)) ) &&
1626 !(poly_when_stoned(youmonst.data) && polymon(PM_STONE_GOLEM))) {
1627 if (!Stoned) {
1628 if (Hallucination && rn2(10)) pline("Thankfully you are already stoned.");
1629 else {
1630 Stoned = Race_if(PM_EROSATOR) ? 3 : 7;
1631 u.cnd_stoningcount++;
1632 pline("You start turning to stone!");
1635 sprintf(killer_buf, "petrifyium bar");
1636 delayed_killer = killer_buf;
1641 if (hitu && singleobj->otyp == EGG) {
1642 if ((!Stone_resistance || (!IntStone_resistance && !rn2(20)) ) && !(poly_when_stoned(youmonst.data) && polymon(PM_STONE_GOLEM))) {
1643 if (Hallucination && rn2(10)) pline("Thankfully you are already stoned.");
1644 else if (Stoned) pline("You are already stoned.");
1645 else {
1646 You("start turning to stone!");
1647 Stoned = Race_if(PM_EROSATOR) ? 3 : 7;
1648 u.cnd_stoningcount++;
1649 delayed_killer = "thrown petrifying egg";
1653 stop_occupation();
1654 if (hitu || !range) {
1655 (void) drop_throw(mon, singleobj, hitu, u.ux, u.uy);
1656 break;
1659 if (!range /* reached end of path */
1660 /* missile hits edge of screen */
1661 || !isok(bhitpos.x+dx,bhitpos.y+dy)
1662 /* missile hits the wall */
1663 || (IS_ROCK(levl[bhitpos.x+dx][bhitpos.y+dy].typ) && !IS_FARMLAND(levl[bhitpos.x+dx][bhitpos.y+dy].typ))
1664 /* missile hit closed door */
1665 || closed_door(bhitpos.x+dx, bhitpos.y+dy)
1666 /* missile might hit bars */
1667 || (levl[bhitpos.x+dx][bhitpos.y+dy].typ == IRONBARS &&
1668 hits_bars(&singleobj, bhitpos.x, bhitpos.y, !rn2(5), 0))
1669 /* Thrown objects "sink" */
1670 || IS_SINK(levl[bhitpos.x][bhitpos.y].typ)
1671 || IS_WATERTUNNEL(levl[bhitpos.x][bhitpos.y].typ)
1674 if (!range || IS_SINK(levl[bhitpos.x][bhitpos.y].typ) || IS_WATERTUNNEL(levl[bhitpos.x][bhitpos.y].typ) || !isok(bhitpos.x+dx,bhitpos.y+dy) || !((u.ux == bhitpos.x+dx) && (u.uy == bhitpos.y+dy)) ) {
1675 if (singleobj) /* hits_bars might have destroyed it */
1676 (void) drop_throw(mon, singleobj, 0, bhitpos.x, bhitpos.y);
1677 break;
1681 tmp_at(bhitpos.x, bhitpos.y);
1682 delay_output();
1684 tmp_at(bhitpos.x, bhitpos.y);
1685 delay_output();
1686 tmp_at(DISP_END, 0);
1688 if (blindinc) {
1689 u.ucreamed += blindinc;
1690 make_blinded(Blinded + (long)blindinc, FALSE);
1691 if (!Blind) Your("%s", vision_clears);
1695 #endif /* OVL1 */
1696 #ifdef OVLB
1698 /* Remove an item from the monster's inventory and destroy it. */
1699 void
1700 m_useup(mon, obj)
1701 struct monst *mon;
1702 struct obj *obj;
1704 if (obj->quan > 1L) {
1705 obj->quan--;
1706 obj->owt = weight(obj);
1707 } else {
1708 obj_extract_self(obj);
1709 possibly_unwield(mon, FALSE);
1710 if (obj->owornmask) {
1711 mon->misc_worn_check &= ~(obj->owornmask);
1712 update_mon_intrinsics(mon, obj, FALSE, FALSE);
1714 obfree(obj, (struct obj*) 0);
1718 #endif /* OVLB */
1719 #ifdef OVL1
1721 /* monster attempts ranged weapon attack against player */
1722 void
1723 thrwmu(mtmp)
1724 struct monst *mtmp;
1726 if (DEADMONSTER(mtmp)) return;
1728 struct obj *otmp, *mwep;
1729 xchar x, y;
1730 schar skill;
1731 int multishot;
1732 const char *onm;
1733 int chance;
1735 int polelimit = POLE_LIM;
1736 int tmpwpndmg = 0;
1738 if (mtmp->data == &mons[PM_MECHTNED]) return;
1739 if (mtmp->data == &mons[PM_IMPALAZON]) return;
1740 if (mtmp->data == &mons[PM_MYSTERY_WOMAN]) return;
1741 if (mtmp->data == &mons[PM_SILVER_LADY_PUMP]) return;
1742 if (uarm && uarm->oartifact == ART_RANGED_REDUCER && !rn2(3)) return;
1744 /* Rearranged beginning so monsters can use polearms not in a line */
1745 if (mtmp->weapon_check == NEED_WEAPON || !MON_WEP(mtmp)) {
1746 mtmp->weapon_check = NEED_RANGED_WEAPON;
1747 /* mon_wield_item resets weapon_check as appropriate */
1748 if(mon_wield_item(mtmp) != 0) return;
1751 /* Pick a weapon */
1752 otmp = select_rwep(mtmp, FALSE);
1753 if (!otmp) return;
1755 if ((MON_WEP(mtmp) == otmp) && is_applypole(otmp)) {
1756 int dam, hitv;
1758 if (otmp->otyp == NOOB_POLLAX || otmp->otyp == GREAT_POLLAX) polelimit += 5;
1759 if (otmp->otyp == YITH_TENTACLE) polelimit += 2;
1760 if (otmp->otyp == POLE_LANTERN) polelimit += 10;
1761 if (otmp->otyp == NASTYPOLE) polelimit += 8;
1762 if (otmp->oartifact == ART_ETHER_PENETRATOR) polelimit += 5;
1763 if (otmp->oartifact == ART_FUURKER) polelimit += 6;
1764 if (otmp->otyp == WOODEN_BAR) polelimit += 7;
1765 if (otmp->oartifact == ART_OVERLONG_STICK) polelimit += 12;
1766 /* monsters cheat and ignore the increased minimum range :P */
1768 if (dist2(mtmp->mx, mtmp->my, mtmp->mux, mtmp->muy) > polelimit ||
1769 !couldsee(mtmp->mx, mtmp->my))
1770 return; /* Out of range, or intervening wall */
1772 if (canseemon(mtmp)) {
1773 onm = xname(otmp);
1774 pline("%s thrusts %s.", Monnam(mtmp),
1775 obj_is_pname(otmp) ? the(onm) : an(onm));
1778 tmpwpndmg = dmgval(otmp, &youmonst);
1779 if (tmpwpndmg > 0) {
1780 if (mtmp->m_lev < 2 && u.urmaxlvlUP < 4) tmpwpndmg /= 2;
1781 if (mtmp->m_lev == 2 && u.urmaxlvlUP < 4) {
1782 tmpwpndmg /= 3;
1783 tmpwpndmg *= 2;
1785 if (mtmp->m_lev == 3 && u.urmaxlvlUP < 4) {
1786 tmpwpndmg /= 4;
1787 tmpwpndmg *= 3;
1789 if (mtmp->m_lev == 4 && u.urmaxlvlUP < 4) {
1790 tmpwpndmg /= 5;
1791 tmpwpndmg *= 4;
1793 if (tmpwpndmg < 1) tmpwpndmg = 1; /* fail safe */
1795 dam = tmpwpndmg;
1797 hitv = 3 - distmin(u.ux,u.uy, mtmp->mx,mtmp->my);
1798 if (hitv < -4) hitv = -4;
1799 if (bigmonst(youmonst.data)) hitv++;
1800 hitv += 8 + otmp->spe;
1801 if (dam < 1) dam = 1;
1802 if (mtmp->m_lev >= 3) dam += rnd(mtmp->m_lev / 3);
1804 (void) thitu(hitv, dam, otmp, (char *)0);
1805 stop_occupation();
1806 return;
1809 x = mtmp->mx;
1810 y = mtmp->my;
1811 /* If you are coming toward the monster, the monster
1812 * should try to soften you up with missiles. If you are
1813 * going away, you are probably hurt or running. Give
1814 * chase, but if you are getting too far away, throw.
1816 /* WAC Catch this since rn2(0) is illegal */
1817 chance = (BOLT_LIM - distmin(x,y,mtmp->mux,mtmp->muy) > 0) ?
1818 BOLT_LIM - distmin(x,y,mtmp->mux,mtmp->muy) : 1;
1819 if (!lined_upB(mtmp) || (URETREATING(x,y) && rn2(chance)))
1820 return;
1822 skill = objects[otmp->otyp].oc_skill;
1823 mwep = MON_WEP(mtmp); /* wielded weapon */
1825 if (!(elongation_monster(mtmp->data) || ElongationBug || u.uprops[ELONGATION_BUG].extrinsic || have_elongatedstone()) && mwep && ammo_and_launcher(otmp, mwep) && objects[mwep->otyp].oc_range &&
1826 dist2(mtmp->mx, mtmp->my, mtmp->mux, mtmp->muy) >
1827 objects[mwep->otyp].oc_range * objects[mwep->otyp].oc_range)
1828 return; /* Out of range */
1830 if (!(elongation_monster(mtmp->data) || ElongationBug || u.uprops[ELONGATION_BUG].extrinsic || have_elongatedstone())
1831 && (uarm && uarm->oartifact == ART_SLOW_MISSILES) && (dist2(mtmp->mx, mtmp->my, mtmp->mux, mtmp->muy) > (BOLT_LIM*BOLT_LIM)) )
1832 return; /* Out of range */
1834 /* monsters were throwing darts way across the map, that is, distances of 70+ squares.
1835 * This was obviously not intended; they should just be able to fire sniper rifles at their actual range. --Amy */
1836 if (!(elongation_monster(mtmp->data) || ElongationBug || u.uprops[ELONGATION_BUG].extrinsic || have_elongatedstone()) && !(mwep && ammo_and_launcher(otmp, mwep) && objects[mwep->otyp].oc_range) && dist2(mtmp->mx, mtmp->my, mtmp->mux, mtmp->muy) > ((BOLT_LIM + strongmonst(mtmp->data) ) * (BOLT_LIM + strongmonst(mtmp->data) )) ) return;
1838 /* Multishot calculations */
1839 multishot = 1;
1840 if (((mwep && ammo_and_launcher(otmp, mwep)) || skill == P_DAGGER || skill == P_KNIFE || skill == P_BOOMERANG || skill == -P_BOOMERANG ||
1841 skill == -P_DART || skill == -P_SHURIKEN || skill == P_SPEAR || skill == P_JAVELIN) && !mtmp->mconf) {
1842 /* Assumes lords are skilled, princes are expert */
1843 if (is_prince(mtmp->data)) multishot += 2;
1844 else if (is_lord(mtmp->data)) multishot++;
1846 if (MonsterMultishotBug || u.uprops[MONSTER_MULTISHOT_EFFECT].extrinsic || have_monstermultishotstone()) {
1847 int multishotbonus = (mtmp->m_lev / 3);
1848 if (multishotbonus < 1) multishotbonus = 1; /* fail safe */
1849 multishotbonus = rno(multishotbonus);
1850 multishot += multishotbonus;
1853 /* strong, nasty or high-level monsters can also shoot more --Amy */
1854 if (mtmp->m_lev >= 10 && strongmonst(mtmp->data) && !rn2(3)) multishot++;
1855 if (mtmp->m_lev >= 10 && strongmonst(mtmp->data) && !rn2(9)) multishot++;
1856 if (mtmp->m_lev >= 10 && strongmonst(mtmp->data) && !rn2(27)) multishot++;
1858 if (mtmp->m_lev >= 10 && extra_nasty(mtmp->data) && !rn2(2)) multishot++;
1859 if (mtmp->m_lev >= 10 && extra_nasty(mtmp->data) && !rn2(4)) multishot++;
1860 if (mtmp->m_lev >= 10 && extra_nasty(mtmp->data) && !rn2(8)) multishot++;
1862 if (mtmp->m_lev >= 10 && mtmp->m_lev < 20) multishot += 1;
1863 if (mtmp->m_lev >= 20 && mtmp->m_lev < 30) multishot += rnd(2);
1864 if (mtmp->m_lev >= 30 && mtmp->m_lev < 40) multishot += rnd(3);
1865 if (mtmp->m_lev >= 40 && mtmp->m_lev < 50) multishot += rnd(4);
1866 if (mtmp->m_lev >= 50 && mtmp->m_lev < 60) multishot += rnd(5);
1867 if (mtmp->m_lev >= 60 && mtmp->m_lev < 70) multishot += rnd(6);
1868 if (mtmp->m_lev >= 70 && mtmp->m_lev < 80) multishot += rnd(7);
1869 if (mtmp->m_lev >= 80 && mtmp->m_lev < 90) multishot += rnd(8);
1870 if (mtmp->m_lev >= 90 && mtmp->m_lev < 100) multishot += rnd(9);
1871 if (mtmp->m_lev >= 100) multishot += rnd(10);
1873 /* Elven Craftsmanship makes for light, quick bows */
1874 if (otmp->otyp == ELVEN_ARROW && !otmp->cursed)
1875 multishot++;
1876 if (mwep && mwep->otyp == ELVEN_BOW && !mwep->cursed) multishot++;
1878 if (mwep && mwep->otyp == WILDHILD_BOW && otmp->otyp == ODOR_SHOT) multishot++;
1879 if (mwep && mwep->otyp == COMPOST_BOW && otmp->otyp == FORBIDDEN_ARROW) multishot++;
1881 if (mwep && mwep->otyp == CATAPULT) multishot += rnd(5);
1883 if (mwep && mwep->otyp == HYDRA_BOW) multishot += 2;
1884 if (mwep && mwep->otyp == DEMON_CROSSBOW) multishot += 4;
1885 if (mwep && mwep->otyp == WILDHILD_BOW) multishot += 2;
1887 if (mwep && is_lightsaber(mwep) && mwep->lamplit) { /* djem so monster lightsaber form */
1888 multishot += 1;
1889 if (mtmp->data->geno & G_UNIQ) multishot += 1;
1892 if (otmp && otmp->otyp == RAPID_DART) multishot += 2;
1893 if (otmp && otmp->otyp == NINJA_STAR) multishot += 3;
1894 if (otmp && otmp->otyp == FLAMETHROWER) multishot += 4;
1896 /* 1/3 of object enchantment */
1897 if (mwep && mwep->spe > 1)
1898 multishot += rounddiv(mwep->spe, 3);
1899 /* Some randomness */
1900 if (multishot > 1)
1901 multishot = rnd(multishot);
1902 if (mwep && objects[mwep->otyp].oc_rof && is_launcher(mwep))
1903 multishot += objects[mwep->otyp].oc_rof;
1905 switch (monsndx(mtmp->data)) {
1906 case PM_SPARD:
1907 case PM_IBERIAN_SOLDIER:
1908 multishot += 3;
1909 break;
1910 case PM_BLUE_ARCHER:
1911 multishot += 2;
1912 break;
1913 case PM_RANGER:
1914 case PM_ROCKER:
1915 case PM_GATLING_ARCHER:
1916 multishot++;
1917 break;
1918 case PM_PELLET_ARCHER:
1919 case PM_ECM_ARCHER:
1920 case PM_SHOTGUN_HORROR:
1921 case PM_SHOTGUN_TERROR:
1922 case PM_KOBOLD_PEPPERMASTER:
1923 multishot++;
1924 multishot++;
1925 break;
1926 case PM_BRA_GIANT:
1927 multishot += 5;
1928 break;
1929 case PM_ELPH:
1930 multishot++;
1931 if (otmp->otyp == ELVEN_ARROW && mwep && mwep->otyp == ELVEN_BOW) multishot++;
1932 break;
1933 case PM_ROGUE:
1934 if (skill == P_DAGGER) multishot++;
1935 break;
1936 case PM_TOSSER:
1937 if (skill == P_JAVELIN) multishot++;
1938 break;
1939 case PM_NINJA:
1940 case PM_NINJA_GAIDEN:
1941 case PM_SAMURAI:
1942 if (otmp->otyp == YA && mwep && mwep->otyp == YUMI) multishot++;
1943 if (otmp->otyp == FAR_EAST_ARROW && mwep && mwep->otyp == YUMI) multishot++;
1944 break;
1945 default:
1946 break;
1948 /* racial bonus */
1949 if ((is_elf(mtmp->data) &&
1950 otmp->otyp == ELVEN_ARROW &&
1951 mwep && mwep->otyp == ELVEN_BOW) ||
1952 (is_orc(mtmp->data) &&
1953 otmp->otyp == ORCISH_ARROW &&
1954 mwep && mwep->otyp == ORCISH_BOW))
1955 multishot++;
1957 if (mwep && mwep->otyp == PISTOL_PAIR) multishot *= 2;
1959 /* weaker monsters shouldn't spam you with thousands of arrows --Amy */
1960 if (!rn2(2) && !strongmonst(mtmp->data) && !extra_nasty(mtmp->data) && !(mtmp->data->geno & G_UNIQ) && multishot > 1) multishot -= rnd(multishot / 2);
1962 if ((long)multishot > otmp->quan) multishot = (int)otmp->quan;
1964 /* we don't want monsters to throw their entire stack of daggers if that's what they use in melee --Amy
1965 * also they shouldn't fire the last from a stack of artifact ammo, because they can melee with it */
1966 if ((long)multishot == otmp->quan && (multishot > 1) && ((otmp == MON_WEP(mtmp)) || (otmp->oartifact && !(otmp->oartifact == ART_SIEGFRIED_S_DEATHBOLT)) ) ) {
1967 multishot--;
1968 if (multishot < 1) multishot = 1; /* shouldn't happen */
1971 if (multishot < 1) multishot = 1;
1972 /* else multishot = rnd(multishot); */
1975 if (canseemon(mtmp)) {
1976 char onmbuf[BUFSZ];
1978 if (multishot > 1) {
1979 /* "N arrows"; multishot > 1 implies otmp->quan > 1, so
1980 xname()'s result will already be pluralized */
1981 sprintf(onmbuf, "%d %s", multishot, xname(otmp));
1982 onm = onmbuf;
1983 } else {
1984 /* "an arrow" */
1985 onm = singular(otmp, xname);
1986 onm = obj_is_pname(otmp) ? the(onm) : an(onm);
1988 m_shot.s = (mwep && ammo_and_launcher(otmp,mwep)) ? TRUE : FALSE;
1989 pline("%s %s %s!", Monnam(mtmp),
1990 m_shot.s ? is_bullet(otmp) ? "fires" : "shoots" : "throws",
1991 onm);
1992 m_shot.o = otmp->otyp;
1993 } else {
1995 m_shot.s = (mwep && ammo_and_launcher(otmp,mwep)) ? TRUE : FALSE;
1997 if (flags.soundok && !issoviet) {
1999 /* at least tell the player that something's happening, instead of stupidly stopping input while the off-screen
2000 * projectile is flying (which can make the player think the game hangs when the projectile was fired from
2001 * far away, since it may delay output for several seconds while nothing apparently happens) --Amy */
2002 if (multishot > 1) {
2003 if (is_bullet(otmp)) You_hear("several gunshots.");
2004 else if (m_shot.s) You_hear("rapid shooting sounds.");
2005 else You_hear("multiple flinging sounds.");
2006 } else {
2007 if (is_bullet(otmp)) You_hear("the sound of gunfire.");
2008 else if (m_shot.s) You_hear("a shooting sound.");
2009 else You_hear("a flinging sound.");
2012 m_shot.o = STRANGE_OBJECT; /* don't give multishot feedback */
2015 m_shot.n = multishot;
2016 for (m_shot.i = 1; m_shot.i <= m_shot.n; m_shot.i++)
2017 m_throw(mtmp, mtmp->mx, mtmp->my, sgn(tbx), sgn(tby),
2018 distmin(mtmp->mx, mtmp->my, mtmp->mux, mtmp->muy), otmp);
2019 m_shot.n = m_shot.i = 0;
2020 m_shot.o = STRANGE_OBJECT;
2021 m_shot.s = FALSE;
2023 nomul(0, 0, FALSE);
2026 #endif /* OVL1 */
2027 #ifdef OVLB
2030 spitmu(mtmp, mattk) /* monster spits substance at you */
2031 register struct monst *mtmp;
2032 register struct attack *mattk;
2034 register struct obj *otmp;
2036 if (DEADMONSTER(mtmp)) return 0;
2038 if(mtmp->mcan) {
2040 if(flags.soundok)
2041 pline("A dry rattle comes from %s throat.",
2042 s_suffix(mon_nam(mtmp)));
2043 return 0;
2045 if(lined_up(mtmp)) {
2046 if (issegfaulter && rn2(10)) {
2047 otmp = mksobj(SEGFAULT_VENOM, TRUE, FALSE, FALSE);
2048 } else switch (mattk->adtyp) {
2049 case AD_BLND:
2050 case AD_DRST:
2051 otmp = mksobj(BLINDING_VENOM, TRUE, FALSE, FALSE);
2052 break;
2053 case AD_DRLI:
2054 otmp = mksobj(FAERIE_FLOSS_RHING, TRUE, FALSE, FALSE);
2055 break;
2056 case AD_NAST:
2057 otmp = mksobj(SEGFAULT_VENOM, TRUE, FALSE, FALSE);
2058 break;
2059 case AD_TCKL:
2060 otmp = mksobj(TAIL_SPIKES, TRUE, FALSE, FALSE);
2061 break;
2062 default:
2063 pline("bad attack type in spitmu");
2064 /* fall through */
2065 case AD_ACID:
2066 otmp = mksobj(ACID_VENOM, TRUE, FALSE, FALSE);
2067 break;
2069 if (!otmp) return 0;
2070 otmp->quan = 1;
2071 otmp->owt = weight(otmp);
2073 if(!rn2(BOLT_LIM-distmin(mtmp->mx,mtmp->my,mtmp->mux,mtmp->muy))) {
2074 if (canseemon(mtmp))
2075 pline("%s spits venom!", Monnam(mtmp));
2076 else if (flags.soundok && !issoviet) You_hear("a spitting sound.");
2077 m_throw(mtmp, mtmp->mx, mtmp->my, sgn(tbx), sgn(tby),
2078 distmin(mtmp->mx,mtmp->my,mtmp->mux,mtmp->muy), otmp);
2079 nomul(0, 0, FALSE);
2080 return 0;
2083 return 0;
2086 #endif /* OVLB */
2087 #ifdef OVL1
2090 breamu(mtmp, mattk) /* monster breathes at you (ranged) */
2091 register struct monst *mtmp;
2092 register struct attack *mattk;
2094 if (DEADMONSTER(mtmp)) return 0;
2096 /* if new breath types are added, change AD_ACID to max type */
2097 int typ = (mattk->adtyp == AD_RBRE) ? rnd(AD_SPC2) : mattk->adtyp ;
2099 if (typ < AD_MAGM || typ > AD_SPC2) typ = rnd(AD_SPC2); /* for shambling horrors etc. --Amy */
2101 if(lined_up(mtmp)) {
2103 if(mtmp->mcan) {
2104 if(flags.soundok) {
2105 if(canseemon(mtmp))
2106 pline("%s coughs.", Monnam(mtmp));
2107 else
2108 You_hear("a cough.");
2110 return(0);
2112 if(!mtmp->mspec_used && rn2(3)) {
2114 if((typ >= AD_MAGM) && (typ <= AD_SPC2)) {
2116 /* angband has the infamous "it breathes" deaths --Amy */
2118 if (isangbander && rn2(2) && (rnd( (int)mattk->damn * 6) > u.uhp )) {
2120 u.youaredead = 1;
2122 pline("It breathes"); /* The following --More-- prompt is forced and shall not be disabled --Amy */
2123 display_nhwindow(WIN_MESSAGE, TRUE); /* --More-- */
2124 pline("You have died.");
2126 killer_format = KILLED_BY_AN;
2127 killer = "fatal breath attack";
2128 done(DIED);
2130 u.youaredead = 0;
2132 return(0);
2135 if (isangbander && rn2(2) && (rnd( (int)mattk->damd * 6) > u.uhp )) {
2137 u.youaredead = 1;
2139 pline("It breathes");
2140 display_nhwindow(WIN_MESSAGE, TRUE); /* --More-- */
2141 pline("You have died.");
2143 killer_format = KILLED_BY_AN;
2144 killer = "fatal breath attack";
2145 done(DIED);
2147 u.youaredead = 0;
2149 return(0);
2152 /* In Soviet Russia, no player may ever know anything. Whether it's a dragon breathing at you,
2153 * a gnome trying to shoot you with his crossbow, or a cobra spitting venom... "if you can't see it,
2154 * it doesn't exist". Or rather, "if there was no message about it in SLASH'EM then there may not be one
2155 * here either". Yes, it's unbelievable, but that's what they are thinking. --Amy */
2157 if(canseemon(mtmp))
2158 pline("%s breathes %s!", Monnam(mtmp),
2159 FunnyHallu ? hallubreathwep[rn2(SIZE(hallubreathwep))] : breathwep[typ-1]);
2160 else if (flags.soundok && !issoviet) {
2161 if (isangbander) pline("It breathes.");
2162 else You_hear("an exhaling sound.");
2164 if (mtmp->data == &mons[PM_AUTO_AIM_CHEATAH]) u.uprops[DEAC_REFLECTING].intrinsic += 5;
2166 if (flags.moreforced && !MessagesSuppressed) display_nhwindow(WIN_MESSAGE, TRUE); /* --More-- */
2167 buzz((int) (-20 - (typ-1)), (rn2(2) ? (int)mattk->damn : (int)mattk->damd ),
2168 mtmp->mx, mtmp->my, sgn(tbx), sgn(tby));
2169 nomul(0, 0, FALSE);
2170 /* breath runs out sometimes. Also, give monster some
2171 * cunning; don't breath if the player fell asleep.
2173 if(!rn2(3))
2174 mtmp->mspec_used = 10+rn2(20);
2175 if(typ == AD_SLEE && !Sleep_resistance)
2176 mtmp->mspec_used += rnd(20);
2177 } else pline("Breath weapon %d used", typ-1);
2180 return(1);
2184 /* WAC for doorbusting ONLY (at this point in time) No checks */
2185 boolean
2186 breamspot(mtmp, mattk, ax, ay)
2187 register struct monst *mtmp;
2188 register struct attack *mattk;
2189 xchar ax, ay;
2191 /* if new breath types are added, change AD_ACID to max type */
2192 int typ = (mattk->adtyp == AD_RBRE) ? rnd(AD_SPC2) : mattk->adtyp ;
2194 if (DEADMONSTER(mtmp)) return 0;
2196 if((typ >= AD_MAGM) && (typ <= AD_SPC2)) {
2197 if(canseemon(mtmp))
2198 pline("%s breathes %s!", Monnam(mtmp),
2199 FunnyHallu ? hallubreathwep[rn2(SIZE(hallubreathwep))] : breathwep[typ-1]);
2200 if (flags.moreforced && !MessagesSuppressed) display_nhwindow(WIN_MESSAGE, TRUE); /* --More-- */
2201 /* Do the door first - monster is ON TOP so call direct */
2202 zap_over_floor(mtmp->mx, mtmp->my, (int) (-20 - (typ-1)), NULL);
2203 buzz((int) (-20 - (typ-1)), (rn2(2) ? (int)mattk->damn : (int)mattk->damd ),
2204 mtmp->mx, mtmp->my, ax, ay);
2205 nomul(0, 0, FALSE);
2206 /* breath runs out sometimes. */
2207 if(!rn2(3))
2208 mtmp->mspec_used = 10+rn2(20);
2209 } else impossible("Breath weapon %d used", typ-1);
2210 return(TRUE);
2214 boolean
2215 linedup(ax, ay, bx, by, special)
2216 register xchar ax, ay, bx, by;
2217 boolean special; /* for monsters that can shoot from infinite distance --Amy */
2219 int dx, dy;
2220 tbx = ax - bx; /* These two values are set for use */
2221 tby = ay - by; /* after successful return. */
2223 /* sometimes displacement makes a monster think that you're at its
2224 own location; prevent it from throwing and zapping in that case */
2225 if (!tbx && !tby) return FALSE;
2227 if ((!tbx || !tby || abs(tbx) == abs(tby)) /* straight line or diagonal */
2228 && distmin(tbx, tby, 0, 0) < ((special || ElongationBug || u.uprops[ELONGATION_BUG].extrinsic || have_elongatedstone()) ? 100 : EnglandMode ? 10 : BOLT_LIM) ) {
2229 if ((ax == u.ux && ay == u.uy) ? (boolean) couldsee(bx, by) : clear_path(ax, ay, bx, by))
2230 return TRUE;
2231 /* don't have line of sight, but might still be lined up
2232 if that lack of sight is due solely to boulders */
2233 dx = sgn(ax - bx), dy = sgn(ay - by);
2234 do {
2235 /* <bx,by> is guaranteed to eventually converge with <ax,ay> */
2236 bx += dx, by += dy;
2237 if ((IS_ROCK(levl[bx][by].typ) && !IS_FARMLAND(levl[bx][by].typ)) || IS_WATERTUNNEL(levl[bx][by].typ) || closed_door(bx, by))
2238 return FALSE;
2239 } while (bx != ax || by != ay);
2240 /* reached target position without encountering obstacle */
2241 return TRUE;
2244 /*if((!tbx || !tby || abs(tbx) == abs(tby))*/ /* straight line or diagonal */
2245 /* && distmin(tbx, tby, 0, 0) < ((ElongationBug || u.uprops[ELONGATION_BUG].extrinsic || have_elongatedstone()) ? 100 : EnglandMode ? 10 : BOLT_LIM)) {
2246 if(ax == u.ux && ay == u.uy) return((boolean)(couldsee(bx,by)));
2247 else if(clear_path(ax,ay,bx,by)) return TRUE;
2249 return FALSE;
2252 boolean
2253 linedupB(ax, ay, bx, by) /* without the distance check --Amy */
2254 register xchar ax, ay, bx, by;
2256 int dx, dy;
2257 tbx = ax - bx; /* These two values are set for use */
2258 tby = ay - by; /* after successful return. */
2260 /* sometimes displacement makes a monster think that you're at its
2261 own location; prevent it from throwing and zapping in that case */
2262 if (!tbx && !tby) return FALSE;
2264 if ((!tbx || !tby || abs(tbx) == abs(tby)) /* straight line or diagonal */
2266 if ((ax == u.ux && ay == u.uy) ? (boolean) couldsee(bx, by) : clear_path(ax, ay, bx, by))
2267 return TRUE;
2268 /* don't have line of sight, but might still be lined up
2269 if that lack of sight is due solely to boulders */
2270 dx = sgn(ax - bx), dy = sgn(ay - by);
2271 do {
2272 /* <bx,by> is guaranteed to eventually converge with <ax,ay> */
2273 bx += dx, by += dy;
2274 if ((IS_ROCK(levl[bx][by].typ) && !IS_FARMLAND(levl[bx][by].typ)) || IS_WATERTUNNEL(levl[bx][by].typ) || closed_door(bx, by))
2275 return FALSE;
2276 } while (bx != ax || by != ay);
2277 /* reached target position without encountering obstacle */
2278 return TRUE;
2281 /*if((!tbx || !tby || abs(tbx) == abs(tby)))*/ /* straight line or diagonal */
2283 if(ax == u.ux && ay == u.uy) return((boolean)(couldsee(bx,by)));
2284 else if(clear_path(ax,ay,bx,by)) return TRUE;
2286 return FALSE;
2289 boolean
2290 lined_up(mtmp) /* is mtmp in position to use ranged attack? */
2291 register struct monst *mtmp;
2293 return(linedup(mtmp->mux,mtmp->muy,mtmp->mx,mtmp->my, (elongation_monster(mtmp->data)) ));
2296 boolean
2297 lined_upB(mtmp) /* is mtmp in position to use ranged attack? */
2298 register struct monst *mtmp;
2300 return(linedupB(mtmp->mux,mtmp->muy,mtmp->mx,mtmp->my));
2303 #endif /* OVL1 */
2304 #ifdef OVL0
2306 /* Check if a monster is carrying a particular item.
2308 struct obj *
2309 m_carrying(mtmp, type)
2310 struct monst *mtmp;
2311 int type;
2313 register struct obj *otmp;
2315 for(otmp = mtmp->minvent; otmp; otmp = otmp->nobj)
2316 if(otmp->otyp == type)
2317 return(otmp);
2318 return((struct obj *) 0);
2321 /* TRUE iff thrown/kicked/rolled object doesn't pass through iron bars */
2322 boolean
2323 hits_bars(obj_p, x, y, always_hit, whodidit)
2324 struct obj **obj_p; /* *obj_p will be set to NULL if object breaks */
2325 int x, y;
2326 int always_hit; /* caller can force a hit for items which would fit through */
2327 int whodidit; /* 1==hero, 0=other, -1==just check whether it'll pass thru */
2329 struct obj *otmp = *obj_p;
2330 int obj_type = otmp->otyp;
2331 boolean hits = always_hit;
2333 if (!hits)
2334 switch (otmp->oclass) {
2335 case WEAPON_CLASS:
2337 int oskill = objects[obj_type].oc_skill;
2339 hits = (oskill != -P_BOW && oskill != -P_CROSSBOW &&
2340 oskill != -P_DART && oskill != -P_SHURIKEN &&
2341 (oskill != -P_FIREARM || obj_type == ROCKET || obj_type == MINI_NUKE) &&
2342 oskill != P_SPEAR && oskill != P_JAVELIN &&
2343 oskill != P_KNIFE); /* but not dagger */
2344 break;
2346 case ARMOR_CLASS:
2347 hits = (objects[obj_type].oc_armcat != ARM_GLOVES);
2348 break;
2349 case TOOL_CLASS:
2350 hits = (obj_type != SKELETON_KEY &&
2351 obj_type != SECRET_KEY &&
2352 obj_type != LOCK_PICK &&
2353 obj_type != HAIRCLIP &&
2354 obj_type != CREDIT_CARD &&
2355 obj_type != DATA_CHIP &&
2356 obj_type != TALLOW_CANDLE &&
2357 obj_type != WAX_CANDLE &&
2358 obj_type != JAPAN_WAX_CANDLE &&
2359 obj_type != OIL_CANDLE &&
2360 obj_type != UNAFFECTED_CANDLE &&
2361 obj_type != SPECIFIC_CANDLE &&
2362 obj_type != __CANDLE &&
2363 obj_type != NATURAL_CANDLE &&
2364 obj_type != UNSPECIFIED_CANDLE &&
2365 obj_type != GENERAL_CANDLE &&
2366 obj_type != LENSES &&
2367 obj_type != RADIOGLASSES &&
2368 obj_type != SHIELD_PATE_GLASSES &&
2369 obj_type != BOSS_VISOR &&
2370 obj_type != NIGHT_VISION_GOGGLES &&
2371 obj_type != TIN_WHISTLE &&
2372 obj_type != GRASS_WHISTLE &&
2373 obj_type != MAGIC_WHISTLE);
2374 break;
2375 case ROCK_CLASS: /* includes boulder */
2376 if (obj_type != STATUE ||
2377 mons[otmp->corpsenm].msize > MZ_TINY) hits = TRUE;
2378 break;
2379 case FOOD_CLASS:
2380 if (obj_type == CORPSE &&
2381 mons[otmp->corpsenm].msize > MZ_TINY) hits = TRUE;
2382 else
2383 hits = (obj_type == MEAT_STICK ||
2384 obj_type == HUGE_CHUNK_OF_MEAT);
2385 break;
2386 case SPBOOK_CLASS:
2387 case WAND_CLASS:
2388 case BALL_CLASS:
2389 case CHAIN_CLASS:
2390 hits = TRUE;
2391 break;
2392 default:
2393 break;
2396 if (hits && whodidit != -1) {
2397 if (whodidit ? hero_breaks(otmp, x, y, FALSE) : breaks(otmp, x, y))
2398 *obj_p = otmp = 0; /* object is now gone */
2399 /* breakage makes its own noises */
2400 else if (obj_type == BOULDER || obj_type == HEAVY_IRON_BALL)
2401 pline("Whang!");
2402 else if (otmp->oclass == COIN_CLASS ||
2403 objects[obj_type].oc_material == MT_GOLD ||
2404 objects[obj_type].oc_material == MT_SILVER)
2405 pline("Clink!");
2406 else
2407 pline("Clonk!");
2410 return hits;
2413 /* Find a target for a ranged attack. From dnethack (thanks Chris_ANG). Here in SLEX, it's meant to be specifically for
2414 * hostile monsters attacking your pets at range. */
2415 struct monst *
2416 mfind_target(mtmp, force_linedup)
2417 struct monst *mtmp;
2418 boolean force_linedup;
2420 if (DEADMONSTER(mtmp)) return (struct monst *)0;
2422 int dir, origdir = -1;
2423 int x, y, dx, dy, tbx, tby;
2425 int i;
2427 struct monst *mat, *mret = (struct monst *)0, *oldmret = (struct monst *)0;
2428 struct monst *mtmp2;
2430 if (mtmp->mpeaceful || mtmp->mtame) return 0;
2432 /* things that shouldn't attack pets go here --Amy */
2433 if (mtmp->data == &mons[PM_MOLDOUX__THE_DEFENCELESS_MOLD]) return 0;
2434 if (mtmp->isshk || mtmp->isgd || mtmp->ispriest || mtmp->data->mlet == S_TROVE) return 0;
2436 struct obj *mrwep = select_rwep(mtmp, TRUE); /* may use polearm even when far from the player --Amy */
2438 for (mtmp2 = fmon; mtmp2; mtmp2 = mtmp2->nmon) {
2439 if(mtmp == mtmp2) continue;
2440 if (mtmp2 && u.usteed && mtmp2 == u.usteed) continue; /* steeds are fragile enough already... --Amy */
2441 if (mtmp2->mtame && (mlined_up(mtmp, mtmp2, FALSE) || attacktype(mtmp->data, AT_GAZE) || attacktype(mtmp->data, AT_WEAP)) &&
2442 ((attacktype(mtmp->data, AT_GAZE) && !mtmp->mcan)
2443 || (attacktype(mtmp->data, AT_MAGC) && !mtmp->mcan && distmin(mtmp2->mx,mtmp2->my,mtmp->mx,mtmp->my) < BOLT_LIM)
2444 || (attacktype(mtmp->data, AT_WEAP) && mrwep && distmin(mtmp2->mx,mtmp2->my,mtmp->mx,mtmp->my) < BOLT_LIM)
2445 || (attacktype(mtmp->data, AT_BREA) && !mtmp->mcan && distmin(mtmp2->mx,mtmp2->my,mtmp->mx,mtmp->my) < BOLT_LIM)
2446 || (attacktype(mtmp->data, AT_BEAM) && distmin(mtmp2->mx,mtmp2->my,mtmp->mx,mtmp->my) < BOLT_LIM)
2447 || (attacktype(mtmp->data, AT_SPIT) && !mtmp->mcan && distmin(mtmp2->mx,mtmp2->my,mtmp->mx,mtmp->my) < BOLT_LIM)) )
2449 if (!mret) {
2451 if (PethateEffect || u.uprops[PETHATE_EFFECT].extrinsic || have_pethatestone()) mret = mtmp2;
2453 if ((!rn2((mtmp2->m_lev > 40) ? 3 : (mtmp2->m_lev > 30) ? 5 : (mtmp2->m_lev > 20) ? 10 : 20) && !(u.usteed && mtmp2 == u.usteed && !rn2(10)) && (!rn2(5) || mtmp2->mcanmove) && (!rn2(5) || (mtmp2->mhpmax > 5 && mtmp2->mhp > (mtmp2->mhpmax / 5) )) && (mtmp2->m_lev > rn2(6)) && (u.petattackenemies >= 0) && ((mtmp->m_lev - mtmp2->m_lev) < (2 + rn2(5)) ) ) || attacktype(mtmp2->data, AT_EXPL) || mtmp->mfrenzied) mret = mtmp2;
2458 if (mret != (struct monst *)0) {
2460 if(!mlined_up(mtmp, mret, FALSE) && !attacktype(mtmp->data, AT_GAZE) && !attacktype(mtmp->data, AT_WEAP)) {
2461 tbx = tby = 0;
2462 } else return mret;
2465 /* Nothing lined up? */
2466 tbx = tby = 0;
2467 return (struct monst *)0;
2470 boolean
2471 mlined_up(mtmp, mdef, breath) /* From dnethack: is mtmp in position to use ranged attack? */
2472 register struct monst *mtmp;
2473 register struct monst *mdef;
2474 register boolean breath;
2476 struct monst *mat;
2478 if (DEADMONSTER(mtmp)) return 0;
2479 if (DEADMONSTER(mdef)) return 0;
2481 boolean lined_up = linedup(mdef->mx,mdef->my,mtmp->mx,mtmp->my, FALSE);
2483 int dx = sgn(mdef->mx - mtmp->mx),
2484 dy = sgn(mdef->my - mtmp->my);
2486 int x = mtmp->mx, y = mtmp->my;
2488 int i = 10; /* arbitrary */
2490 /* No special checks if confused - can't tell friend from foe */
2491 if (!lined_up || mtmp->mconf || !mtmp->mtame) return lined_up;
2493 /* Check for friendlies in the line of fire. */
2494 for (; !breath || i > 0; --i)
2496 x += dx;
2497 y += dy;
2498 if (!isok(x, y)) break;
2500 if (x == u.ux && y == u.uy)
2501 return FALSE;
2503 mat = m_at(x, y);
2504 if (mat)
2506 if (!breath && mat == mdef) return lined_up;
2508 /* Don't hit friendlies - since this is used by hostile monsters, other hostile monsters == friendly */
2509 if (!mat->mtame && !mat->mpeaceful) return FALSE;
2513 return lined_up;
2517 #endif /* OVL0 */
2519 /*mthrowu.c*/